Reproductor de Secuencias
Un único motor asíncrono genérico para todo flujo ordenado de varios pasos — avisos de tutorial, intros de jefe, cambios de fase — reproducidos por el mismo servicio, declarativo en lugar de corrutinas anidadas.
Para qué sirve este sistema
La mayoría de proyectos Unity necesitan orquestar flujos ordenados de varios pasos: mostrar un aviso, esperar, resaltar algo, esperar otra vez, devolver el control. Ya sea una secuencia de tutorial, una introducción de jefe o un momento de gameplay guionizado, el problema de fondo es el mismo: ejecutar una lista de etapas en orden y esperar a que termine antes de devolver el control a quien llamó.
Serenity lo resuelve una sola vez con ISequencePlayerService, un orquestador asíncrono genérico en el namespace Serenity.SequencePlayer. No sabe nada de cinemáticas, diálogos ni ningún otro dominio: solo sabe reproducir una lista ordenada de etapas y esperar el resultado, dejando cada decisión de vocabulario al vertical que se apoye encima.
El problema en Unity
Sin un motor compartido, cada flujo coreografiado acaba siendo su propia corrutina o máquina de estados. Un paso de tutorial, una intro de jefe y un evento guionizado se implementan de tres formas distintas, se prueban de tres formas distintas y se depuran de tres formas distintas. La cancelación, el manejo de errores y el logging se copian y pegan o se omiten. Los puntos de llamada dependen de MonoBehaviours concretos en lugar de interfaces estables.
El coste real es el mantenimiento. Un solo cambio de diseño — añadir un paso, reordenar una fase — toca varias implementaciones. Un motor que cablea su vocabulario de etapas lo empeora: cada nuevo tipo de flujo o fuerza un miembro nuevo en un enum compartido o queda directamente descartado.
Cómo lo aborda Serenity
ISequencePlayerService expone dos sobrecargas de PlayAsync: una que acepta una clave de texto y resuelve la definición en runtime, y otra que acepta directamente una instancia de ISequenceDefinition. Ambas devuelven una Task esperable, así que quien llama puede programar una secuencia, esperarla y continuar con la lógica de juego en una sola línea. Cada ISequenceDefinition contiene un IReadOnlyList ordenado de unidades ISequenceStage; las etapas que necesitan una duración explícita implementan ITimedSequenceStage, que añade una propiedad DurationSeconds.
ISequenceStage ya no lleva un enum de etapas cerrado y propiedad del motor. Su miembro Kind es una cadena de texto plana que el motor nunca interpreta: existe únicamente para que un vertical construido sobre el motor defina su propio vocabulario de etapas y ramifique sobre él. Un sistema de tutoriales puede usar valores de Kind como «Highlight» o «WaitForInput» sin tocar jamás el código del motor, y el Reproductor de Cinemáticas — el vertical cinemático construido sobre este mismo motor — hace lo propio con sus nombres de etapa cinemáticos.
Cómo encaja en Serenity
El namespace SequencePlayer sigue la estructura por capas de Serenity. La capa de Aplicación contiene ISequencePlayerService, la interfaz de factoría ISequencePlayerServiceFactory, ISequencePlayerSettings y los contratos ISequenceDefinition e ISequenceStage — deliberadamente libres de cualquier tipo de etapa específico de dominio. La capa de Infraestructura aporta la implementación Unity; la capa de Instalación lo conecta todo a través de la pipeline de inicialización de Serenity para que los consumidores solo vean interfaces.
El Reproductor de Secuencias coopera con el sistema de Feedback para efectos de pantalla, con el Reproductor de música para arrancar o parar pistas en etapas concretas, con Game Mode para señalar que hay una secuencia guionizada activa y que otros sistemas puedan reaccionar, y con el Event Dispatcher para publicar señales de ciclo de vida de etapa que la interfaz o la analítica puedan observar.
Flujo de trabajo práctico
- Define tu secuencia como un ScriptableObject que implemente ISequenceDefinition y registra su clave en ISequencePlayerSettings.
- Implementa cada etapa como una clase que implemente ISequenceStage o ITimedSequenceStage, dando a Kind un valor de texto con sentido para tu propio sistema.
- Deja que el instalador registre ISequencePlayerService a través de la pipeline de inicialización.
- Inyecta ISequencePlayerService en cualquier punto de llamada que necesite orquestar un flujo de varios pasos.
- Llama a PlayAsync con una clave de texto o una instancia de definición y espera el resultado: el motor reproduce las etapas ordenadas y devuelve el control cuando termina la última.
- Usa CancellationToken para abortar a mitad de secuencia al descargar una escena o cambiar de estado de juego sin dejar el motor en un estado inconsistente.
Qué incluye
- ISequencePlayerService con dos sobrecargas de PlayAsync — reproducir por clave de texto o por instancia de ISequenceDefinition
- ISequenceDefinition con un IReadOnlyList ordenado de unidades ISequenceStage para la orquestación en runtime
- ITimedSequenceStage que extiende ISequenceStage con DurationSeconds para la ejecución de etapas por tiempo
- ISequenceStage.Kind como una cadena plana y agnóstica al motor, para que los verticales definan su propio vocabulario de etapas en lugar de extender un enum compartido
- ISequencePlayerSettings exponiendo DefinitionIds para el registro desde el inspector
- Interfaz de factoría ISequencePlayerServiceFactory para implementaciones intercambiables
- Soporte de CancellationToken de extremo a extremo para que las secuencias aborten limpiamente en transiciones de escena o cambios de estado
- Una base estable para verticales de dominio — el Reproductor de Cinemáticas se distribuye como el vertical cinemático construido sobre este mismo motor
Cuándo usarlo
- Flujos de tutorial que deben ejecutar una lista ordenada de avisos, resaltados y pausas antes de devolver el control.
- Introducciones de jefe, cambios de fase o momentos de gameplay guionizados que necesitan ejecutarse como una lista ordenada de pasos.
- Juegos donde el mismo patrón de coreografía de varios pasos se repite en contextos distintos y quieres un motor, no N corrutinas.
- Bases de código que necesitan esperar a que una secuencia termine antes de disparar la siguiente transición de estado, sin atar a quien llama a un conjunto fijo de tipos de etapa.
Sistemas relacionados
Usa Serenity cuando quieras un único motor de orquestación asíncrona para todo flujo ordenado de tu proyecto, con un vocabulario de etapas que sigue siendo tuyo en lugar de venir cocido en el framework.
English
Español
Català