Registro de cambios

Últimas actualizaciones y mejoras de Serenity.

Volver al inicio

1.1.0 — Audio posicional y por prioridad, colas de loop musical, bucles de efectos de mixer, menús lazy y compuerta de input por GameMode

Breaking Changes

  • SpawnPose ya no expone los siete campos float planos (PositionX/Y/Z, RotationX/Y/Z/W). Ahora está respaldado por Position (System.Numerics.Vector3) y Rotation (System.Numerics.Quaternion). La construcción no se ve afectada — el constructor de siete float y FromPosition(x, y, z) se mantienen — pero el código que leía los campos float individuales ahora debe leer pose.Position.* / pose.Rotation.*.

Añadido

  • Compuerta de input principal como GameMode — un valor PrimaryInputGate en el enum GameMode permite que el prompt de input principal reutilice la maquinaria existente de señales de transición de entrada/salida por modo. El almacenamiento serializado, la recuperación y las listas reordenables de entrada/salida en el inspector se generan automáticamente para el nuevo modo.
  • Loops musicales conservando la colaStartTime, EndTime, TailPreservingLoop, TailFadeOutDuration y TailFadeOutCurve en IMusicTrackDefinition / MusicTrack / UnityMusicTrackDefinition. Una segunda voz transporta la cola de reverb/ambiente de la pasada anterior a través de la unión del loop, programada con precisión de muestra mediante AudioSettings.dspTime / PlayScheduled, de forma que el loop nunca produzca clicks. Los puntos de loop se definen como códigos de tiempo HH:MM:SS:MMM o en términos de DAW — tempo, compás, barra de inicio/fin — mediante MusicBarTimeCalculator; el fade de la cola sigue una curva Lineal/Exponencial/Logarítmica/S-Curve/Custom.
  • Reproducción de audio posicional — objeto de valor AudioWorldPosition y PlaybackPosition opcional en AudioPlayerPlayClipInput; un clip reproducido con posición se reproduce en 3D en ese punto, y sin posición permanece en 2D. Funciona tanto desde una llamada directa al caso de uso como desde una señal PlayAudioClip, sin cambios en la firma del gateway/servicio.
  • Asignación por prioridad de sonidos — cuando el pool de AudioSource está lleno, un clip puede tomar el control de un sonido en reproducción de menor prioridad en lugar de ser descartado. Esto se gobierna mediante Priority / PriorityPolicy / CanBeReplaced por clip y un AudioPriorityCandidateSelector (AudioPriorityPolicy: IgnoreIfNoSourceAvailable / ReplaceLowerPriority / ReplaceLowerOrEqualPriority / AlwaysReplace). La semántica de prioridad de Serenity — cuanto más alto, más importante — se mapea a la prioridad invertida de AudioSource.priority de Unity únicamente en el límite con Unity.
  • Herramienta de autoría de AudioMixer Effect Loop (Tools ▸ Serenity ▸ Audio ▸ Create Audio Mixer Effect Loop) — crea un grupo de mixer con una cadena Receive → effects → Attenuation y un asset reutilizable UnitySoundMixerEffectLoopDefinition que lo describe.
  • Ventana de sincronización de Effect Loops (Tools ▸ Serenity ▸ Audio ▸ Sync Effect Loops) — reconcilia el AudioMixer y SoundMixerSettings con las definiciones de effect-loop del proyecto: crea un Send por cada source hacia el Receive del loop, lo expone como {Source}_{Loop}_Send y registra la definición. Es idempotente y aditiva.
  • Selección de grupos source en la herramienta de creación — permite elegir qué grupos hermanos alimentan el loop, con Select All / None.
  • Scripts de acciones enable/disable autogenerados — para cada grupo source seleccionado, genera un par de acción/señal Enable + Disable de EventDispatcher — reutilizando el generador compartido de scripts de acciones — ya preconfigurado para aplicar/limpiar el loop en ese grupo, escrito en una carpeta Events configurable.
  • Aplicar/limpiar effect-loops en runtime: ISoundMixerService.ApplyEffectLoop / ClearEffectLoop, SoundMixerApplyEffectLoopSignal / SoundMixerClearEffectLoopSignal, sus casos de uso, DTOs solo de intención y un SoundMixerEffectLoopRouteResolver puro e independiente del motor.
  • UnitySoundMixerEffectLoopDefinition / UnitySoundMixerEffectLoopSource ScriptableObjects con inspector personalizado, además de un registro EffectLoops en SoundMixerSettings.
  • AudioMixerYamlReader solo para editor — lee la estructura de .mixer — y AudioMixerEffectLoopReflectionAdapter — aísla la API interna UnityEditor.Audio detrás de una única clase.
  • Modo de instanciación por menúMenuInstantiationMode (PreloadOnStartup / LazyOnFirstOpen) en IMenuSettingsDefinition y UnityMenuSettingsDefinition, editable bajo una sección Advanced en el inspector de configuración del menú.
  • Pipeline de instanciación lazy de menús: IMenuInstanceGate, MenuLifecycleResolver, EnsuringMenuTransitionateToView, UnityMenuLazyBuildContext, UnityMenuLazyRegistration y IUnityMenuViewInstanceFactory / UnityMenuViewInstanceFactory.
  • Señales de transición de salida por modoIGameModeSettingsDefinition.GetExitSignalsForGameMode; el inspector de configuración de GameMode ahora muestra listas reordenables separadas de señales de entrada/salida por modo.
  • Pausa durante la carga de escena — ajuste PauseDuringSceneLoad de GameMode — activado por defecto — con un toggle en el editor de settings, que congela el reloj del juego mientras se carga la escena aditiva de gameplay y lo restaura — mediante try/finally — cuando finaliza la carga, evitando que los objetos recién instanciados simulen por detrás del overlay de carga.
  • Generación de configuración en la primera ejecución — en una instalación nueva, el idioma detectado del sistema operativo/navegador ahora se persiste en gameSettings.cfg en el momento de la detección — standalone mediante UnitySystemConfigurationSnapshotStore; WebGL/ResourcesOnly mediante SerenityFallbackLocalizationService — protegido por una comprobación de existencia del archivo para preservar la preferencia guardada de jugadores que ya vuelven.

Cambiado

  • SpawnPose ahora está respaldado por System.Numerics Vector3 Position + Quaternion Rotation — sustituyendo los siete float planos —, siguiendo el patrón de objeto de valor RailNodePosition de GameRail; se mantiene como C# puro, sin dependencia del motor. UnityWaveService lee pose.Position.* / pose.Rotation.*. Ver Breaking Changes.
  • UnityAudioPlayerService.ApplyPlaybackPlacement ahora es la única fuente de verdad para AudioSource.spatialBlend — con posición → 1 y el emitter se mueve allí; sin posición → 0 y el emitter se deja en su sitio —; ApplyClipToSource ya no aplica el spatial blend del clip.
  • UnityGameModeService despacha las señales del modo salido después de OnExitMode, reflejando el comportamiento existente de las señales de entrada; entrar en PrimaryInputGate dispara sus señales de entrada y salir de él dispara sus señales de salida mediante el mismo dispatch de SetMode.
  • El pause mixer effect loop ahora se controla mediante señales de entrada/salida de GameMode — Enable al entrar en Pause, Disable al salir de Pause — en lugar de clases de acción dedicadas.
  • UnityMenuService construye los menús LazyOnFirstOpen al mostrarlos por primera vez — cacheados y reutilizados —; los menús PreloadOnStartup siguen siendo eager. Los menús iniciales y de pausa configurados como lazy se tratan como preload para evitar tirones en la primera apertura. El comportamiento por defecto no cambia — PreloadOnStartup sigue siendo el valor por defecto.
  • UnitySoundMixerSettingsEditor ahora lee los parámetros expuestos en vivo desde el AudioMixer en memoria — se actualiza automáticamente mientras editas, sin necesidad de guardar — y etiqueta la lista de definiciones registradas de forma diferenciada respecto al encabezado de la sección.
  • Las definiciones de effect-loop usan un único DefaultWet normalizado — dry es su complemento, 1 - wet —, mostrado como un slider "Dry/Wet"; la herramienta de creación acepta carpetas de destino separadas para Media y Events.
  • El nivel de salida del loop se trata como un trim estático del mixer — no como un parámetro runtime expuesto —; el Send del source sigue el nivel actual del grupo source.
  • UnityYamlUtils se mantuvo como helper YAML genérico — todo el conocimiento específico de AudioMixer YAML se movió al módulo SoundMixer.

Features

  • El prompt de selección de dispositivo ahora es un GameMode observable (PrimaryInputGate) que dispara efectos secundarios mediante señales de entrada/salida sin transicionar los modos de juego por sí mismo — al seleccionar dispositivo emite OnPrimarySelected y la composition root despacha EnterMenuSignal, permitiendo que la acción EnterMenu cambie el modo.
  • La música puede hacer loop entre puntos de inicio/fin definidos mientras una segunda voz transporta la cola de reverb de la pasada anterior a través de la unión, con un fade-out de cola acotado y definido por curva — una duración de 0 corta limpiamente en el punto de loop.
  • Los sonidos pueden reproducirse en una posición del mundo — 3D — y pueden reclamar un slot ocupado del pool a un sonido de menor prioridad en lugar de ser descartados.
  • Un effect loop puede ser creado, cableado, registrado y activado/desactivado desde gameplay — por ejemplo, un low-pass/reverb de pausa sobre Music — de extremo a extremo desde el editor, sin escribir a mano routing ni scripts de acciones.
  • Los menús pueden optar por creación lazy en la primera apertura, reduciendo el trabajo de arranque, mientras se conserva el arranque eager para los menús que lo necesitan.
  • Los modos de juego pueden ejecutar efectos secundarios mediante señales tanto al entrar como al salir de un modo.

Corregido

  • Los cambios de valor de menú ahora se aplican a la opción que realmente ha cambiado — no a la actualmente seleccionada — y resuelven la opción seleccionada por su GetIndex() lógico en lugar de por su posición en la jerarquía, corrigiendo valores de sliders entrelazados donde dos opciones compartían un mismo UiOptionValue — por ejemplo, master/ambient.
  • ISoundMixerService ahora está registrado en el ServiceLocator runtime, por lo que las acciones de EventDispatcher pueden resolverlo.
  • Los GUIDs de nivel de mezcla de Send por source se preasignan cuando se crea el Send, por lo que exponer el nivel de Send de cada source ahora funciona correctamente.
  • Se eliminaron referencias [SerializeReference] colgantes a tipos de señales de acción eliminados en assets de ejemplo — un tipo managed desconocido estaba anulando las otras señales válidas al entrar en Play.

Eliminado

  • Clases redundantes EnablePauseMixerEffectLoopAction / DisablePauseMixerEffectLoopAction y el asset de ejemplo PauseEffectLoop — reemplazados por señales de salida de GameMode y el generador de scripts de acciones.
  • Un mapping erróneo de SoundMixerSettings (Music_SucutruleLoop_SendAudio_MasterVolume) que referenciaba un parámetro expuesto del mixer inexistente.

Infraestructura

  • Añadidos tests para el route resolver de SoundMixer effect-loop, effect loop, installer, casos de uso y cobertura.
  • Añadidos tests para el resolver de lifecycle de Menu, el caso de uso ensure-transition y el enum de modo de instanciación de menú.
  • Añadidos tests para el music bar/time calculator, fade-curve evaluator y getters de music-track; audio world-position y placement; selección de candidatos por prioridad de audio y prioridad de clips; construcción de SpawnPose; y las acciones/señales de primary-input-gate de GameMode.

1.0.12 — Soporte WebGL, tema Serenity y localización en runtime

Añadido

  • Tema Serenity — un nuevo tema de UI completo con un conjunto completo de componentes (Background, Title, Label, Input, Dropdown, Selector, Slider, Toggle, Submit, Modal, PrimaryInputPrompt, Highlight), incluyendo animator controllers para el bucle de color del highlight y las transiciones de mostrar/ocultar modales.
  • Soporte para builds WebGL — el primer target de compilación WebGL para Serenity.
  • Herramientas de exportación de recursos para WebGLSerenityWebGLResourcesExporter, SerenityWebGLResourcesCleaner, SerenityWebGLResourcesValidator, SerenityWebGLResourcesPaths y SerenityWebGLExportManifest para exportar assets de Serenity al árbol Resources del consumidor para builds WebGL.
  • Fallback de localización en runtimeSerenityFallbackLocalizationService carga JSON por cada par (tabla, locale) desde Resources y responde al nuevo ILocalizationService.TryTranslate(key, out value), permitiendo traducción y cambio de idioma en vivo en modo ResourcesOnly (WebGL).
  • Barra de progreso de carga por tema — un slot LoadingProgressTemplate en los componentes del tema de UI y una variante de prefab LoadingBar para cada tema (Default, Alternative, Alternative2, Animated, Animated2, Futuristic, Serenity, Writings).
  • Enum SerenityAssetLoadingMode e interfaces/implementaciones IAssetLoadingModeProvider / UnitySerenityAssetLoadingModeProvider para seleccionar cómo se cargan los assets (Addressables vs. solo Resources).
  • Evento ILocalizationService.GameLanguageChanged, disparado cuando realmente cambia el valor del idioma.
  • Comando de menú en el editor (Serenity ▸ UI ▸ Generate LoadingProgress Prefabs) que genera las variantes de prefab de barra de carga por tema y las conecta con las definiciones de tema.
  • Campo "Loading Progress Prefab" en el inspector de la definición del tema de UI.
  • Familia tipográfica Inter (pesos variables y estáticos con assets SDF) e imágenes de soporte (WhiteBackground, square-roundborder).

Cambiado

  • El overlay de carga de gameplay ahora construye su barra de progreso a partir de LoadingProgressTemplate, recurriendo a SlideableTemplate cuando no hay un prefab dedicado asignado.
  • UnityUiTMP_TextLocalizationUpdaterComponent ahora llama a TryTranslate en modo fallback, cachea la clave original de localización entre cambios de idioma y la vuelve a capturar cuando el texto mostrado difiere de la última traducción.
  • UnityLocalizationService mantiene GameLanguageChanged como no-op, delegando el refresco en la propia cadena OnSelectedLocaleChanged de Unity Localization.
  • Corregido el comportamiento de UnityPrimaryInputPromptView para builds WebGL.
  • InitializationPipelineService, UnityCutscenePlayerService, ReflectionCallTask, AddressablesAssetLocator, UnityAddressableUtils, UnityAssetUtils, AudioMixerDependencyCache y UnityMainThreadDispatcher actualizados para soportar carga solo mediante Resources y restricciones de WebGL.
  • El grupo Addressables de Serenity y la configuración de Addressables se actualizaron para registrar los nuevos assets.

Funcionalidades

  • El modo ResourcesOnly ahora realiza traducción real y permite cambiar de idioma en runtime mediante el selector de idioma de la UI de ajustes.
  • La exportación de Resources para WebGL utiliza semántica de movimiento durante la exportación y recurre al idioma del navegador como locale inicial.
  • El JSON de localización se carga mediante un escaneo recursivo con Resources.LoadAll<TextAsset>("") y un filtro de forma de string table, sin requerir acoplamiento con el asmdef de Unity.Localization.Editor.

Corregido

  • Corregida la desaparición del selector de la barra de carga al salir el ratón, usando un prefab dedicado de progreso de carga en lugar de reutilizar la plantilla interactiva del slider.
  • Corregidos los builds ResourcesOnly que anteriormente mostraban las claves de localización en pantalla sin forma de cambiar de idioma en runtime.
  • Corregido el selector de idioma —cuyos valores son a su vez claves de localización— que traducía la clave cacheada obsoleta en lugar de la actual.

Infraestructura

  • Añadidas herramientas de editor para exportación, limpieza, validación y seguimiento mediante manifest de Resources para WebGL.
  • La exportación de localización basada en reflection evita el acoplamiento con el asmdef de Unity.Localization.Editor.
  • Añadidos tests para los casos de uso de localización y el instalador de localización.

1.0.8 — Selectores de Editor, Autoetiquetado de Addressables y Validación de TMP Essentials

Añadido

  • SerenityTmpEssentialsValidator, un validador exclusivo de editor que detecta recursos esenciales de TextMeshPro ausentes e intenta importarlos automáticamente cuando es posible.
  • Protección en Play Mode ante TMP Essentials ausentes, cancelando la entrada en Play Mode antes de que puedan producirse errores de runtime de Unity/TMP.
  • Diálogo manual de recuperación de TMP Essentials con opciones para abrir el importador de TMP, ignorar la advertencia durante la sesión actual o volver a comprobar.
  • Postprocesador de importación de Serenity que programa una comprobación de TMP Essentials cada vez que se importan assets de Serenity en una sesión del editor de Unity ya abierta.
  • SerenityAddressablesAutoLabeler, un postprocesador exclusivo de editor que registra automáticamente los assets ScriptableObject de Serenity recién importados como Addressables.
  • Asignación automática de labels de Addressables para assets ScriptableObject de Serenity basada en mapeos exactos de tipo y reglas fallback por prefijo de namespace.
  • Constantes ModuleLabels centralizadas para todas las labels de módulo y labels de tipo de Serenity.
  • Constantes ModuleLabels.Types para labels de Addressables basadas en tipo, como assets de fuente, imagen, audio y personaje.
  • Labels de módulo adicionales para los sistemas Character, GameMode, SequencePlayer y Wave.
  • Combinaciones comunes de labels adicionales para GameSettings + Localization y GameSettings + UI.
  • Helper RenderIdObjectField<TAsset>(...) en FoundationEditor para renderizar ObjectFields de Unity respaldados por ids serializados en string.
  • EventDispatcherSignalTypePicker, un selector compartido con búsqueda para subtipos concretos de EventDispatcherSignal.
  • EventDispatcherSignalTypeAdvancedDropdown, un selector con búsqueda basado en AdvancedDropdown para campos string de tipos de señal.
  • Label de Addressables module:game-mode.
  • Registro y etiquetado de Addressables para GameModeSettings.

Cambiado

  • SerenityPackageDependencyInstaller ahora considera TextMeshPro como satisfecho cuando los tipos runtime de TMP están disponibles, incluso si com.unity.textmeshpro no aparece listado como paquete independiente.
  • La detección de dependencias de TextMeshPro ahora soporta configuraciones de Unity 6 / UGUI 2.0+ donde TMP viene incluido con com.unity.ugui.
  • Las cadenas de labels de Addressables ahora pasan por Serenity.Shared.Constants.ModuleLabels en lugar de literales string hardcodeados.
  • InstallationConstants.ModuleLabels ahora actúa como shim de compatibilidad que reexporta los valores canónicos de ModuleLabels.
  • InstallationConstants.TypeLabels ahora actúa como shim de compatibilidad que reexporta ModuleLabels.Types.
  • UnityAddressablesLabeler ahora usa constantes centralizadas de ModuleLabels para labels gestionadas, reglas de ruta y reglas de tipo.
  • UnityAddressablesLabeler ahora gestiona labels adicionales de Serenity para los módulos Character, GameMode, SequencePlayer y Wave.
  • UnityAudioPlayerInstaller, UnityMusicPlayerInstaller, UnityGameSettingsInstaller, UnityLocalizationInstaller, UnityMenuInstaller, UnityModalInstaller, UnityPlayerInputInstaller, UnitySoundMixerInstaller, UnitySystemConfigurationInstaller, UnityCharacterInstaller y los servicios relacionados con Cutscene/Sequence ahora usan constantes centralizadas de labels de módulo.
  • AudioMixerDependencyCache ahora usa por defecto ModuleLabels.AUDIO_MIXER en lugar de una label de Addressables hardcodeada.
  • UnityUiSettingsEditor ahora renderiza ScaleKey y FontSizeKey como ObjectFields de Unity respaldados por assets UnityUIGameSettingsDefinition.
  • UnityGameGraphicsSettingsEditor ahora renderiza QualityLevelKey, ScreenResolutionKey e IsFullScreenKey como ObjectFields de Unity respaldados por assets UnityGraphicGameSettingsDefinition.
  • UnityLocalizationSettingsEditor ahora renderiza GameLanguageKey y VoiceLanguageKey como ObjectFields de Unity respaldados por assets UnityLocalizationGameSettingsDefinition.
  • UnityMenuServiceSettingsDefinitionEditor ahora renderiza InitMenuId como un ObjectField de Unity respaldado por assets UnityMenuSettingsDefinition.
  • UnityGameModeSettingsDefinitionEditor ahora renderiza PauseMenuId como un ObjectField de Unity respaldado por assets UnityMenuSettingsDefinition.
  • UnityActionDefinitionEditor ahora renderiza Signal mediante un selector de tipo de señal con búsqueda en lugar de un dropdown simple.
  • UnityModalSettingsEditor ahora renderiza SignalType mediante un selector de tipo de señal con búsqueda en lugar de un dropdown simple.
  • UnityModalSettingsEditor ahora comparte el descubrimiento de tipos de señal mediante EventDispatcherSignalTypePicker, evitando lógica de reflexión duplicada.
  • UnityMenuSettingsDefinitionEditor ahora usa constantes centralizadas de labels de módulo al resolver game settings y menús.
  • UnitySoundMixerSettingsEditor ahora usa constantes centralizadas de labels de módulo al resolver game settings de audio.
  • Los assets de menú de ejemplo de Serenity se han reserializado para incluir valores ViewId explícitos en opciones y valores.
  • Los assets de menú de ejemplo de Serenity ahora incluyen arrays OnShow y OnHide vacíos explícitos.
  • El asset de ejemplo GameModeSettings ahora incluye entradas de señales de transición para los valores más recientes del enum GameMode.

Funcionalidades

  • Los assets ScriptableObject de Serenity recién creados ahora pueden añadirse automáticamente al grupo de Addressables de Serenity con las labels de módulo correctas.
  • El autoetiquetado de Addressables ahora soporta mapeos exactos de tipo para assets conocidos de Serenity y fallback por namespace para futuros assets dentro de módulos existentes.
  • Los selectores de editor para referencias ScriptableObject respaldadas por ids string ahora soportan drag-and-drop desde la ventana Project.
  • Los selectores de editor para referencias ScriptableObject respaldadas por ids string ahora soportan el flujo de búsqueda estándar del Object Picker de Unity.
  • Los campos de tipo de señal ahora ofrecen selección con búsqueda conservando los contratos string serializados originales.
  • UnityActionDefinition.Signal continúa almacenando Type.FullName.
  • UnityModalSettings.SignalType continúa almacenando Type.AssemblyQualifiedName.
  • UnityModalSettings.SignalType conserva la opción <None>, almacenando un string vacío cuando no hay selección.
  • La validación de TMP Essentials se ejecuta tanto al iniciar/importar en el editor como de forma síncrona al entrar en Play Mode.
  • La autoimportación de TMP Essentials intenta localizar el paquete mediante utilidades de editor de TMP, metadatos del Package Manager o Library/PackageCache.

Mejorado

  • La UX del Inspector ahora se acerca más a los flujos estándar de Unity para referencias respaldadas por assets.
  • Se han reducido las selecciones inválidas accidentales provocadas por dropdowns largos sin búsqueda.
  • Se ha reducido el código duplicado de dropdowns y reflexión en editores personalizados.
  • La gestión de labels de Addressables ahora es más segura y fácil de mantener gracias a una única fuente de verdad.
  • El autoetiquetado de Addressables es idempotente y no destructivo: no elimina labels existentes y solo añade labels conocidas de Serenity.
  • La detección del paquete TMP es más robusta entre versiones de Unity.
  • La detección de TMP Essentials ahora distingue entre que el runtime de TMP esté instalado y que los recursos esenciales de TMP estén realmente presentes en Assets/.
  • Los diagnósticos de TMP Essentials ahora registran coincidencias de TMP font assets sin tratarlas como prueba de que Essentials esté instalado.
  • El código de instaladores y editor ahora evita dispersar labels de Addressables hardcodeadas por el codebase.
  • Las definiciones de assembly se han actualizado donde era necesario para que los módulos puedan referenciar las constantes compartidas de labels.

Corregido

  • Corregida la detección falsa de dependencia ausente para TextMeshPro en versiones de Unity donde TMP viene incluido mediante UGUI en lugar de instalarse como com.unity.textmeshpro.
  • Corregido el etiquetado ausente module:game-mode para GameModeSettings.
  • Corregidos varios campos de editor que antes requerían selección mediante dropdown aunque representaban ids respaldados por assets.
  • Corregido que UnityActionDefinition.Signal y UnityModalSettings.SignalType siguieran siendo dropdowns sin búsqueda tras la refactorización inicial del picker.
  • Corregida la lógica duplicada de descubrimiento de tipos de señal entre la selección de señales de modal y los menús de señales de botones de modal.
  • Corregido el uso de labels de Addressables hardcodeadas en varios instaladores y utilidades de editor.
  • Corregida la cobertura de labels gestionadas de Addressables para módulos más recientes de Serenity como Character, GameMode, SequencePlayer y Wave.

Infraestructura

  • Añadidas utilidades de editor para el registro automático en Addressables y la asignación de labels.
  • Añadidas utilidades de editor para la validación y recuperación de TMP Essentials.
  • Añadida infraestructura compartida de editor para la selección de tipos de señal.
  • Añadido helper compartido de editor para el puente entre ObjectField e ids string.
  • Añadidas referencias de assembly definition a Serenity.Shared.Constants donde ahora se usan constantes centralizadas de labels.
  • Actualizada la configuración de Addressables para eliminar labels obsoletas e incluir la nueva label module:game-mode.
  • Actualizado el grupo de Addressables de Serenity para que Media/GameMode/GameModeSettings esté etiquetado con module:game-mode.
  • Actualizados los assets serializados de ejemplo para que coincidan con el modelo actual de datos de menús y game mode.

1.0.5 — Transiciones de Music Player, Señales de GameMode e Integración con Menú

Añadido

  • Enum MusicPlayerTransitionType con tres estrategias de transición: CUT, FADEIN_FADEOUT y CROSS_FADE.
  • Parámetros de transición configurables en IMusicPlayerService.PlaySong(...) y nuevo método PlaySongById(...).
  • Caso de uso MusicPlayerPlaySongById y DTO MusicPlayerPlaySongByIdInput para reproducir pistas específicas por identificador con control explícito de loop y transición.
  • Método gateway PlaySongById en IMusicPlayerGateway.
  • Contrato SetGameModeService(IGameModeService) en IMenuService para coordinación entre servicios.
  • Contrato GetSignalsForGameMode(GameModeEnum) en IGameModeSettingsDefinition para configuración de señales por modo.
  • Valores Initialization y Cutscene al enum GameMode, estableciendo Initialization como modo inicial por defecto.
  • Secuencias de transición EventDispatcherSignal por modo en UnityGameModeSettingsDefinition.
  • Orquestación DispatchModeTransitionSignals(...) en UnityGameModeService que lanza las señales configuradas después de cada cambio de modo.
  • Inspector completo basado en ReorderableList para señales de transición por modo en UnityGameModeSettingsDefinitionEditor.
  • Registro de ServiceLocator para IMusicPlayerService durante la instalación del music player.

Cambiado

  • UnityGameModeService ahora se inicializa en modo Initialization en lugar de Menu, posponiendo la primera transición real de modo hasta que el sistema de menús esté listo.
  • UnitySerenityInstaller.ShowMenu() ahora conecta el IGameModeService resuelto en el servicio de menú antes de invocar ShowInitialMenu(), asegurando que el game mode esté sincronizado al arrancar.
  • UnityMusicPlayerInstaller ahora recibe ServiceLocatorInstaller para descubrimiento de servicios en runtime.
  • Formato de referencia de Serenity.GameMode.Domain.asmdef estandarizado a GUID.
  • Nombres de assets listos para producción: Audio_SoundToTestAudio_SoundToTrigger, Audio_TrackToTestMusic_TrackList.
  • Configuración de AudioTestingMenu actualizada para referenciar los assets de producción renombrados.

Funcionalidades

  • La reproducción de música ahora impone una regla de una única pista activa mediante lerping de volumen basado en corrutinas.
  • Las solicitudes de reproducción rápidas sustituyen de forma segura transiciones anteriores ("la última solicitud gana"), evitando audio sources huérfanas.
  • CROSS_FADE vuelve automáticamente a CUT cuando no hay suficientes canales de audio configurados.
  • Las señales de transición de GameMode se despachan en el orden exacto configurado en el inspector, saltando y registrando de forma segura las entradas nulas.
  • GameMode.Menu ahora se afirma automáticamente cada vez que se ejecuta ShowInitialMenu(), manteniendo sincronizados el sistema de menús y el estado de modo.

Mejorado

  • El inspector de UnityGameModeSettingsDefinitionEditor ahora renderiza una lista de señales reordenable dedicada por cada valor de GameMode, con dropdowns de selección de subtipo y ordenación drag-and-drop.
  • Los elementos de la lista de señales muestran el nombre del subtipo concreto de EventDispatcherSignal para identificación rápida.
  • Las assembly definitions Serenity.Menu.Application y Serenity.UnityMenu.Infrastructure ahora referencian los contratos de GameMode para coordinación entre capas.

Corregido

  • Prevenidas posibles transiciones recursivas de modo apoyándose en el short-circuit de SetMode cuando el modo objetivo coincide con el modo actual.
  • Actualizadas las firmas del stub del gateway de music player para mantener compatibilidad de interfaz con el nuevo contrato con soporte de transiciones.

Infraestructura

  • Nuevas referencias de assembly definition añadidas para conectar capas de MusicPlayer, Menu y GameMode sin dependencias circulares.
  • Assembly definition de tests ampliada para incluir Serenity.UnityMusicPlayer.Installation y cubrir validación a nivel de instalador.

1.0.3 — Señales de Ciclo de Vida de Menú y Mejoras del Inspector

Añadido

  • Añadidas colecciones de señales de ciclo de vida OnShow y OnHide a UnityMenuSettingsDefinition.
  • Añadido soporte de señales de ciclo de vida de menú a IMenuSettingsDefinition.
  • Añadido despacho runtime de señales de ciclo de vida para transiciones de visibilidad de menú.
  • Añadido cableado de señales de ciclo de vida en UnityMenuViewFactory.
  • Añadido soporte SetLifecycleSignals(...) a UnityMenuView.

Funcionalidades

  • Los menús ahora pueden despachar secuencias personalizadas de EventDispatcherSignal cuando se muestran u ocultan.
  • El orden de ejecución de señales de ciclo de vida ahora sigue el orden exacto configurado en el inspector.
  • Las colecciones de señales de ciclo de vida ahora soportan reordenación drag-and-drop mediante listas reordenables estándar de Unity.

Mejorado

  • Mejorado UnityMenuSettingsDefinitionEditor con una sección dedicada Lifecycle Signals.
  • Las listas de señales de ciclo de vida ahora ofrecen:
    • controles de añadir/eliminar,
    • ordenación drag-and-drop,
    • menús de selección de subtipo,
    • estilo de inspector consistente con el resto de editores de Serenity.
  • Mejorada la consistencia de UX del inspector reutilizando los mismos patrones de creación de señales ya presentes en otros sistemas de Serenity.

Corregido

  • Corregido el renderizado del inspector de señales de ciclo de vida para que las implementaciones de EventDispatcherSignal puedan seleccionarse correctamente.
  • Corregido el flujo de serialización para señales polimórficas de ciclo de vida usando referencias gestionadas de Unity.
  • Asegurado que los assets de menú legacy sigan funcionando de forma segura con colecciones de señales de ciclo de vida vacías.

Infraestructura

  • Reutilizada la infraestructura existente de EventDispatcherSignal y el flujo de despacho sin introducir sistemas paralelos de ciclo de vida.
  • Mantenidos intactos los límites de Clean Architecture exponiendo señales de ciclo de vida mediante abstracciones de solo lectura en la capa de negocio.

1.0.2 — Mejoras de Editor y del Inspector de Localización

Añadido

  • UnityLocalizationLocaleEditorUtils, un helper de editor basado en reflexión para descubrimiento seguro de locales de Unity Localization sin añadir carga de dependencia de assembly.

Cambiado

  • Mejorado LocalizationSettingsDefinitionEditor para mejorar la UX de los assets UnityLocalizationGameSettingsDefinition.
  • Reforzado el flujo de importación de Serenity y el proceso de recuperación de localization.
  • Refactorizado el flujo de señales de botones del editor de modal settings para interacciones de editor más limpias.

Funcionalidades

  • Bloqueado el campo ValueType a SELECTABLE con normalización automática y validación de seguridad para prevenir errores de configuración.
  • Sustituido el input de texto libre "Key" en la tabla de opciones por un dropdown dinámico poblado desde los locales de Unity Localization.

Mejorado

  • Añadido soporte fallback para keys desconocidas y HelpBoxes informativos para guiar a los usuarios cuando los ajustes de Localization faltan o no están configurados.
  • Estabilidad de inicialización del paquete tras importar Serenity en un proyecto Unity limpio.

Corregido

  • Resolución del color de fondo del loading overlay cuando se usan cámaras de renderizado.

Infraestructura

  • Reutilizadas las utilidades UI existentes de FoundationEditor y UnityGameSettingsDefinitionEditor para mantener consistencia visual y funcional.

1.0.0 — Lanzamiento Inicial

✨ Funcionalidades

  • Lógica de juego desacoplada sin dependencias de motor en las capas core. Todo el código de dominio y aplicación compila con noEngineReferences: true, garantizando que las reglas de negocio sean totalmente portables, testeables y libres de acoplamiento con Unity.

  • Sistema de persistencia extensible y por capas. Una jerarquía de almacenamiento unificada soporta key-value stores respaldados por PlayerPrefs, blob stores basados en archivos con escrituras atómicas y streams append-only, todo detrás de contratos intercambiables que pueden apuntar a archivos locales, servicios cloud o backends personalizados.

  • Precarga avanzada de assets con presupuestos de memoria. Un motor de prefetch sensible a prioridades, con expulsión LRU, presupuestos de memoria configurables, estrategias de ventana deslizante y bajo demanda, y resolución de labels basada en Addressables, proporciona disponibilidad predecible de assets con presión de recursos controlable.

  • Game settings tipados y persistidos por repositorio. Un sistema genérico de settings soporta tipos Boolean, Integer, Float y Selectable con notificaciones de cambio de valor, persistencia automática e integración reactiva con módulos de audio, gráficos y localización.

  • Gestión de personajes basada en estado. Los personajes siguen un ciclo de vida bien definido (Spawning → Active → Dying → Dead) con seguimiento de hit points, snapshots inmutables y puntos de extensión virtuales para especialización específica del juego.

  • Contador de combo agnóstico al juego. Un modelo puro de conteo con snapshots inmutables que no impone semántica de gameplay: timeout, multiplicador y lógica de puntuación siguen siendo responsabilidad de la capa consumidora.

  • Persistencia de checkpoints opaca. Slots de guardado con nombre y metadatos extensibles (timestamp, label, stage) almacenan payloads binarios arbitrarios sin interpretar ni validar su contenido, dejando la estrategia de serialización a los consumidores.

  • Pipeline de inicialización configurable. Un sistema de arranque ordenado por fases y tareas con seguimiento de progreso ponderado, criticidad por tarea (Critical vs. NonCritical) y políticas de ejecución conectables (secuencial o paralela por fase).

  • Sistema completo de animación procedural. Un motor de procedural expression basado en datos y keys soporta composición de poses por capas (oscilación, drift, ruido, impulso), animación de propiedades de material, animación de escala de transform, acciones discretas one-shot (flinch, recoil, stumble), activación basada en reglas con condiciones de histéresis y ajuste en tiempo real, todo completamente agnóstico al producto.

  • Sistema de eventos publish/subscribe type-safe. Un event dispatcher centralizado con acciones autoregistradas, clases de señal tipadas y descubrimiento basado en atributos permite comunicación desacoplada entre módulos.

  • Reproducción de audio multicategoría. Un sistema de audio enrutado por gateway soporta canales SFX, Music, Voice, Ambient, Environment y UI con pooling por categoría y configuración de clips guiada por settings.

  • Music player dedicado con soporte de crossfade. La gestión de música de fondo ofrece operaciones play, stop, fade-in, fade-out y crossfade de forma independiente del sistema de audio de formato corto.

  • Abstracción de audio mixer. Gestión de volumen y mute por grupos (Master, Music, SFX, Voice, UI) con persistencia automática mediante integración con game settings.

  • Gestión de ciclo de vida de stages. Un agregado stage de nivel superior rastrea estados de inicio, completado y fallo con notificaciones basadas en señales consumidas por módulos downstream como waves, timers y scoring.

  • Progresión secuencial de waves. Estructura stage wave-by-wave con detección automática de clear y señales encadenadas para wave start, wave cleared y all-waves-cleared.

  • Scoring dinámico multimétrica. Un modelo de puntuación sin límite direccionado por keys con nombre soporta registro runtime de métricas y operaciones aritméticas completas (add, subtract, multiply, divide, set, reset) con persistencia respaldada por repositorio.

  • Gestión del modo de aplicación. Un servicio de game mode coordina transiciones entre estados Menu, Game y Pause con estrategias de pausa conectables, cambio de action-map de input y coordinación basada en señales.

  • Seguimiento del ciclo de vida de sesión. Gestión de estado por sesión con fuentes de tiempo agnósticas al motor, acumulación de ticks frame-by-frame y snapshots inmutables de sesión.

  • Sistema de gestión de timers. Timers con nombre en modos countdown, elapsed y repeating proporcionan progreso normalizado, control pause/resume y notificaciones de ciclo de vida basadas en señales.

  • Navegación de menús con soporte de stack. Un sistema de menús basado en navigation stack soporta operaciones show, hide, push, pop y peek con configuración por menú y señales de ciclo de vida.

  • Sistema de diálogos modales. Diálogos modales configurables con factorías de botones, gestión de resultados basada en callbacks y señales preconstruidas para confirmaciones comunes (salir de la aplicación, reiniciar juego, resetear settings).

  • Fundación UI agnóstica a plataforma. Una jerarquía de vistas, sistema de theme/style y modelo de componentes permiten construcción UI componible sin dependencias de motor en la capa de dominio.

  • Gestión de estado de game UI. Modelos abstractos de estado para HUD y results-screen con delegación de renderizado mediante presenter-port permiten testear la lógica UI aislada de la infraestructura de renderizado.

  • Localización con integración de settings. Gestión de idioma de juego y voz con cambio automático de idioma impulsado por cambios persistentes en game settings.

  • Gestión de ajustes gráficos. Gestión reactiva de quality level, screen resolution y fullscreen mode impulsada por eventos de cambio de valor de game settings.

  • Detección de configuración del sistema. Consultas de capacidades de hardware (memoria, GPU, pantalla) con generación de perfil de calidad recomendado para configuración automática.

  • Modelo genérico de spawning y pooling. Creación y destrucción de entidades rastreadas por handle, con consultas de estado de pool, desacopladas de la mecánica de instanciación mediante un factory port.

  • Identidad de entidades de gameplay. Identidad de entidad basada en GUID con clasificación semántica (Player, Character, Hazard) proporciona un vocabulario de referencia compartido entre sistemas de gameplay.

  • Modelo de movimiento basado en rail. Rail paths con nombre y seguimiento de progreso normalizado permiten movimiento on-rails dirigido externamente sin acoplamiento a interpolación o easing.

  • Gestión de estado de armas. Mecánicas de trigger, cambio de fire-mode y seguimiento de magazine/ammo con snapshots de solo lectura, independientes de la representación visual o de sistemas de proyectiles.

  • Motor de orquestación de secuencias. Un sistema genérico de ejecución ordenada proporciona iteración de stages basada en completado, consumida por agregados verticales como el cutscene player.

  • Reproducción de cinemáticas. Ejecución temporizada de stages con tipos fade, timeline, wait y dialog construida sobre la base de orquestación de secuencias.

  • Logging estructurado con verbosidad por categoría. Un sistema de logging configurable con niveles de severidad, overrides por categoría, perfiles de enrutado de logs y component loggers consumidos por todos los módulos.

  • Navegación de view browser. Navegación forward/back entre pantallas con consultas de estado de navegación para flujos de browsing impulsados por UI.

  • Service locator mínimo. Un contrato de resolución de servicios respaldado por diccionario para casos estrechos donde la inyección por constructor no es práctica, por ejemplo acciones de evento instanciadas por reflexión.

  • Sistema de tareas componible. Contratos de unidades de trabajo asíncronas con niveles de criticidad, invocación de métodos basada en reflexión, resolución de argumentos sensible a servicios y soporte de despacho al main thread.

  • Persistencia basada en archivos con escrituras atómicas. Un file-system blob store con seguridad write-then-rename, resolución de rutas específica de plataforma y soporte de streams append-only.

🧱 Arquitectura

  • Aplicación estricta de Clean Architecture. Cada agregado sigue una estructura estricta Domain ← Application ← Installation con flechas de dependencia solo hacia dentro. Las capas Domain tienen cero o mínimas dependencias externas; las capas Application dependen únicamente de contratos de dominio y servicios fundacionales transversales; las capas Installation cablean implementaciones específicas de plataforma.

  • Aislamiento del motor mediante assembly definitions. Los assemblies core de negocio declaran noEngineReferences: true, garantizando enforcement en tiempo de compilación de que ninguna API de Unity se filtra en la lógica de dominio o aplicación.

  • Principios SOLID en todo el sistema. Agregados de responsabilidad única, contratos de servicio segregados por interfaz, extensión open/closed mediante instaladores abstractos y factory ports, e inversión de dependencias mediante interfaces agnósticas a plataforma.

  • Vocabulario Domain-Driven Design. Las entidades llevan estado mutable con transiciones protegidas, los value objects proporcionan identidad y snapshots inmutables, y los agregados definen bounded contexts con puntos de integración explícitos.

  • Diseño de API guiado por casos de uso. Las operaciones de cara al consumidor están encapsuladas en clases de caso de uso tipadas con DTOs de entrada dedicados, agrupadas en contenedores inyectables para grafos de dependencias limpios.

  • Patrón de snapshot inmutable. Todos los agregados con estado exponen snapshots de solo lectura para consultas, asegurando que los consumidores no puedan mutar accidentalmente el estado interno.

  • Patrón de instalador abstracto. Cada agregado define un instalador abstracto que declara el contrato de wiring; las capas concretas de plataforma (Unity, tests o targets personalizados) proporcionan implementaciones sin modificar el código de negocio.

  • Comunicación intermódulo basada en señales. Las señales de evento tipadas fluyen por un dispatcher centralizado, manteniendo los agregados desacoplados y permitiendo coordinación reactiva.

📦 Módulos

  • Global — Contratos fundacionales, eventos de ciclo de vida (exit/restart), jerarquía de interfaces de casos de uso, modelo de componentes para composición UI y la base abstracta de instalador consumida por todos los demás agregados.

  • EventDispatcher — Sistema de eventos publish/subscribe type-safe con acciones autoregistradas, clases de señal tipadas y descubrimiento basado en atributos.

  • Logging — Logging configurable con niveles de severidad, overrides de verbosidad por categoría, perfiles de enrutado de logs, component loggers y soporte de salida a archivo/consola.

  • ServiceLocator — Resolución mínima de servicios tipados con implementación por defecto respaldada por diccionario.

  • Task — Contratos de unidades de trabajo asíncronas con criticidad, invocación de métodos basada en reflexión y resolución extensible de argumentos.

  • InitializationPipeline — Sistema de arranque ordenado por fases y tareas con seguimiento de progreso ponderado, gestión de fallos basada en criticidad y políticas de ejecución conectables.

  • Persistence — Jerarquía de almacenamiento por capas: key-value stores, blob stores basados en streams y append-only stores, todo detrás de contratos de plataforma intercambiables.

  • FilePersistence — File-system blob store con seguridad de escritura atómica write-then-rename y resolución de rutas específica de plataforma.

  • PlayerPrefsPersistence — Key-value store ligero respaldado por Unity PlayerPrefs con codificación Base64.

  • GameSettings — Sistema de settings tipados (Boolean, Integer, Float, Selectable) con persistencia por repositorio y notificaciones de cambio de valor.

  • Checkpoint — Persistencia opaca de checkpoint binario con slots con nombre (Slot1–3, Auto, Quick) y metadatos extensibles.

  • Score — Modelo de scoring dinámico multimétrica con métricas ilimitadas por key, operaciones aritméticas completas y persistencia por repositorio.

  • Combo — Contador de combo agnóstico al juego con snapshots inmutables y puntos de extensión virtuales para multiplicador, timeout o comportamiento de decay.

  • Character — Ciclo de vida de personaje basado en estado (Spawning → Active → Dying → Dead) con gestión de hit points, enums de estado heredables y snapshots inmutables.

  • GameplayEntity — Identidad de entidad basada en GUID con clasificación semántica y referencias ligeras entre sistemas.

  • GameSpawner — Spawning de entidades y gestión de estado de pool rastreados por handle con un factory port para la estrategia de instanciación.

  • Stage — Ciclo de vida de stage de nivel superior (NotStarted → InProgress → Completed/Failed) con resolución de spawn points y contratos de autoría de rail paths.

  • Wave — Progresión secuencial de waves con detección automática de clear y señales de ciclo de vida encadenadas.

  • Timer — Gestión de timers con nombre en modos countdown, elapsed y repeating, progreso normalizado y señales de ciclo de vida.

  • GameMode — Máquina de estados de modo de aplicación (Menu, Game, Pause) con estrategias de pausa conectables y transiciones basadas en señales.

  • GameSession — Seguimiento de ciclo de vida por sesión con fuentes de tiempo agnósticas al motor y acumulación de tiempo transcurrido basada en ticks.

  • AudioPlayer — Reproducción de audio multicategoría con enrutado gateway, channel pooling y operaciones guiadas por casos de uso.

  • MusicPlayer — Gestión de música de fondo con operaciones play, stop, fade y crossfade.

  • SoundMixer — Gestión de volumen y mute por grupos con integración reactiva de game settings.

  • GameGraphics — Gestión reactiva de quality level, resolution y fullscreen impulsada por cambios en game settings.

  • SystemConfiguration — Detección de capacidades de hardware con generación de perfil de calidad recomendado.

  • PlayerInput — Abstracción de input agnóstica a plataforma con cambio de action-map y contratos de binding de input actions.

  • Ui — Jerarquía de vistas, sistema de theme/style y modelo de componentes para construcción UI componible e independiente del motor.

  • Menu — Sistema de menús basado en navigation stack con configuración por menú y señales de ciclo de vida.

  • Modal — Diálogos modales configurables con factorías de botones, resultados basados en callbacks y señales de confirmación preconstruidas.

  • GameUi — Gestión abstracta de estado de HUD y results-screen con delegación mediante presenter-port.

  • ViewBrowser — Navegación forward/back entre pantallas con consultas de estado.

  • Localization — Gestión de idioma de juego y voz con cambio automático de idioma impulsado por settings.

  • SequencePlayer — Motor genérico de orquestación de ejecución ordenada para iteración de stages basada en completado.

  • CutscenePlayer — Reproducción cinemática con stages temporizados (fade, timeline, wait, dialog) construida sobre la base de orquestación de secuencias.

  • GameRail — Registro de rail paths con nombre y seguimiento de progreso normalizado para movimiento on-rails.

  • GameWeapon — Mecánicas de trigger, cambio de fire-mode y seguimiento de magazine/ammo con snapshots de solo lectura.

  • ProceduralExpression — Sistema de animación procedural basado en datos con composición de poses por capas, animación de material/transform, activación basada en reglas, acciones discretas y soporte de ajuste en tiempo real.

  • Shared — Constantes transversales (nombres de servicio, labels de módulo, identificadores de contexto) y clases utilitarias (parseo, reflexión, generación de GUID).

🛠️ Tooling

  • Generador de documentación API basado en DocFX. Un builder de documentación integrado accesible desde Tools → Serenity → Docs compila todos los assemblies con documentación XML de Roslyn y genera un sitio API estático navegable mediante DocFX, con instalación automática, generación de configuración y soporte de plantilla con branding.

  • Herramienta de setup de Procedural Expression. Un wizard de setup de un clic (Tools → Serenity → Procedural Expression → Setup Minimal Idle) autodetecta huesos de esqueletos, genera todos los assets de configuración necesarios y conecta un perfil de animación procedural a cualquier prefab, soportando personajes riggeados, objetos simples, props y elementos UI.

  • Inspector de diagnósticos de Asset Prefetcher. Un inspector personalizado de Editor para el servicio de prefetch proporciona refresco de caché, limpieza, exportación al portapapeles, visualización de diagnósticos, polling de auto-refresco y visualización de categorías de assets con código de color.

  • Inspector de System Configuration. Un inspector personalizado para system configuration settings proporciona una interfaz completa para timing de recopilación de datos, scope y ajuste de heurísticas.

  • Inspectores de Menu y Modal. Inspectores personalizados de Editor para menu views y componentes modal proporcionan visualización de configuración de solo lectura, gestión de binding de señales e interfaces de configuración de botones.

  • Configuración basada en ScriptableObject. Prefetch policy profiles, procedural expression profiles, state keys, layers, actions, rules, audio settings, definiciones de game settings y localization tables se authoran como assets ScriptableObject, permitiendo configuración por no programadores y presets versionados.

  • Patrón de instalador abstracto para wiring de plataforma. Cada agregado define un instalador abstracto con dependencias explícitas; los instaladores concretos específicos de Unity gestionan creación de MonoBehaviours, integración con Addressables y registro en service locator.

  • Panel de debug de Procedural Expression. Una GUI overlay en runtime (activada con F12) muestra valores live de state-key con sliders con código de color, pistas de rango y controles de reset para ajuste en tiempo real en Play Mode.

  • Property drawers personalizados de Procedural Expression. Drawers de referencia de Bone ID con selección dropdown sensible al perfil, editores de reglas con configuración inline de condiciones y editores de perfil con validación y visualización de propiedades derivadas.

🎯 Propósito

Serenity existe para eliminar el boilerplate recurrente que acompaña a cada proyecto Unity: wiring de persistencia, gestión de settings, enrutado de audio, secuenciación de inicialización, transiciones de modo y fontanería de eventos. En lugar de proporcionar sistemas de gameplay opinados, ofrece la columna vertebral arquitectónica — contratos limpios, límites por capas y módulos componibles — sobre la que se construye el código específico de cada juego.

Al imponer aislamiento estricto del motor en las capas core, Serenity garantiza que la lógica de negocio siga siendo testeable fuera de Unity, portable entre plataformas y resistente a cambios en la API del motor. El patrón de instalador abstracto significa que cambiar un backend de persistencia o un sistema de input requiere implementar una única interfaz, no refactorizar un árbol de dependencias.

Cada módulo sigue las mismas convenciones estructurales: entidades de dominio con transiciones de estado protegidas, snapshots inmutables para consultas seguras, clases de casos de uso con entradas tipadas y puntos de integración basados en señales. Esta consistencia reduce el tiempo de onboarding y hace que los patrones entre módulos sean reconocibles de inmediato.

Serenity no es una plantilla de juego. No proporciona personajes, ni niveles, ni condiciones de victoria. Proporciona la base que hace que esos sistemas sean más limpios, más rápidos de construir y más fáciles de mantener durante toda la vida de un proyecto.

✨ Funcionalidades

  • Lógica de juego desacoplada sin dependencias del motor en las capas core. Todo el código de dominio y aplicación compila bajo noEngineReferences: true, garantizando que las reglas de negocio sean completamente portables, testeables y libres de acoplamiento con Unity.

  • Sistema de persistencia extensible y por capas. Una jerarquía unificada de almacenamiento da soporte a key-value stores (respaldados por PlayerPrefs), blob stores basados en archivos con escrituras atómicas y streams append-only, todo ello detrás de contratos intercambiables capaces de apuntar a archivos locales, servicios cloud o backends personalizados.

  • Precarga avanzada de assets con presupuestos de memoria. Un motor de prefetch consciente de prioridades, con expulsión LRU, presupuestos de memoria configurables, estrategias sliding-window y on-demand, y resolución de labels basada en Addressables proporciona disponibilidad predecible de assets con una presión de recursos controlable.

  • Game settings tipados y persistidos en repositorio. Un sistema genérico de configuración soporta tipos Boolean, Integer, Float y Selectable, con notificaciones de cambio de valor, persistencia automática e integración reactiva con los módulos de audio, gráficos y localización.

  • Gestión de personajes basada en estados. Los personajes siguen un ciclo de vida bien definido (Spawning → Active → Dying → Dead) con seguimiento de puntos de vida, snapshots inmutables y puntos de extensión virtuales para especializaciones específicas del juego.

  • Sistema de combos agnóstico del juego. Un modelo puro de conteo con snapshots inmutables que no impone semánticas de gameplay: el timeout, los multiplicadores y la lógica de puntuación quedan bajo responsabilidad de la capa consumidora.

  • Persistencia opaca de checkpoints. Slots de guardado con nombre y metadatos extensibles (timestamp, etiqueta, etapa) almacenan payloads binarios arbitrarios sin interpretar ni validar su contenido, dejando la estrategia de serialización en manos del consumidor.

  • Pipeline de inicialización configurable. Sistema de arranque basado en fases y tareas con seguimiento ponderado del progreso, criticidad por tarea (Critical vs NonCritical) y políticas de ejecución configurables (secuencial o paralela por fase).

  • Sistema completo de animación procedural. Un motor procedural basado en datos y claves soporta composición de poses en capas (oscilación, drift, ruido, impulso), animación de propiedades de materiales, animación de escala de transforms, acciones discretas de un solo disparo (flinch, recoil, stumble), activación basada en reglas con condiciones de histéresis y ajuste en tiempo real, todo completamente agnóstico al producto.

  • Sistema de eventos publish/subscribe tipado. Un event dispatcher centralizado con acciones auto-registrables, clases de señales tipadas y descubrimiento basado en atributos permite una comunicación desacoplada entre módulos.

  • Reproducción de audio multi-categoría. Un sistema de audio con routing mediante gateways soporta canales SFX, Music, Voice, Ambient, Environment y UI, con pooling específico por categoría y configuración de clips basada en settings.

  • Reproductor de música dedicado con soporte crossfade. La gestión de música de fondo ofrece operaciones de play, stop, fade-in, fade-out y crossfade independientes del sistema de audio de corta duración.

  • Abstracción de audio mixer. Gestión de volumen y mute por grupos (Master, Music, SFX, Voice, UI) con persistencia automática mediante integración con game settings.

  • Gestión del ciclo de vida de stages. Un aggregate principal de stages realiza seguimiento de estados de inicio, completado y fallo mediante notificaciones basadas en señales consumidas por módulos descendentes como waves, timers y scoring.

  • Progresión secuencial de waves. Estructura wave-by-wave con detección automática de limpieza y señales en cascada para eventos de inicio de wave, wave completada y todas las waves completadas.

  • Sistema de puntuación multi-métrica dinámica. Un modelo de scoring ilimitado basado en claves soporta registro dinámico de métricas y operaciones aritméticas completas (add, subtract, multiply, divide, set, reset) con persistencia respaldada por repositorio.

  • Gestión de modos de aplicación. Un servicio de game modes coordina transiciones entre estados Menu, Game y Pause mediante estrategias de pausa configurables, cambio de action maps de input y coordinación basada en señales.

  • Seguimiento del ciclo de vida de sesiones. Gestión de estado por sesión con fuentes de tiempo agnósticas al motor, acumulación de ticks frame a frame y snapshots de sesión inmutables.

  • Sistema de temporizadores. Temporizadores con nombre compatibles con modos countdown, elapsed y repeating, proporcionando progreso normalizado, control de pausa/reanudación y notificaciones de ciclo de vida basadas en señales.

  • Navegación de menús con soporte stack. Un sistema de menús basado en stack de navegación soporta operaciones show, hide, push, pop y peek, con configuración específica por menú y señales de ciclo de vida.

  • Sistema de diálogos modales. Diálogos modales configurables con factories de botones, manejo de resultados basado en callbacks y señales preconstruidas para confirmaciones comunes (salir de la aplicación, reiniciar juego, resetear settings).

  • Fundación UI agnóstica de plataforma. Una jerarquía de vistas, sistema de themes/styles y modelo de componentes permiten construir interfaces composables sin dependencias del motor en la capa de dominio.

  • Gestión del estado de la UI del juego. Modelos abstractos de HUD y pantallas de resultados con delegación de renderizado mediante presenter-port permiten testear lógica UI de forma aislada de la infraestructura de renderizado.

  • Localización integrada con game settings. Gestión del idioma del juego y de voces con cambio automático impulsado por cambios persistentes en los game settings.

  • Gestión de configuración gráfica. Gestión reactiva de niveles de calidad, resolución de pantalla y modo fullscreen impulsada por eventos de cambio de valor de game settings.

  • Detección de configuración del sistema. Consultas de capacidades hardware (memoria, GPU, display) con generación automática de perfiles de calidad recomendados.

  • Modelo genérico de spawning y pooling. Creación y destrucción de entidades con seguimiento mediante handles y consultas del estado del pool, desacopladas de la mecánica de instanciación mediante un factory port.

  • Identidad de entidades gameplay. Identidad basada en GUID con clasificación semántica (Player, Character, Hazard) que proporciona un vocabulario compartido de referencias entre sistemas gameplay.

  • Modelo de movimiento sobre raíles. Rails con nombre y seguimiento de progreso normalizado permiten movimiento on-rails impulsado externamente sin acoplamiento a lógica de interpolación o easing.

  • Gestión de estado de armas. Mecánicas de trigger, cambio de fire mode y seguimiento de cargadores y munición mediante snapshots de solo lectura, independientes de la representación visual o de los sistemas de proyectiles.

  • Motor de orquestación de secuencias. Un sistema genérico de ejecución ordenada proporciona iteración de stages basada en completado, consumida por aggregates verticales como el reproductor de cutscenes.

  • Reproducción de cutscenes cinematográficas. Ejecución temporal de stages con tipos fade, timeline, wait y dialog construidos sobre la base del motor de orquestación de secuencias.

  • Logging estructurado con verbosidad basada en categorías. Sistema configurable de logging con niveles de severidad, overrides por categoría, perfiles de routing y component loggers consumidos por todos los módulos.

  • Navegación View Browser. Navegación forward/back entre pantallas con consultas de estado orientadas a flujos UI.

  • Service Locator minimalista. Contrato de resolución de servicios basado en diccionario para casos concretos donde la inyección por constructor resulta impráctica (por ejemplo, acciones de eventos instanciadas mediante reflexión).

  • Sistema de tareas componible. Contratos de trabajo asíncrono con niveles de criticidad, invocación de métodos basada en reflexión, resolución de argumentos consciente de servicios y soporte de dispatching al hilo principal.

  • Persistencia basada en archivos con escrituras atómicas. Blob store basado en sistema de archivos con seguridad write-then-rename, resolución de rutas específica por plataforma y soporte para streams append-only.

🧱 Arquitectura

  • Aplicación estricta de Clean Architecture. Cada aggregate sigue una estructura estricta Domain ← Application ← Installation con dependencias únicamente hacia dentro. Las capas de dominio tienen cero o mínimas dependencias externas; las capas de aplicación dependen únicamente de contratos de dominio y servicios foundation transversales; las capas de instalación conectan implementaciones específicas de plataforma.

  • Aislamiento del motor mediante assembly definitions. Los assemblies core de negocio declaran noEngineReferences: true, garantizando a nivel de compilación que ninguna API de Unity se filtre hacia la lógica de dominio o aplicación.

  • Principios SOLID de extremo a extremo. Aggregates de responsabilidad única, contratos de servicio segregados por interfaz, extensión open/closed mediante installers abstractos y factory ports, e inversión de dependencias mediante interfaces agnósticas de plataforma.

  • Vocabulario Domain-Driven Design. Las entidades contienen estado mutable con transiciones protegidas, los value objects proporcionan identidad y snapshots inmutables, y los aggregates definen bounded contexts con puntos de integración explícitos.

  • Diseño de API orientado a casos de uso. Las operaciones orientadas al consumidor se encapsulan en clases de casos de uso tipadas con DTOs de entrada dedicados, agrupadas en contenedores inyectables para mantener grafos de dependencias limpios.

  • Patrón de snapshots inmutables. Todos los aggregates con estado exponen snapshots de solo lectura para consultas, garantizando que los consumidores no puedan mutar accidentalmente el estado interno.

  • Patrón de installer abstracto. Cada aggregate define un installer abstracto que declara el contrato de wiring; las capas concretas de plataforma (Unity, tests o targets personalizados) proporcionan implementaciones sin modificar código de negocio.

  • Comunicación inter-módulo basada en señales. Las señales de eventos tipadas fluyen a través de un dispatcher centralizado, manteniendo desacoplados los aggregates mientras permiten coordinación reactiva.

📦 Módulos

  • Global — Contratos foundation, eventos de ciclo de vida (exit/restart), jerarquía de interfaces de casos de uso, modelo de componentes para composición UI y base de installers abstractos consumida por todos los demás aggregates.

  • EventDispatcher — Sistema de eventos publish/subscribe tipado con acciones auto-registrables, clases de señales tipadas y descubrimiento basado en atributos.

  • Logging — Sistema configurable de logging con niveles de severidad, overrides de verbosidad por categoría, perfiles de routing, component loggers y soporte de salida a archivo/consola.

  • ServiceLocator — Resolución mínima de servicios tipados con implementación por defecto basada en diccionario.

  • Task — Contratos de trabajo asíncrono con criticidad, invocación de métodos mediante reflexión y resolución extensible de argumentos.

  • InitializationPipeline — Sistema de arranque basado en fases y tareas con seguimiento ponderado del progreso, gestión de fallos basada en criticidad y políticas de ejecución configurables.

  • Persistence — Jerarquía de almacenamiento por capas: key-value stores, blob stores basados en streams y append-only stores, todo ello detrás de contratos de plataforma intercambiables.

  • FilePersistence — Blob store basado en sistema de archivos con seguridad write-then-rename y resolución de rutas específica por plataforma.

  • PlayerPrefsPersistence — Key-value store ligero respaldado por Unity PlayerPrefs con codificación Base64.

  • GameSettings — Sistema de settings tipados (Boolean, Integer, Float, Selectable) con persistencia en repositorio y notificaciones de cambio de valor.

  • Checkpoint — Persistencia opaca de checkpoints binarios con slots nombrados (Slot1–3, Auto, Quick) y metadatos extensibles.

  • Score — Modelo dinámico de scoring multi-métrica con métricas ilimitadas basadas en claves, operaciones aritméticas completas y persistencia en repositorio.

  • Combo — Sistema de combos agnóstico del juego con snapshots inmutables y puntos de extensión virtuales para multiplicadores, timeout o comportamiento de degradación.

  • Character — Ciclo de vida de personajes basado en estados (Spawning → Active → Dying → Dead) con gestión de hit points, enums de estado heredables y snapshots inmutables.

  • GameplayEntity — Identidad de entidades basada en GUID con clasificación semántica y referencias ligeras entre sistemas.

  • GameSpawner — Spawning de entidades con seguimiento mediante handles y gestión del estado del pool mediante un factory port para la estrategia de instanciación.

  • Stage — Ciclo de vida principal de stages (NotStarted → InProgress → Completed/Failed) con resolución de spawn points y contratos de autoría de rail paths.

  • Wave — Progresión secuencial de waves con detección automática de limpieza y señales de ciclo de vida en cascada.

  • Timer — Gestión de temporizadores con nombre compatibles con modos countdown, elapsed y repeating, con progreso normalizado y señales de ciclo de vida.

  • GameMode — Máquina de estados de modos de aplicación (Menu, Game, Pause) con estrategias de pausa configurables y transiciones impulsadas por señales.

  • GameSession — Seguimiento del ciclo de vida por sesión con fuentes de tiempo agnósticas al motor y acumulación de tiempo basada en ticks.

  • AudioPlayer — Reproducción de audio multi-categoría con routing mediante gateways, pooling de canales y operaciones orientadas a casos de uso.

  • MusicPlayer — Gestión de música de fondo con operaciones de play, stop, fade y crossfade.

  • SoundMixer — Gestión de volumen y mute por grupos con integración reactiva con game settings.

  • GameGraphics — Gestión reactiva de calidad, resolución y fullscreen impulsada por cambios en game settings.

  • SystemConfiguration — Detección de capacidades hardware con generación de perfiles de calidad recomendados.

  • PlayerInput — Abstracción de input agnóstica de plataforma con cambio de action maps y contratos de binding de acciones.

  • Ui — Jerarquía de vistas, sistema de themes/styles y modelo de componentes para construcción de UI composable e independiente del motor.

  • Menu — Sistema de menús basado en stack de navegación con configuración específica por menú y señales de ciclo de vida.

  • Modal — Diálogos modales configurables con factories de botones, resultados basados en callbacks y señales de confirmación preconstruidas.

  • GameUi — Gestión abstracta de HUD y pantallas de resultados mediante delegación presenter-port.

  • ViewBrowser — Navegación forward/back entre pantallas con consultas de estado.

  • Localization — Gestión del idioma del juego y de voces con cambio automático impulsado por settings.

  • SequencePlayer — Motor genérico de orquestación de ejecución ordenada para iteración de stages basada en completado.

  • CutscenePlayer — Reproducción cinematográfica con stages temporizados (fade, timeline, wait, dialog) construidos sobre la base del motor de secuencias.

  • GameRail — Registro de rail paths con nombre y seguimiento de progreso normalizado para movimiento on-rails.

  • GameWeapon — Mecánicas de trigger, cambio de fire mode y seguimiento de cargadores y munición mediante snapshots de solo lectura.

  • ProceduralExpression — Sistema de animación procedural basado en datos con composición de poses en capas, animación de materiales/transforms, activación basada en reglas, acciones discretas y soporte de ajuste en tiempo real.

  • Shared — Constantes transversales (service names, module labels, context identifiers) y clases utilitarias (parsing, reflection, generación de GUIDs).

🛠️ Herramientas

  • Generador de documentación API basado en DocFX. Un generador de documentación integrado, accesible desde Tools → Serenity → Docs, compila todos los assemblies utilizando documentación XML de Roslyn y genera un sitio estático navegable de la API mediante DocFX, con instalación automática, generación de configuración y soporte para templates personalizados con branding.

  • Herramienta de configuración de Procedural Expression. Un asistente de configuración en un solo clic (Tools → Serenity → Procedural Expression → Setup Minimal Idle) detecta automáticamente los huesos del esqueleto, genera todos los assets de configuración necesarios y conecta un perfil de animación procedural a cualquier prefab, dando soporte a personajes riggeados, objetos simples, props y elementos UI.

  • Inspector de diagnóstico del Asset Prefetcher. Un inspector personalizado de Editor para el servicio de prefetch proporciona refresco de caché, limpieza, exportación al portapapeles, visualización de diagnósticos, polling con auto-refresh y visualización por colores de categorías de assets.

  • Inspector de configuración del sistema. Un inspector personalizado para settings de configuración del sistema proporciona una interfaz completa para controlar tiempos de recopilación de datos, alcance y ajuste de heurísticas.

  • Inspectores de Menu y Modal. Inspectores personalizados de Editor para vistas de menú y componentes modales proporcionan visualización de configuración en modo solo lectura, gestión de bindings de señales e interfaces de configuración de botones.

  • Configuración basada en ScriptableObjects. Los perfiles de políticas de prefetch, perfiles de procedural expression, state keys, layers, acciones, reglas, configuraciones de audio, definiciones de game settings y tablas de localización se crean como assets ScriptableObject, permitiendo configuración por parte de usuarios no programadores y presets versionables.

  • Patrón de installer abstracto para wiring de plataforma. Cada aggregate define un installer abstracto con dependencias explícitas; los installers concretos específicos de Unity gestionan la creación de MonoBehaviours, la integración con Addressables y el registro en el service locator.

  • Panel de depuración de Procedural Expression. Un overlay GUI en runtime (activable mediante F12) muestra valores live de state keys utilizando sliders codificados por color, indicadores de rango y controles de reset para realizar ajustes en tiempo real durante el Play Mode.

  • Custom property drawers de Procedural Expression. Drawers personalizados para referencias de Bone IDs con selección mediante dropdown consciente del perfil, editores de reglas con configuración inline de condiciones y editores de perfiles con validación y visualización de propiedades derivadas.

🎯 Propósito

Serenity existe para eliminar el boilerplate recurrente que acompaña a cualquier proyecto de Unity: wiring de persistencia, gestión de settings, routing de audio, secuenciación de inicialización, transiciones de modos y plumbing de eventos. En lugar de proporcionar sistemas gameplay cerrados u opinados, Serenity ofrece la columna vertebral arquitectónica — contratos limpios, límites por capas y módulos componibles — sobre la que se construye el código específico de cada juego.

Al imponer un aislamiento estricto del motor en las capas core, Serenity garantiza que la lógica de negocio siga siendo testeable fuera de Unity, portable entre plataformas y resistente a cambios en la API del motor. El patrón de installer abstracto permite sustituir un backend de persistencia o un sistema de input implementando una única interfaz, sin necesidad de refactorizar un árbol entero de dependencias.

Cada módulo sigue las mismas convenciones estructurales: entidades de dominio con transiciones de estado protegidas, snapshots inmutables para consultas seguras, clases de casos de uso con entradas tipadas y puntos de integración basados en señales. Esta consistencia reduce el tiempo de onboarding y hace que los patrones entre módulos sean reconocibles de inmediato.

Serenity no es una plantilla de juego. No proporciona personajes, niveles ni condiciones de victoria. Proporciona la base que hace que esos sistemas sean más limpios, más rápidos de construir y más fáciles de mantener a lo largo de toda la vida útil de un proyecto.