Changelog
Latest updates and improvements to Serenity.
1.3.0 — Leaderboards, Game Saves, Data-Driven HUD & the Rebuilt Serenity Hub
This release is about your players' data: putting it on screen and keeping it safe. A complete leaderboard stack, a full game-save system with slots and permanent progress, and an authorable HUD with a visual builder and its own animation system — plus gamepad motion (gyro) support, the Serenity Hub rebuilt as a searchable workspace, and new wizards that configure all of it without touching code.
Added
- Leaderboards (new module) — a complete high-score stack, end to end. The five-step Create Leaderboard wizard (Tools ▸ Serenity ▸ Create ▸ Leaderboard ▸ Create Leaderboard) walks you through it: pick a preset ("High Score", "Best Time"…), pick the score your game already tracks, pick where the data lives — device storage, human-readable JSON files, an embedded SQLite database, your own HTTP service, or a direct Postgres/MySQL/MongoDB connection — and optionally get a ready-to-navigate leaderboard screen wired into an existing menu. Ranking is deterministic with proper tie handling, all 8 shipped themes render the board in their own visual language, and a misconfigured backend never breaks your game: it logs a warning and falls back to device storage.
- Game saves & permanent progress (two new modules) — GameSave gives your game a configurable number of save slots, each an extensible document of typed sections (inventory, milestones, completion — plus anything your game registers). Save-slot menus list label, timestamp and completion instantly, without loading whole saves. GameProgress keeps what must survive slot deletion — completion counts, unlocked extras — so wiping a playthrough never erases what the player has earned. Checkpoint quicksaves travel inside the active slot automatically, cloud saves are a backend choice rather than extra code, and two wizards (Create Game Save Settings, Create Game Progress Settings) configure everything, backend included.
- Data-driven HUD with a visual builder — health bars, ammo counters, timers and any live stat, authored as data instead of hand-wired scripts. Elements anchor to nine screen positions with independent grow direction, bind to live game data, and draw through seven display styles — text, number, time (including the arcade MM'SS"CC style), stack, segmented, gauge and icon set. Author for player 1 and get player 2 mirrored automatically. HUD Builder guides the data binding so only valid chains can be authored, and HUD Preview is a true editing surface: drag to move, pull handles to scale, rotate Photoshop-style, snap with Ctrl — every gesture is a single undo step, at any resolution and theme. A dedicated validator flags bindings broken by renames before your players ever see a blank element.
- HUD elements nest and animate — elements can be grouped inside layout boxes that arrange their children automatically (spacing, alignment, padding), a number can split into a big integer part and a small fraction part, and everything animates through fifteen ready-made presets — Punch, Pulse, Heartbeat, Blink, Wiggle, Spin, Shake, Slide in, Fade in, Damage flash, Ghost pulse and more — covering scale, rotation, position, visibility and color. Animations trigger on value changes, signals or on show, with per-entry cooldowns, all authored in the builder's new Animation tab and validated like everything else.
- Animation Hub (Tools ▸ Serenity ▸ Browse ▸ Animation ▸ Animation Hub) — one searchable window for every animation in the project: model-embedded clips, standalone clips, animator controllers with their states and transitions, and procedural animation. Create and edit clips and controllers in place, preview a clip live on the actual model with play and scrub controls, and simulate procedural profiles against real state values — without ever touching your scene or your assets.
- Gamepad motion (gyro) support — DualSense, DualShock 4 and Switch Pro now expose gyro and accelerometer readings, with drift calibration built in. The Controls settings menu gains Gyro Aim and Gyro Sensitivity options your players can use out of the box, and the new Gamepad Motion Monitor window shows live motion values per connected pad for tuning.
- Score, leveled up — declare score metrics on a settings asset instead of registering them in code (the new Score Settings wizard authors it), feed a metric from how far something travels with the new Transform Distance Meter component, and award fixed amounts from any trigger with the new AddScoreSignal — all zero-code. Score also now installs through the Initialization Pipeline like every other system.
- Leaderboards meet the HUD, no code required — show a board's #1 entry or the local player's personal best directly on the HUD through bindable services and a best-entry cache component; submit the current score from any trigger — a button, a signal reaction — through the new submit component's single
SubmitNow()call; and render any decimal precision a score needs. - Database Drivers window (Tools ▸ Serenity ▸ Validate ▸ Database Drivers) — choosing a real database backend requires hand-installed driver DLLs; this window lists exactly which files each backend needs, marks what is already installed, links every missing one to its exact NuGet package and version, and only offers to enable the backend once the set is complete. No more discovering dependencies one error at a time.
- The Serenity Hub, rebuilt from the ground up — the package's front door is now a full workspace: six views (Home, Create, Validate, Browse, Advanced, Learn), a card grid where every tool shows its icon and description, favorites and recents pinned to Home, and Ctrl+K global search across all 89 tools. Validation never runs behind your back anymore: results are cached with their timestamp, and scans run only when you ask.
- AI Prompt Builder (Tools ▸ Serenity ▸ AI ▸ Prompt Builder) — a wizard that interviews you about what you want to build and generates the optimal prompt for your AI agent. It scans the project so the prompt extends your real assets instead of creating from scratch, keeps a personal library of reusable instructions, and delivers the result to the clipboard, a file, or straight into your agent as a slash command. Its intents now include a free-form request — describe anything in plain language and the prompt routes the agent to the right modules — and a dedicated HUD design intent.
- Add Language wizard — add a locale to your existing translation tables in one guided pass: filterable, paged grids with a reference-language column for context, optional wiring into your language settings, and atomic rollback if anything fails. It never invents new keys.
- Documentation that wears your game's brand — the generated docs site now takes its title, logo text, tagline, footer and accent color from your Player Settings automatically, and the new Docs Branding window (Tools ▸ Serenity ▸ Docs ▸ Docs Branding) lets you customize all of it with a live preview.
- Sample scene generator (Tools ▸ Serenity ▸ Create ▸ Samples ▸ Generate Sample Scene) — generates the demo scene on demand: canvas, diagnostics HUD, a toast host and a button wired to show a toast. Safe to re-run.
- New validators — Addressable Keys catches stored asset paths that would silently fail to load at runtime, with a one-click fix; Localization Keys gains a live locale preview and per-locale warnings for keys that exist but have no translation yet.
- The Signal Flow Browser now sees everything — signal emitters and reactions placed in prefabs and scenes, action definitions, and menu or modal option signals all show up as dispatchers and reactions. A signal fired only from a menu option no longer misreports as "Unused".
Improved
- Every signal picker is searchable — the long flat menus for choosing a signal type are replaced by a searchable dropdown, everywhere.
- Every wizard, one experience — all creation wizards now share the same step engine, so the breadcrumb is freely navigable in both directions in every one of them: any step you've already visited is one click away.
- Fire Now in the Modal Builder — preview the modal you're authoring while Play Mode runs, before creating any asset.
- Create Player Input can author the Input Actions asset — the wizard now offers "Create New…" instead of requiring an existing .inputactions file.
- Rails can be bound at runtime —
BindRail(railService, railId)on the rail follower and driver enables per-instance rails, for example pooled NPCs each following their own path. - Bring your own adaptive-trigger backend — register a custom backend from your own code (for example a licensed console SDK) and it survives package updates; a failing backend falls back gracefully instead of breaking feedback.
- HUD Builder arguments are type-aware — board ids, score keys and field selections render as dropdowns populated from your project's own assets instead of free-text fields, and they refresh live as you add boards or metrics.
- Positioned sounds are audible by default — a one-shot played at a world position without authored spatial settings now gets a sensible rolloff instead of Unity's default, which made a cue fired from twenty meters away practically inaudible.
- Editor text fields commit when you click away — typing a value and clicking Create or Next no longer discards the edit still sitting in the field; sustained typing still collapses into a single save and a single undo step.
- A cleaner Tools menu — internal development-only tooling no longer appears in your project.
Fixed
- Time values with hours now format like a clock: 3600 seconds renders as
1:00:00. - All Addressables operations now run on the Unity main thread, eliminating rare, hard-to-diagnose errors when entering Play Mode while assets load during boot.
- Retag All (Plugin) no longer registers file types the Addressables build cannot pack, and now also cleans up entries that no longer belong — running it once repairs an already-affected project.
- Starting a wave no longer releases pooled actors that other systems spawned through the same service.
- A Signal Emitter can now be wired directly into a Button's On Click (new
DispatchSignalmethods usable from UnityEvents). - The asset-path field in the Inspector no longer breaks a valid Addressables address when you edit it.
- A gamepad whose connection fails now degrades to silence instead of surfacing errors mid-game.
- Package upgrades are more resilient: a stale development marker accidentally copied into a game project is detected and cleaned automatically, and project validation no longer reports false branding errors on clean projects.
- Generated docs now apply the configured accent color, and the docs landing page no longer links to a page that doesn't exist in game projects.
- Leaving pause through Resume, Back to menu or Restart now notifies pause listeners exactly once — anything tracking pause state through signals no longer gets stranded in a paused state.
- Reading a BOOL game setting with an authored default no longer throws.
- Performance: steady per-frame allocations in the HUD and procedural-animation path were cut by roughly two thirds, and a diagnostic-logging hitch during pooled enemy spawn bursts is gone.
Upgrade notes
Most projects update with a regular package import. If you've extended Serenity, a few API changes may need a small touch:
- Custom
IServiceLocatorimplementations must add the non-genericTryGet(Type, out object)member — for a dictionary-backed locator it's a one-line delegation. - Custom
IUiThemeComponentsimplementations must add aHudElementTemplateproperty; returningnullis valid and simply skips HUD theming. - Custom sequence player subclasses that branched on
stage.StageTypemust comparestage.Kind(a string) instead. Existing sequence assets migrate automatically on first load — no manual step required. - Custom initialization pipeline profiles must add the four new install tasks (
InstallScore, thenInstallLeaderboard— beforeInstallMenu— plusInstallGameSaveandInstallGameProgress), and game installers should resolveIScoreService,ILeaderboardService,IGameSaveServiceandIGameProgressServicelazily, since they now register during the pipeline. - The ProceduralExpression module is now called ProceduralAnimator — update
using Serenity.ProceduralExpression...directives, asmdef references to the old assembly names, and any recipe or serialized type string that names the module. Scenes, prefabs and assets keep resolving without reimport, since script identities are preserved. - Custom procedural layer subclasses declare which channels they write through a one-line
DrivenChannelsoverride, andRegisterTransformTargetnow takes an explicitallowPositionOverrideargument. - Several designer-facing asset types now generate a stable internal Guid on first load — re-save those assets once to persist it.
- If the very first import of 1.3.0 reports "multiple assembly definition files": delete the duplicate
.asmdeffile whose.metaGUID differs from the same-named one shipped by the package, let the editor recompile, and the package's self-cleaning completes the rest automatically. This can only happen once, on the import that delivers the fix — later updates reconcile renamed modules and folders on their own.
1.2.2 — Effortless, Self-Cleaning Package Updates: One Import, Zero Leftovers
Improved
- One-import updates — moving up to the latest Serenity is now a single, clean import. The package tidies up after itself automatically, so files retired in newer versions don't linger in your project or get in the way.
- Hands-off upgrade flow — the update applies quietly in the background and leaves everything you've configured exactly as it was, so you can grab the newest Serenity and get right back to building.
Upgrade note
Updating from any previous version is a simple package import — no manual folder deletion and, in the common case, no editor restarts required.
1.2.1 — Service Extension Creator: Extend Anything (Services, Stores, Repositories, Gateways, Factories, Installers & Your Own Classes) + Self-Cleaning Package Upgrades + Opt-In Gameplay Readiness Gate + Technical-Debt Sweep
Added
- Service Extension Creator — a new wizard (
Tools ▸ Serenity ▸ Services ▸ Service Extension Creator) that generates ready-to-use, fully wired code to extend almost anything in Serenity: services, persistence stores, repositories, gateways, factories — and even your own custom classes. No more hand-wiring boilerplate to add your own logic on top of the framework. - Effortless package updates — updating Serenity is now a simple, single import. The package cleans up after itself automatically, so old or renamed files from previous versions no longer stick around and cause conflicts.
- AI agent skills installer — a new tool to install Serenity's AI coding assistant skills directly into your project for Claude Code, Cursor, GitHub Copilot, and other AI coding tools.
Improved
- Smoother loading screens — the loading progress bar now animates cleanly to 100% before the game reveals, instead of feeling abrupt on fast loads.
- Gameplay readiness gate is now opt-in — projects that don't need to wait for extra gameplay setup before showing a level no longer pay any unnecessary loading delay.
- Sound pooling, split-screen camera shake, menu alignment, and rail movement all received polish and correctness improvements under the hood.
Fixed
- Menu and modal show/hide sounds now play correctly.
- Backing out of a menu now plays the proper "cancel" sound instead of the wrong one.
- Minor gameplay session and weapon-reload edge cases were tightened up.
Cleanup
- Removed unused, non-functional legacy code to keep the framework lean.
Upgrade note
Updating from any previous version is now a simple package import — no manual folder deletion or editor restarts required in the common case.
1.2.0 — Game Camera System, Theme Builder, Setup Assistant, Serenity Hub, Safe Asset Delete, Live Cutscene Preview & Visual Signal Flow
This release is about two things: getting you from an empty project to a running game faster than ever (Serenity Hub, Setup Assistant, Theme Builder) and protecting your project while you work (Safe Asset Delete, Validate Everything, live previews). It also ships a brand-new Game Camera module with local-multiplayer split-screen, and Serenity's entire business core is now engine-agnostic — your game rules no longer depend on Unity types.
Added
- Game Camera system (new module) — a complete camera management layer behind one service,
IGameCameraService. It keeps a registry of every camera in the game (auto-discovered on scene load, even inactive or unreferenced ones), switches the active camera without breaking your rigs — only theCameracomponent is toggled, never the GameObject, so a CinemachineBrain or any sibling script keeps running — and gives you local-multiplayer split-screen out of the box, with automatic viewport layouts that recalculate as players join and leave. Register cameras with zero code viaUnityGameCameraRegistrar, or exclude one from discovery with aUnityGameCameraExcludemarker. - Theme Builder wizard (Tools ▸ Serenity ▸ UI ▸ Theme Builder) — a complete, ready-to-run UI theme from scratch in one pass. Pick three colors, a font, a background and a selection style, and it generates the theme asset plus 20 prefabs (buttons, sliders, dropdowns, toggles, labels, loading bars, modals, toasts and more) — including generated show/hide and selection animations with None / Subtle / Elegant / Energetic presets and live previews. Everything is auto-registered into Addressables and can be set as your active theme immediately. No sample themes required, no cloning, no manual wiring.
- Setup Assistant (Tools ▸ Serenity ▸ Setup Assistant) — from an empty project to a playable boot → main menu → gameplay → pause loop in five guided steps. It validates your choices live, shows a real dry-run preview before writing anything, and every asset it creates is idempotent — re-running never duplicates your work.
- Serenity Hub (Tools ▸ Serenity ▸ Hub) — the package's "start here" front door: a status dashboard for required Unity packages, installer wiring and overall project health, plus a categorized launcher for the 50+ Serenity tools. Every row deep-links into the real tool that fixes it. Opens automatically on first import.
- Safe Asset Delete — deleting an asset that other assets still reference no longer leaves silent dangling references behind. A review window lists every affected asset (click to inspect it), and Delete & Clean removes the asset and nulls out every stale reference for you, logging exactly what was cleaned.
- Signal Flow Browser, redesigned as a visual diagram — see your event flow as a node diagram that reads cause → signal → effect, with color-coded cards, filter chips (In Use / Unused / Dispatcher / Modal / Reaction), click-to-highlight connections and jump-to-asset or jump-to-script from every node. Finding the signals your project no longer uses is now one click.
- Live cutscene preview — the Cutscene Outline now previews your cutscene inside the editor window: scrub the timeline, press play, and watch fades and Timeline stages rendered through the rig's own camera — no Play mode, no changes to your open scene.
- Validate Everything (Tools ▸ Serenity ▸ Validate Everything) — one dashboard aggregating every project validator, including two new ones that catch assets missing their Addressables labels and audio definitions missing from their registries — the classic "why doesn't my sound play?" gaps. Fixable findings get one-click Fix buttons with a confirmation naming exactly what will change.
- Inline post-creation checklists — audio clip and music track assets now show their Addressables-tagging and registration status directly in the Inspector, each with a one-click fix — so a missing registration surfaces while you author, not at runtime.
- Installer status at a glance — the Serenity Installer inspector now groups its fields into Required and Optional and shows live status under each one: green when assigned, red when the game cannot boot without it, yellow when leaving it empty silently disables a feature.
- Safer wave authoring — a wave spawn entry's actor slot now only accepts prefabs and warns when it's empty, instead of letting you author a wave that silently spawns nothing.
- Engine-agnostic core — Serenity's entire business layer now compiles without Unity. Your game rules, settings and flows are written against pure C# contracts: easier to test today, portable tomorrow.
Fixed
- The pause menu no longer stays visible behind other menus when navigating from pause to another view (for example Options).
- Four shipped modals (End Game Session, Exit Application, Reset Settings, Restart Game) had their signal references silently broken by an earlier internal rename; they resolve again and stay visible to the Signal Flow Browser.
- Audio registration validation no longer falsely flags every registered clip and track, which also restores the one-click Fix (register) buttons.
- Dropdowns generated by the theme tooling now wire their selected value correctly, including its runtime translation.
- A handful of leftover Spanish editor labels and log messages were translated to English.
Upgrading from 1.1.x
This release includes breaking API changes (that's why it's 1.2.0). You don't have to hunt them down by hand: run Tools ▸ Serenity ▸ Migration ▸ Migrate to 1.2.0 — it scans your project's code, shows a before/after preview of every change with checkboxes, and applies only what you approve; anything ambiguous is reported instead of rewritten, and re-running it is always safe. An upgrade guide ships in the package for the few manual cases. Existing character config assets need a one-time retag and re-save — Validate Everything points at each one and fixes the tags for you.
1.1.4 — Feedback System (Vibration, LED, Adaptive Triggers, Screen Shake/Flash, Hit-Stop, Audio), Linux USB & Bluetooth + Windows Bluetooth Gamepad Output, GNOME/KDE Wayland Monitor Detection, Cutscene Wizard, Looping Cutscenes, No-Code Cutscene Triggers & Typed Cutscene Recipes
Added
Bluetooth gamepad output on Linux (DualSense & DualShock 4) — vibration, LED and adaptive triggers drive the pads over Bluetooth as well as USB. The raw-HID writers detect each pad's transport from the hidraw
HID_IDbus field and emit the report that bus requires: over Bluetooth the reframed, CRC32-checksummed reports (DualSense report id0x31with a rolling sequence tag; DualShock 4 report id0x11), over USB the plain0x02/0x05reports. The checksum is aPlaystationHidChecksumhelper — a reflected CRC-32 over an0xA2seed plus the report body, matching the kernelhid-playstationdriver. The Switch Pro's0x10report is identical over both buses.RawHidDeviceexposes aGetBusTypequery and aHidBusTypeenum for the transport selection.Bluetooth PlayStation output on Windows (DualSense & DualShock 4) — vibration and LED now drive a DualSense or DualShock 4 over Bluetooth on Windows, which previously did nothing: Unity's built-in PlayStation output is inert over Bluetooth, and Serenity's Windows path only carried the USB report through
ExecuteCommand. Each writer now sends the same Bluetooth report Linux uses (DualSense0x31, DualShock 40x11, both CRC32-suffixed) through a raw Windows HID handle (RawHidDevice) — USB stays onExecuteCommand, Bluetooth is routed through the sharedGamepadHidrawTransport.RawHidDevice(Windows) gained three fixes this required: it matches the Bluetooth device-path spelling (vid&0002054c_pid&0ce6) as well as USB (vid_054c&pid_0ce6); it resolves a pad by serial or, when the serial isn't in the path (as over Bluetooth), the single unambiguous VID/PID match; and it pads each write to the device'sOutputReportByteLength(read once viaHidP_GetCaps), which Windows requires for HIDWriteFile. The DualSense additionally needs a one-timeRELEASE_LEDSreport before the first colour report, or its lightbar ignores colour and stays in its power-on state (the DualShock 4 lightbar responds to its flags byte directly). Validated on hardware over Bluetooth (both pads). (Bluetooth input on Windows is Unity's own HID backend — it works once Windows finishes installing the pad's HID interface; a half-installed pairing shows the controller but streams no input, fixed by removing and re-pairing it.)GNOME & KDE monitor detection on Wayland —
LinuxSystemMonitorsProviderdetects the multi-monitor layout across the major Wayland compositors by trying several backends in priority order and taking the first that returns data:swaymsg(wlroots/Sway),wlr-randr(other wlroots compositors such as Hyprland/river),kscreen-doctor -o(KDE Plasma / KWin) and theorg.gnome.Mutter.DisplayConfig.GetCurrentStateD-Bus method viagdbus(GNOME). GNOME and KDE Wayland sessions get correct per-monitor position, resolution, refresh rate and primary-display flag. EDID-based identity (manufacturer/model/serial) comes from/sys/class/drmfor every backend.Feedback system — a new module for game feel, with one caller-facing entry point,
IFeedbackService(Serenity.Feedback.Application). A piece of feedback is a definition (a list of effects authored as one asset) played by id:Play("Hit")fires it on the pad that most recently acted, and global enable and intensity scaling live in exactly one place (SetGlobalEnabled/SetGlobalIntensity, applied to every impulse). Targeting is multiplayer-aware — the same definition can be addressed at the acting pad, a specific joined player (PlayForPlayer), a specificPlayerInput(PlayForPlayerInput), or a specific device (PlayForDevice) — andStopAllcuts every channel and pad at once. The core (definitions, effects, intensity math, scaling) is engine-agnostic (Serenity.Feedback.Domain/Serenity.Feedback.Application, deliberately noUnityEnginetypes); the Unity side (Serenity.UnityFeedback.Infrastructure) provides the channels, gamepad output, settings and editor tooling.Eight feedback effects — a definition composes any of: Gamepad Vibration (dual low/high-frequency motors with a hold duration), Gamepad LED (DualSense light-bar colour), Gamepad Adaptive Trigger (DualSense; Resistance, Weapon or Off mode with start/end travel and strength), Screen Flash (full-screen colour flash with an authorable alpha-over-time envelope, on unscaled time so it survives a hit-stop), Gameplay Hit Stop (brief time-scale dip on impact), Screen Shake (Camera) and Screen Shake (UI) (decaying positional shake, world-space and screen-space), and Audio (Sound) — play an authored sound (referencing a
UnityAudioPlayerClipDefinition) through the audio player as part of the same cue, so a single definition fires rumble + flash + a sound together. Effects are authored inspector-side via[SerializeReference]FeedbackEffectAuthoringblocks (the layer that holdsColor,[Range]and tooltips) and converted to the pure effects; each effect is handled by its own channel, and every haptic/visual impulse is scaled by the global intensity before output. Audio is the exception — it is independent of the vibration enable/intensity settings (it plays even when controller vibration is off and its volume is never attenuated), expressed through a per-effectBypassesGlobalGateopt-out on the effect contract so the service gates each effect individually rather than the whole definition.Cross-platform gamepad output (DualSense / DualShock 4 / Switch Pro) — Serenity drives vibration, LED and adaptive triggers by owning the controller's HID output report directly. The DualSense writer carries vibration, LED colour AND both adaptive triggers in a single USB report, so a vibration or colour update no longer clobbers an active trigger effect (it keeps per-device state as the single source of truth and re-emits the whole report on every change); the DualShock 4 writer combines vibration and light-bar colour the same way; and a streaming Switch Pro service drives HD vibration and the Home-button LED over a raw HID handle (the pad's vibration is not latched, so it is streamed at ~100 Hz on a background thread, with intensity mapped through a perceptual curve). Feedback routes to the device that actually triggered the action via an acting-device tracker, so in local multiplayer each player's effects land on their own pad, and identical pads are disambiguated by serial.
Linux gamepad support — on Linux, Unity's input backend cannot send HID output reports, so Serenity writes LED / vibration / adaptive-trigger reports straight to the controller's
/dev/hidrawNnode (the same path the Switch Pro uses on every OS), covering DualSense, DualShock 4 and Switch Pro over both USB and Bluetooth (the per-bus report selection is detailed above). The Switch Pro face buttons are also mapped on Linux's SDL backend (which exposes them by Nintendo label rather than physical position) sobuttonSouth= the physical bottom button as on every other platform.No-code feedback trigger —
PlayFeedbackSignalis the event-dispatcher bridge to the service: dispatch it (e.g. from the existing no-codeSignalEmitterComponent, or anyEventDispatcherAction) with a definition id and optional player/device targeting, and the feedback plays — so "when signal X happens, vibrate / flash / shake" needs no hand-written code. AFeedbackDefinitionScriptableObject (Serenity ▸ Feedback ▸ Feedback Definition) holds the authored effect list, and a workedStartGameFeedbackexample (StartGameFeedbackActionreacting toStartGameFeedbackActionSignal) ships underEXAMPLES.Menu feedback — menu navigation plays feedback no-code: a configured definition fires when the selected option changes (
MenuTickDefinitionId) and when an option is submitted (MenuSubmitDefinitionId), both read from the feedback settings asset, so menus give haptic/visual response on a controller without any per-menu wiring (and stay silent when no defaults are configured).Feedback Builder & inspectors — Tools ▸ Serenity ▸ Feedback ▸ Create Feedback opens a Feedback Builder window that authors a
FeedbackDefinition(pick effects, set their fields) and creates the asset; theFeedbackDefinitioninspector renders the effect list through a dedicated effect-list GUI (add / remove / reorder effect blocks), and aUnityFeedbackSettingsasset (Serenity ▸ Feedback ▸ Settings) configures the global defaults including the menu tick/submit definitions.No-code feedback trigger from the builder + typed
feedbacksrecipe section — Create Feedback now also emits aUnityEventDispatcherSignalDefinition(<Name>Trigger.asset) pre-wired to dispatchPlayFeedbackSignalfor the new definition, so a designer drops it on aSignalEmitterComponentand plays the feedback with zero code and no generated script (independent of, and alongside, the existing Signal+Action code path — both are now optional toggles).FeedbackDefinitionalso becomes a first-class typedfeedbacksrecipe section (importer/exporter/template-generator/discovery), round-tripping its polymorphic[SerializeReference]effect list through the shared codec, with an optionalgenerateTriggerflag that creates the same no-code trigger on import. A full Feedback aggregate cookbook (Documentation/Cookbooks/Gameplay/Feedback.md, the 12-section template) ships alongside it, and the Cookbooks README module-map + SO index,ConfiguringSerenitySystems, the docs root, and theserenity-cookbooksskill router were updated to route Feedback.Installer & DI wiring —
UnitySerenityInstaller.InstallFeedback()registers the feedback service (UnityFeedbackInstaller, depending on the game-settings and event-dispatcher services) and is run from the boot initialization pipeline (a newInstallFeedbacktask). The module ships its own Addressables label (module:feedback) so its assets load at boot like every other Serenity module. Adaptive-trigger output is pluggable behind a backend interface — a PC HID backend drives the DualSense over USB on desktop, with a PS5-SDK backend scaffolded for console.Cutscene Wizard (Tools ▸ Serenity ▸ Cutscenes ▸ Cutscene Wizard) — a stepped IMGUI builder for cutscenes (Template → Stages → Rig → Trigger → Create), modeled on the Settings Wizard. It seeds the stage list from a preset (Splash
FadeIn→Wait→FadeOut, Timeline cutsceneFadeIn→PlayTimeline→FadeOut, or Blank), lets you edit each stage (type, duration, fade colour, Timeline) with reorder/add/remove, optionally creates a rig prefab (aGameObjectwith aPlayableDirector, playOnAwake off) or assigns an existing one, and on finish registers the newUnityCutsceneDefinitioninto the project'sUnityCutscenePlayerSettings.Definitions— finding or creating that settings asset — which closes the silent "authored a cutscene but it never loads because it wasn't added to the settings" gap. The window (CreateCutsceneWindow) only collects input; a pureCutsceneCreatordoes every asset mutation with rollback on failure (mirrorsModalCreator/GameSettingCreator), andCutscenePresetLibraryholds the templates.Boot / init-pipeline task generation — the wizard's Trigger step can also create a
Play{Name}UnityReflectionCallTaskDefinitionthat plays the cutscene from the initialization pipeline (the boot-splash path). It mirrors the shippedPlayCompanySplashScreentask — an instance call toUnityCutscenePlayerService.PlayAsync,resolveFromServices: true, the cutsceneIdas the single string arg — atDegradablecriticality so a failed splash never halts boot. The task is created next to the definition but not auto-inserted into a profile; add it to aUnityInitializationPipelineProfileafterInstallCutscenePlayer.No-code cutscene play trigger — the wizard's optional Trigger step generates a
{Name}ActionSignal+ an[AutoRegisterEventAction] {Name}Action(via the sameSerenityEventDispatcherActionScriptCreatorthe Modal Builder uses, with a cutscene-specificExecutebody inCutsceneTriggerScriptCreator). The action resolvesICutscenePlayerServicefrom theServiceLocatorBridge— the service is already registered in theServiceLocatorbyUnitySerenityInstaller.InstallCutscenePlayer— and firesPlayAsync(id)fire-and-forget (safe: the service self-bounds each stage and the whole cutscene with hard wall-clock timeouts). A designer then dispatches the generated signal with the existing no-codeSignalEmitterComponent, so "when signal X fires, play cutscene Y" needs no hand-written code. Cutscenes previously had no signal-driven trigger — only directICutscenePlayerService.PlayAsyncinjection.Looping cutscenes —
ICutscenePlayerServicegainsPlayLoopingAsync(id)/Stop(id)/IsPlaying(id): a cutscene can now run as a persistent, looping background sequence (menu backdrops, ambient scenes) instead of the one-shot staged pipeline.PlayLoopingAsyncinstantiates the definition's rig under the cutscene service (so it survives scene loads), sets the rig'sPlayableDirectortoLoopwrap mode and returns immediately; it is idempotent — re-playing an already-looping key is a no-op, never a duplicate rig —Stoptears the rig down, and looping playback deliberately bypasses the one-shot pipeline's per-stage and wall-clock timeouts (a loop has no end to time-bound). The Cutscene Wizard's Trigger step gained a Trigger kind choice: Play once (the existingPlayAsyncaction) or Play looping, which generates aPlay{Name}Actionand aStop{Name}Actionsignal/action pair so a looping cutscene can be started and stopped no-code.Timeline auto-create in the Cutscene Wizard — a
PlayTimelinestage can tick "Create a new Timeline for this stage" and the wizard creates an emptyTimelineAssetnext to the cutscene and assigns it, and bakes the first stage's Timeline into a newly created rig'sPlayableDirectorso the rig opens ready to author in the Timeline window (harmless at runtime —playOnAwakeis off and the service re-assigns per stage). Gated behind aSERENITY_TIMELINEversion define (com.unity.timelinein the editor asmdef) so the assembly compiles when the Timeline package is absent.Typed
cutscenesrecipe section — cutscenes are now a first-class typed section of a.serenity-recipe.json(likemenus/modals/audioClips) instead of riding the genericassetscodec. ARecipeCutsceneDtocarriesid/output/rigPrefaband an orderedstages[](id,stageType— aCutsceneStageTypename,duration,fadeColoras{r,g,b,a}, andtimelineas aPlayableAssetpath).CutsceneRecipeImporter(reflection-discovered, ordered betweenmenusandmodals) writes the private stage fields through aSerializedObjectand resolves the rig/Timeline by path;CutsceneRecipeExporterround-trips them back. The template generator emits a realisticFadeIn→PlayTimeline→FadeOutstub, the discovery registry exposes theCutsceneStageTypevocabulary, andexample.serenity-recipe.jsongains a worked cutscene. APlayTimelinestage with no Timeline imports but is reported as a warning.Cutscene documentation — the Cutscenes & Sequences cookbook (
Documentation/Cookbooks/Narrative/CutscenesAndSequences.md) was expanded from a field stub to the full 12-section aggregate template (domain model + hard-timeout bounds, the three authoring paths incl. the Wizard, the typed recipe section, installer/DI + service registration, the no-code trigger contract, ID contracts, a worked example, verification, and a source map). The recipe schema reference, the AI asset-generation guide, the docs README, and the Cookbooks SO catalog were updated to list the newcutscenessection and the Cutscene Wizard.Scene-scoped hierarchy queries —
UnityHierarchyUtilsgains multi-root, scene-wide search:GetSceneRoots,FindInSceneWithTag/FindAllInSceneWithTag, andFindInScene<T>/FindAllInScene<T>, each with an overload taking a specificSceneand a no-arg overload defaulting to the active scene. They walk every root GameObject of the scene and include inactive objects — the scenarios the existing single-root find helpers didn't cover.Claude Code skills shipped in-package — Serenity now bundles LLM-first Claude Code skills under
Assets/Serenity/Documentation/Skills/(so they ship in the.unitypackage) plus an installer that activates them: Tools ▸ Serenity ▸ AI ▸ Install Claude Skills (SerenityClaudeSkillsInstaller) copies each bundled skill folder into the project's.claude/skills/, where Claude Code actually discovers skills — aSKILL.mdleft underAssets/is inert, because Claude Code only scans<project>/.claude/skillsand~/.claude/skills. The first skill,serenity-cookbooks, is a router that makes an AI agent read the matching per-module Aggregate Cookbook before authoring or wiring any Serenity system (with hard rules to pull exact fields from the Project Recipe Template Generator and to retag Addressables + register audio after import). The installer skips Unity.metafiles and lives in the existingSerenity.PackageBootstrapper.Editorassembly alongside the package exporter; the regenerable install output (.claude/skills/) is git-ignored.
Changed
- The Cookbooks SO catalog now lists
UnityCutsceneDefinitionunder the typedcutscenessection (wasassets) with the Cutscene Wizard as its authoring tool.
Fixed
- Signal emitter never recovered from an early service lookup —
SignalEmitterComponentlatched its event-dispatcher and logger lookups as "resolved" before checking they succeeded, so an emitter that fired before boot finished registering the services (e.g. a logo-animation event during the splash) cached the failed null lookup permanently — and sinceSetActive(false/true)doesn't reset private fields, disabling and re-enabling the object didn't recover it: the trigger stayed silently dead (warnings included) for the whole session. The latch is now set only on a successful resolution, so the next dispatch retries and picks the service up once it's registered. - Primary input prompt ignored Screen Shake (UI) —
UnityPrimaryInputPromptViewFactorycreated the prompt's container as a plainTransform, butUnityUiShakeReceiveronly offsets theanchoredPositionofRectTransformdirect children of the root canvas, so the input prompt never moved during a UI screen-shake feedback. The container is now a full-stretchRectTransform(anchored to fill its parent), which also makes it a spec-correct UGUI element.
Infrastructure
- Added the
Serenity.Feedbacktest suites (EditMode) covering the engine-agnostic core:FeedbackIntensityclamping,FeedbackScalerglobal-intensity scaling, per-effectScaledoutput, and the feedback-target / definition-data DTOs. Extended with the audio gating contract:AudioEffectreportsBypassesGlobalGateandScaledreturns it unchanged, while the haptic effects stay gated. - Added
CutsceneRecipeRoundTripTest(EditMode) to theSerenity.ProjectRecipe.Tests.Editorsuite: import → assert the definition and its stages, export → assert the DTO, and an export → re-import-into-a-new-root round trip. Added a new Editor-onlySerenity.UnityCutscenePlayer.Installation.Editorassembly for the wizard. - Added
UnityHierarchyUtilsSceneTestscovering the new scene-scoped queries — roots-only enumeration, tag and component search across multiple roots (hit and miss), inactive objects, and empty/invalid scenes — against both an isolated freshly created scene and the active scene for the no-arg overloads.
1.1.3 — Cascade Menus, Theme-Driven Toasts & Project Recipe System focused on AI generation
Added
- Cascade menus — a multi-column, drill-down menu system where selecting an option opens a sub-column to its side. The engine-agnostic navigation model + builder lives in
Serenity.Menu.Application.Cascade(CascadeMenuModel,CascadeColumn,CascadeMenuPage,CascadeOption,ICascadeMenuContext); the Unity side (Serenity.Menu.Infrastructure.Cascade) adds the renderer, a pointer proxy for mouse, and three ScriptableObject definitions —OptionsCascadeMenu(static authored options with a per-leaf[SerializeReference] OnSelectSignal),DynamicCascadeMenu, andTargetCascadeMenu.UnityCascadeViewDefinition(Serenity/Menu/Cascade/Cascade View) makes a cascade a router-resolvable transition target like any composite view, so a menu option can transition into it; it builds under the canvas viaUnityCascadeViewFactory/UnityCascadeViewService(IViewProvider) /UnityCascadeViewInstaller, wired fromUnitySerenityInstaller.InstallCascadeViews().DefaultCascadeMenuContextruns a static cascade with no game code (a leaf's optional signal is dispatched on resolve, then the view returns to its opener).ICascadeMenuContext.Dispatch+OptionsCascadeMenu.OptionDefinition.KeepOpenOnSelectlet a terminal option fire its signal without closing the cascade. - Themed cascade rendering — the cascade menu renders through a designer-authored, per-theme
CascadeView.prefab(a newCascadeViewTemplateslot on the theme, authored for all 8 themes from each theme's own background + title font) instead of a hardcoded procedural panel, so it matches the active UI theme.UnityCascadePanel(modeled onUnityModalComponent) provides header + options-root slots,SetTitle/SetInteractable/SetOptions,ConfigureScroll(clamp to a visible count behind a mask), andAdaptWidth(auto-fit to the widest label, clamped to[MinWidth, MaxWidth], longer labels wrap).UnityCascadeViewDefinitionreplaces the inertPanelWidthwithMinWidth/MaxWidth+VisibleOptionsCount. The cascade also plays the theme'sIUiThemeSoundson navigate / submit / cancel and supports mouse hover-to-focus + click-to-select (a procedural fallback remains when a theme has no cascade template). A game-agnostic TESTING cascade sample (MENU → First Action / Submenu One → Choice A,B / Submenu Two → Choice C,D) and a "Cascade Menu Test" option inTestingMenuexercise it end to end. - Serenity UI widgets —
SerenityButton,SerenityGauge,SerenityImage,SerenityLabel,SerenityStatusPanelandSerenityUiContext(Serenity.Ui.Infrastructure.Widgets), runtime wrappers over the themed UI components;SerenityUiContext.CreateOptionComponentis what the cascade renderer uses to fill panels with theme-native submit components. - Project Recipe system (Tools ▸ Serenity ▸ Project Recipe Importer / Exporter / Template Generator) — author Serenity content as human-readable
.serenity-recipe.jsonfiles and turn them into real ScriptableObjects through the Unity Editor API (no hand-written.asset/.meta/GUIDs). The importer does idempotent create/update with Validate / Dry-Run / Import, covering typed sections (audioClips/musicTracks/menus/modals) plus a genericSerializedObjectcodec that round-trips every other Serenity SO including[SerializeReference]signal graphs; the exporter turns an existing project back into a recipe; the template generator emits the exact, drift-free recipe stub for any authorable SO. All three ship as an EditorWindow plus a headless CLI entry point, in a newSerenity.UnityProjectRecipe.Infrastructure.Editorassembly. - Theme-driven toast notifications —
UnityToastComponent(Add Component ▸ Serenity ▸ UI ▸ Toast), a transient, non-blocking notification that spawns a short message, holds, and removes it (unlike a modal, it never steals input). The visual is the active theme's toast prefab (composed from each theme's own Background + Label and wired into a newToastTemplateslot on the UI theme), so toasts inherit the project's fonts/look; when no per-component prefab is assigned it falls back to the active theme'sToastTemplatevia the service locator. The toast can fit-to-content or use a fixed size (a bool), and animation is fully prefab/Animator-driven — the component only spawns and toggles the prefab'sisShowingparameter (no code-based fade), so five themes (Serenity, Animated, Animated2, Futuristic, Writings) unfold via their own controller mirroring each theme's modal while themes without an Animator simply appear/disappear. The toast host lives in the UI root prefab (UnityUiSettings.Ui) on a high-sorting nested canvas, so it is present wherever the UI is instantiated. Fully no-code to trigger:Show(string)is wirable from anyUnityEvent, andShowToastSignal+UnityToastSignalReactionComponentcarry the message as an event-dispatcher payload — so "when signal X happens, toast 'Saved!'" needs no script. - Cutscene Player Settings inspector —
UnityCutscenePlayerSettingsEditor(aFoundationEditor) so the cutscene-player settings asset shows the standard Serenity inspector (header, Id validation, Guid, Definitions list) instead of Unity's default, and fills the asset's blank Id/Guid. - "Import → press Play" — self-registering project services + project-extensible Addressables — removes the two manual steps that remained after recipe import.
[AutoRegisterService](inSerenity.ServiceLocator.Application) marks a class exposingpublic static void Install(IServiceLocator);AutoRegisterServiceBootstrapdiscovers these across the loaded assemblies (mirroring[AutoRegisterEventAction]) and runs them late inUnitySerenityInstaller's bootstrap (per-installer try/catch — a bad service logs but never aborts boot), so a game's services self-register with no bootstrap MonoBehaviour in the scene.[SerenityAddressable("label")](inSerenity.Shared) opts a project (non-Serenity) ScriptableObject type into the auto-labeler, making its assets Addressable under the given label(s); the project loads them at boot withUnityAssetUtils.LoadAllFromAnyBlocking<T>("label")— no hand-wired Inspector reference. Together: a project can be authored by recipes and run with just import → press Play. - Headless project validation (Tools ▸ Serenity ▸ Validate Project (JSON), or headless
SerenityProjectValidationRunner.ValidateFromCommandLine -validationKind all -validationResult <path>) — runs the three project-integrity validators (Health Check empty/duplicateId/Guid, Missing References dangling object references, and Localization Keys) and emits the findings as JSON so an AI agent or CI can confirm a project is correctly wired — not just that a recipe imported — and self-correct. The exit code is1when there are errors (duplicate ids, dangling references) and0otherwise (localization gaps are warnings, so partial translation doesn't fail a build). Each validator's scan logic was extracted from its editor window into a shared, GUI-free engine (SerenityHealthCheckValidator/SerenityMissingReferenceValidator/SerenityLocalizationKeyValidator) over a commonSerenityValidationReport, so the windows and the headless runner report identically. - Discoverability registry (Tools ▸ Serenity ▸ Project Recipe Registry, or headless
SerenityDiscoveryRegistry.DumpFromCommandLine -registryOutput <path>) — a machine-readable "what exists" dump so an AI agent references real ids/types/enums instead of guessing them: every concrete event signal (with both full name and assembly-qualified name), every authored action id (theStartGame-style targets of a menu/modalACTIONoption, scanned fromUnityActionDefinitionassets), the code reactions ([AutoRegisterEventAction]), the authorable ScriptableObject types and their recipe section, the recipe enum vocabularies, the recipe sections, and a curated list of the semantic ID contracts (e.g.InitialViewIdmust equal a menu id). Discovery is reflection-based and decoupled (types resolved by name), so the dump stays correct as code changes; it's the lookup that prevents the silent<Invalid: …>failure an unresolved action id produces. - Headless recipe import + machine-readable report —
SerenityRecipeEngine.ImportFromCommandLineruns the full Validate / Dry-Run / Import loop with no Editor GUI (the symmetric counterpart to the existing export/template CLIs):-recipeFile(required),-recipeMode Validate|DryRun|Import(defaultImport),-recipeOutputRoot(optional override), and-recipeResult <path>(writes the report as JSON, even on failure). It exits with code0on success and1when there are blockers or errors, so CI or an AI agent can branch on the result. The report now also serializes viaSerenityRecipeReport.ToJson()— counts (created/updated/skipped), flags (hasErrors/hasBlockers), and per-itemmessages/actionswith enums written as their string names — so an agent reads outcomes and per-item problems directly and self-corrects. This closes the author → validate → import → read-result → retry loop end to end without a human in it. - Typed menu/modal signal wiring in recipes — the
menus/modalsrecipe sections now wire[SerializeReference]EventDispatcherSignals directly, no longer deferring them: per-optionsubmitSignals[](→UiOption.OnSubmitSignals) on both menus and modals, plus menu-levelonShow/onHide/onCancel(lists) andonSubmit(→EventToDispatchOnSubmit). A newRecipeSignalDtodescribes each signal as atype(the .NETFullName, matching the discovery registry) with optionalfields(aRecipeNode[]for a signal carrying serialized data — parameterless markers need onlytype). The newRecipeSignalCodecapplies and captures them by reusingRecipeSerializedPropertyCodec's managed-reference path (newly exposed asApplyProperty/CaptureProperty), so signals — including a signal's nested field graph — round-trip through both importer and exporter. Anullslot leaves the existing value untouched; a non-null list replaces it; an unresolvabletypeis reported in validation and left unset (never a null list entry). The Action system (valueType: ACTION) remains the recommended route for cross-system flow. - Localization recipe section — the
localizationsection of a.serenity-recipe.jsonnow generates real Unity Localization content (previously deferred/reported-only): it ensures the requested locales exist, creates or finds the String Table Collection, and upserts inline key/value entries ({ "key": …, "values": [ { "locale": …, "text": … } ] }— an array of pairs, sinceJsonUtilitycan't deserialize a map), idempotently and dry-run-aware. String tables with inline entries are covered; CSV import and Asset tables remain future additions. The importer (LocalizationRecipeImporter) ships in the localization assembly and is discovered by reflection, so the core recipe engine gains no dependency on the Unity Localization package — recipes without localization still build.SerenityRecipeEngine.CreateImporters()now auto-discovers section importers (sorted by a newOrder) instead of a hardcoded list. - Serenity documentation set (
Assets/Serenity/Documentation/) — recipe schema reference, an AI-agent asset-generation guide, per-system configuration docs, a Serenity application-flow + first-iteration bootstrap walkthrough, an MCP-automation guide, a wiring cookbook, and per-ScriptableObject cookbooks (Audio, Cutscenes, Events, GameMode/Boot, GameSettings, Gameplay, Localization, Logging, PlayerInput, System/Assets, UI). - Aggregate Cookbooks (
Assets/Serenity/Documentation/Cookbooks/) — 21 end-to-end, AI-facing docs, one per module, that document a whole system rather than a single ScriptableObject's fields: Character, Wave, Stage, ProceduralExpression, GameplayEntity, GameSpawner, Checkpoint, GameSession, Score, Combo, GameWeapon, GameRail, GameUi, GameMode (Gameplay), Ui, ViewBrowser (UI), AssetPrefetcher, ServiceLocator, Timer, Task, Persistence, FilePersistence (Core). Each follows a fixed 12-section template — What it is · Domain model & lifecycle · Authoring surface (Recipe SO vs scene MonoBehaviour vs runtime-only) · Config · Scene authoring · Installer/DI wiring · Signal contract · ID & cross-reference contracts · Composition · Worked example · Verification · Source map — written from the actual source, so they answer "how does an AI build a Wave system / manage a Character" (config + scene placement + DI + signals + cross-aggregate composition), the parts a per-SO field reference can't. Infrastructure modules with no asset (ServiceLocator, Timer, Persistence…) mark the N/A sections explicitly and document the service/DI API instead. The cookbooks are organized into category subfoldersCookbooks/{Gameplay, UI, Audio, Settings, Narrative, Core}/. - Complete 38-module map — the master
Cookbooks/README.mdnow links every Serenity module to its authoritative doc (the aggregate cookbooks plus the per-system reference docs for the rest), with a composition diagram showing how GameMode → GameSession → Stage → Wave → Character → Score/Combo/GameUi fit together. Nothing in the module list is undocumented.
Changed
- Media asset reorganization —
Assets/Mediamoved underAssets/Serenity/Media(themes, prefabs, fonts, generated views, sample menus); references bind by GUID, so the move is transparent. - Mixer Topology window overhaul — the routing diagram now auto-sizes multi-line cards, draws per-type icons and a legend, supports selectable nodes with a detail panel, and highlights/pulses connectors, replacing the earlier clipped fixed-size boxes.
Fixed
- Gamepad double-submit on menu transitions —
SetActionMapswitched thePlayerInputmap unconditionally, so a UI Show (e.g. a menu→menu transition) re-switched to the already-current "Menu" map, andSwitchCurrentActionMap's disable→re-enable ran the Input System's initial-state check, which re-firedperformedfor any control still actuated — a Submit press held across the transition was processed twice, landing on the freshly shown view's selected option. The switch is now skipped when the requested map is already current. (The cascade renderer applies the same press-release gate so the Submit that opened it doesn't immediately submit its focused option.)
Infrastructure
- Added the
Serenity.ProjectRecipe.Tests.Editorsuite (44 EditMode tests) covering the recipe importer/exporter round-trip, the genericSerializedObjectcodec, the template generator, recipe validation, theSerenityRecipeReport.ToJson()machine-readable report, theSerenityDiscoveryRegistrydiscovery dump, and typed menu/modal signal wiring (per-option + menu-level, parameterless and payload-carrying signals, with an export→re-import round trip). - Added
GameModeMusicBinderComponent,UnityToastComponent, andUnityAudioPlayerServiceplacement PlayMode tests. - Added the
Serenity.UnityValidation.Tests.Editorsuite covering the sharedSerenityValidationReport.ToJson()output and aSerenityProjectValidationRunner.RunAll()smoke test (all three validators run; selectable by kind).
1.1.2 — Authoring Tools (Modal / Game-Settings / Audio), Rich Modal Options, Addressables Retagging, Input Action Invoker & Comprehensive Test Coverage
Added
- Modal Builder tool (Tools ▸ Serenity ▸ Modal ▸ Create Modal) — generates a Signal + Action script (reusing the shared Action Script generator) plus a
UnityModalSettingsand aUnityActionDefinitionasset, all referencing the same generated signal. The signal type string is built deterministically (UnityActionDefinition.Signal=Type.FullName;UnityModalSettings.signalTypeName= full assembly-qualified name) so the signal picker matches them exactly. The modal button inspector was extracted into a sharedModalButtonsInspectorGUIused by both the editor and the tool. - Modal title/text runtime translation —
IsTranslatingTitle/IsTranslatingTextonUiShowModalParametersflow through toUnityModalComponent, which get-or-adds aUnityUiTMP_TextLocalizationUpdaterComponenton the title/text TMP at runtime (no prefab edit). Previously modal titles/text were never translated — only buttons were. - Show modal by id — modals can be shown by their configured id, complementing the parameter-driven show path.
- Rich modal options — modals now render the full menu
UiOption[]model instead of the submit-only button model. A modal carriesUiOption[] Options,ModalDirection Direction,OptionsGap,Scrollable, andVisibleOptionsCount, configured just like a menu — with per-interaction component construction (SUBMIT / SLIDER / TOGGLE / SELECTOR), runtime layout-group swap for direction, and aScrollRectviewport clamped toVisibleOptionsCount. Legacy modalButtonsare lazily migrated toUiOptions (InteractionType = SUBMIT) with all their signals preserved.ModalDirection.HORIZONTAL = 0(the opposite ofMenuDirection.VERTICAL) so every existing modal asset deserializes unchanged. - Multi-signal option submit —
UiOptionnow carries aList<EventDispatcherSignal> OnSubmitSignals(read viaUiOption.GetSubmitSignals()), so a single menu or modal option can dispatch several signals in order. The legacy singleOnSubmitSignalis kept for back-compat and lazily migrated. New options default to an emptyACTION(a no-op that just dispatches the option's submit signals). - Game Settings Wizard (Tools ▸ Serenity ▸ GameSettings ▸ Settings Wizard) — a stepped IMGUI wizard that authors
UnityGameSettingsDefinitionassets, with a preset library, live option auto-fill (fromQualitySettings/Screen.resolutions/Locales/AudioMixer), opt-in service wiring, and a "generate full recommended set" action. The wiring step writes the settingIdonto the matching service-settings key (graphics / localization / UI / sound-mixer) so the setting actually takes effect at runtime. - Batch audio import tools — Tools ▸ Serenity ▸ Audio ▸ Batch Import Sound Effects generates one
UnityAudioPlayerClipDefinitionper selected file; Batch Import Music Tracks generates oneUnityMusicTrackDefinitionper file with shared fields plus a per-track Advanced loop foldout (tail-preserving, time/bar region, fade). - Audio Channel Manager (Tools ▸ Serenity ▸ Audio ▸ Audio Channel Manager) — a mixer ↔ Serenity relationship view that analyzes inconsistencies, creates channels/groups, and deletes them with a dry-run plan + Undo.
- Addressables Retag Selected window (Tools ▸ Serenity ▸ Addressables ▸ Retag Selected…) — lists retag-eligible assets under any dropped/browsed folder, previews the labels each would receive, lets you choose which to retag (Select All / None / Invert), and applies them. Ineligible files (excluded extensions, docs/manual segments, localization assets) are hidden; assets outside the Serenity plugin roots are accepted (address falls back to stripping a leading
Assets/). - Remove GUID Labels tool (Tools ▸ Serenity ▸ Addressables ▸ Remove GUID Labels) — purges stale GUID-shaped Addressables labels from all entries and the settings label table, leaving
module:*,type:*, andLocale*labels untouched. - Input Action Invoker —
UnityInputActionInvoker(Add Component ▸ Serenity ▸ Input ▸ Input Action Invoker), a drop-in component that maps Input System actions to parameterless public methods on referenced scripts and calls them when the input fires — Serenity's reflection-based equivalent of Unity's PlayerInput → Invoke Unity Events mode. A custom inspector reads the action maps/actions from an assignedInputActionAsset(or a siblingPlayerInput's asset) and lists each target's invokable methods in dropdowns. Each action entry has its own trigger phase (Started/Performed/Canceled) and any number of method calls. Actions are bound from the siblingPlayerInput's per-player action instance when present (keeping local-multiplayer callbacks isolated), falling back to the assigned asset for standalone use. - Signal Reaction component —
SignalReactionComponent(Add Component ▸ Serenity ▸ Events ▸ Signal Reaction), the no-code counterpart toSignalEmitterComponent: where the emitter dispatches a signal without code, this component reacts to one. A custom inspector lists each reaction as a searchable dropdown of every concreteEventDispatcherSignaltype in the project plus a responseUnityEvent, so a designer can wire "when signal X is dispatched, do Y" entirely in the Inspector — the first no-code way to react to a signal (previously only the code-definedEventDispatcherAction<TSignal>could). Subscriptions go through the sharedIEventDispatcherService(resolved viaServiceLocatorBridge); the component waits for the service to be registered before binding and unsubscribes cleanly when disabled. The parameterlessUnityEventanswers "react to this signal happening" — reactions that need the signal's payload still belong in anEventDispatcherAction<TSignal>. - Missing References report (Tools ▸ Serenity ▸ Validate Missing References) — a one-click editor window that scans every
IFoundationSettingsScriptableObject (clips, tracks, menus, modals, definitions, settings…) for references that were assigned but can no longer be resolved (a deleted/moved clip, table, prefab or definition), and lists each offending asset and field with a Ping button. Only missing references are reported, not empty fields. Designer-facing "what's broken?" tooling that surfaces the silent null-reference failures the architecture is prone to. - Health Check dashboard (Tools ▸ Serenity ▸ Validate Health Check) — a single "is my project wired correctly?" window for non-programmers. Runs new integrity checks over every
IFoundationSettingsasset — emptyId/Guid, duplicateIdwithin a definition type, and duplicateGuidacross the project (the keys Serenity services resolve by) — each with a Ping button, and gathers the previously-scattered validators (Validate Installation / UI Theme Prefabs / Branding / Find FoundationSettings / Missing References) behind one-click launch buttons rather than re-implementing them. - In-editor audio audition — the AudioClip definition and Music Track inspectors now have Play / Stop preview buttons (
SerenityEditorAudioPreview, a shared editor helper that drives Unity's internalAudioUtilby reflection, tolerant of version differences and failing soft), so audio designers can hear a clip or track without entering Play mode. - Localization key validator (Tools ▸ Serenity ▸ Validate Localization Keys) — scans every Serenity asset for translation keys (any field whose
IsTranslating…toggle is on — menu/modal titles, option labels, modal text, game-setting values…) and validates each against the project's Unity Localization string tables, reporting missing keys (which silently fall back to the raw key at runtime) and translating-but-empty fields, each with a Ping button. The scan is convention-based (IsTranslating<Field>→ sibling<Field>), so it covers any future translatable field automatically. - Game Mode Music Binder —
GameModeMusicBinderComponent(Add Component ▸ Serenity ▸ Game Mode ▸ Game Mode Music Binder), the no-code way to play different music per game mode (previously this needed a code-definedEventDispatcherAction<GameModeChangedSignal>). For eachGameModea designer assigns a Signal Definition asset (typically aPlayMusicTracksignal authored in the Signal Definition inspector); on entering that mode the binder dispatches it through the sameDispatch(IEventDispatcherSignalDefinition)pathSignalEmitterComponentuses — building no payload itself, so it works for any signal type. Subscribes toGameModeChangedSignalviaServiceLocatorBridge, waits for the service before binding, and unsubscribes when disabled. - Modal button presets — the Modal Builder (Tools ▸ Serenity ▸ UI ▸ Modal Builder) now offers one-click presets (OK · OK/Cancel · Yes/No · Confirm/Cancel) that populate the modal's options with SUBMIT buttons (built exactly like
ModalButtonToUiOptionConverter, with no signals yet so the designer just wires each button), so common dialogs no longer start from a blank button list. - Cutscene Outline (Tools ▸ Serenity ▸ Cutscenes ▸ Cutscene Outline) — a read-only outline + validator for
UnityCutsceneDefinitionassets: it lists the stages in order with their type, duration and key reference (Timeline asset / fade colour), shows the total run time, and flags problems — most importantly aPlayTimelinestage with no Timeline assigned (which would play nothing at runtime). Reads everything throughSerializedObject, so it gives narrative designers a no-code "what happens, in what order, and is anything missing?" view without entering Play mode. The structural-preview slice of the roadmap's Cutscene preview (a live scrubbable Timeline preview is a later addition). - Cutscene stage scrubber — the Cutscene Outline window gained a scrub timeline: a proportional stage bar with a draggable playhead that highlights the active stage at any scrubbed time, plus per-stage start–end times and active-stage highlighting in the list.
PlayTimelinestages use their assignedPlayableAsset's real duration so the layout is accurate. This is the stage-level slice of the roadmap's "cutscene scrub" — it does not play the Timeline's content (a frame-accurate PlayableDirector preview remains a later addition). - Toast notifications —
UnityToastComponent(Add Component ▸ Serenity ▸ UI ▸ Toast), a non-blocking notification that fades a short message in, holds, and fades out (unlike a modal, it never steals input). The visual is a designer-assigned prefab carrying aTMP_Text, so toasts inherit the project's fonts/theme; spawned toasts parent to a configurable container (add aVerticalLayoutGroupto stack them) and animate on unscaled time so they work while the game is paused. Fully no-code to trigger:Show(string)is wirable from anyUnityEvent— a Button'sonClick, aSignalReactionComponentresponse (with the message typed into the inspector), an animation event — so "when signal X happens, toast 'Saved!'" needs no script. - Signal Flow Browser (Tools ▸ Serenity ▸ Events ▸ Signal Flow Browser) — a read-only view of the event graph: for every
EventDispatcherSignalit shows who dispatches it (authored Signal Definition assets), what listens for it (modal settings), and what reacts to it in code ([AutoRegisterEventAction]actions), each pingable, with a search box. Authored assets are discovered generically viaSerializedObjectand reactions from the attribute +EventDispatcherAction<T>base, so the otherwise-invisible no-code event wiring is browsable in one place. - GameMode Overview (Tools ▸ Serenity ▸ GameMode ▸ Transition Overview) — a read-only view of a
UnityGameModeSettingsDefinition: one card perGameModelisting the signals dispatched on enter and on exit, plus the shared action-map/pause configuration, and a reminder that the service also dispatchesGameModeChangedSignal(previous → new)on every transition. Reads through theIGameModeSettingsDefinitionaccessors so it always lists every mode (flagging ones with no wiring), giving designers a no-code picture of "what happens when each mode is entered/left." - Init Pipeline Overview (Tools ▸ Serenity ▸ Init ▸ Pipeline Overview) — a read-only outline + validator for
UnityInitializationPipelineProfileassets: it lists the boot tasks in run order with their criticality and weight, shows each task's share of the progress bar and the total weight, and flags problems — most importantly empty task slots (which would throw at boot) and empty Ids. Reads throughSerializedObject, so designers can sanity-check the startup flow (and see how many critical tasks can halt boot) without entering Play mode. The structural slice of the roadmap's Init pipeline simulator. - Init Pipeline Simulator (Tools ▸ Serenity ▸ Init ▸ Pipeline Simulator) — a dry-run boot simulator for
UnityInitializationPipelineProfileassets: tick the tasks you want to fail and Run to see how the criticality rules cascade — a critical failure halts boot and skips the remaining tasks, while a non-critical failure is logged and boot continues — with per-task outcomes (ok / failed / skipped) and a simulated progress bar showing how far boot gets. Models the criticality handling ofInitializationPipelineService.RunAsyncwithout executing the tasks; the dynamic half of the Init Pipeline item (the read-only Overview is the structural half). - Diagnostics overlay —
UnityDiagnosticsOverlayComponent(Add Component ▸ Serenity ▸ Debug ▸ Diagnostics Overlay), an on-screen play-mode HUD showing FPS / frame time, time scale, the current and previousGameModewith pause state, and the number of joined players — a designer-facing "what is the game doing right now?" panel for the common "why isn't this working?" questions. It reads only through service interfaces (IGameModeServiceviaServiceLocatorBridge) and degrades to "n/a" when a service isn't up, toggles via a configurable key or no-codeToggle()/Show()/Hide()methods (wirable to a UnityEvent or input action), and hides itself in non-development player builds unless explicitly enabled. - Player Join Overlay —
UnityPlayerJoinOverlayComponent(Add Component ▸ Serenity ▸ Debug ▸ Player Join Overlay), an on-screen panel that lists the players currently joined via the Input System — each slot's player index, control scheme and devices — so a designer can see local-multiplayer joins happen while testing instead of reading the Console. Self-contained (reads onlyPlayerInput.all, no services), toggles via a configurable key (default F4, alongside the F3 Diagnostics Overlay) or no-codeToggle()/Show()/Hide(), and hides itself in non-development builds unless enabled. - Mixer Topology (Tools ▸ Serenity ▸ Audio ▸ Mixer Topology) — a read-only visual routing diagram for an
AudioMixerand the Serenity sound config: it draws each Serenity audio channel wired to its mixer group (right-angle connectors), marks groups whose volume is exposed and which are effect-loop groups, and lays out each effect loop's source groups feeding its loop group via sends. ReusesAudioMixerRelationshipScanner, so it stays consistent with the Audio Channel Manager but is a pure viewer ("how does my audio route?") rather than the manager's analysis/repair tool. - Positional / 3D audio authoring —
AudioPlayerClipnow carriesspatialBlend,minDistance,maxDistance,spreadanddopplerLevel, applied to theAudioSourceat play time byUnityAudioPlayerService. Because these are constructor parameters (with[FloatRange]sliders), they are authorable no-code in the Signal Definition inspector when building aPlayAudioClipsignal — combined with the existingAudioWorldPositionplayback position, a designer can place and shape a 3D sound without code. Zero-regression: the settings are applied only whenspatialBlend > 0, so existing clips (which default to0= 2D) leave the AudioSource's own/prefab min-max distance, spread and Doppler untouched and behave exactly as before. - Input rebinding component —
UnityInputRebindComponent(Add Component ▸ Serenity ▸ Input ▸ Input Rebind), no-code interactive rebinding for a single Input System binding (the classic "press a key to rebind" settings row). Wire a button toStartRebind()and another toResetBinding(); the current binding text is pushed through aUnityEvent<string>(wire it to a TMP/UI text'stextsetter) andonRebindStarted/onRebindStoppeddrive a "Press any key…" prompt. WrapsPerformInteractiveRebinding(disabling the action during the rebind as the Input System requires) and, whenpersistis on, saves the asset's binding overrides toPlayerPrefsand reloads them on enable so rebinds survive restarts. By default it rebinds the referenced asset's binding (shared-asset/single-player settings menu); enableusePlayerInputfor local multiplayer to rebind the per-player action instance resolved from a parentPlayerInputand persist per player index instead. - Designer Quick Start guide (
Assets/Documentation/DESIGNER_QUICKSTART.md) — a no-code onboarding tour: a first-run checklist (the four validators), a map of everyTools ▸ Serenitytool andAdd Component ▸ Serenitycomponent, and step-by-step recipes ("show a toast when something happens", "different music per game mode", "let players rebind a key", "why isn't this working?").
Changed
- Deterministic editor-menu ordering — every
[MenuItem("Tools/Serenity/…")]now carries an explicitpriority(Setup 0–99, Project/Build 100–199, Authoring 200–299, Validate/Find 300–399, Docs 400+) and every[CreateAssetMenu]carries anorderfrom a curated 100-wide-block scheme, so Serenity's context menus render the same way on every machine instead of in arbitrary compile order. - Menu path normalization —
Serenity/Ui→Serenity/UI(UiTheme → UI Theme, CompositeView → Composite View) andSerenity/Settings/Unity UI Settings→Serenity/UI/UI Settings. Existing assets bind by script GUID, so renames are safe. - Shared option inspector — the menu's option
ReorderableListwas extracted into a reusableUiOptionListInspectorGUI, now used by bothUnityMenuSettingsDefinitionEditorandUnityModalSettingsEditor(identical ValueType / UI Element / Id / Label / Value / Translate-Label + per-option signal-list UI). - Option value-type enum rename —
UiComponentValueType.MENU_TRANSITION→TRANSITIONandMENU_ACTION→ACTION(ordinals unchanged, so serialized assets are preserved). UnityModalController.Navigateis now direction-aware: HORIZONTAL modals navigate options with left/right and edit values with up/down; VERTICAL modals keep the previous up/down navigation + left/right value editing.
Features
- Modal dialogs can now be authored with the same rich, multi-option, scrollable, horizontally- or vertically-laid-out model as menus, and can run a list of signals per option — not just a single confirm/cancel button each.
- Common authoring flows are now one-click editor tools: scaffolding a modal (signal + action + settings), authoring game-settings definitions with live presets and automatic service wiring, batch-importing SFX/music, and managing audio channels against the mixer.
- Addressables labels can be re-applied to a hand-picked subset of assets under any folder, and legacy GUID-shaped labels can be purged project-wide.
Fixed
- The Directory Cloner no longer propagates stale, GUID-shaped Addressables labels:
UpdateAddressablesEntriesskips GUID-like labels when copying a source entry's labels, and the new Remove GUID Labels tool cleans up labels left over from the old cloner behavior. - Resolved several pre-existing latent bugs surfaced while building out test coverage:
ComponentLogger's self-recursiveId/Guidsetters,TimerFormatterService.FormatTimeInSecondsusing a/120instead of/3600hour divisor,AudioWorldPosition.ToStringformatting non-invariantly, andUnityGameSettingsOptionResolver.ResolveSelectablethrowing an NRE on an empty option set (now guarded).
Infrastructure
- Comprehensive automated test coverage. Behavioral tests were added across every pure Domain + Application module, taking the pure suite from 1,742 → 3,508 green tests, then across the testable Unity glue layer (≈28
Unity*assemblies, ~1,130 new PlayMode tests) and the OS file-persistence I/O services (0% → covered), taking the full PlayMode suite from 4,131 → 5,334 tests. All 36 pre-existing PlayMode failures were resolved (real bugs fixed + stale tests updated). Coverage also reached the Unity editor-tooling layer (docfx / generators / importers / validators) in EditMode and the Unity installers (15 modules) in PlayMode. - A standalone net8.0 NUnit harness (a
UnityEngineshim with real Vector/Mathf arithmetic) runs the entire pure Domain + Application suite in under a second without launching the Unity editor or requiring a license — the fast verify loop that drove the coverage work. - Added PlayMode tests for
UnityInputActionInvokerusing the Input SystemInputTestFixture(Performed / Started / Canceled phases, the standalone-asset and PlayerInput paths, multiple methods per action, invalid-method resilience, and disable-stops-invoking) — the firstInputTestFixture-based test in the repo. Added theUnity.InputSystem.TestFrameworkreference toTests.asmdef, along with the other cross-assembly references the new coverage required. - Added pure-logic tests for the Addressables retag eligibility / address-building rules and the GUID-label invariants, the modal rich-option builder and Buttons → Options migration, the Game Settings Wizard writers, and the audio relationship analyzer / channel-deletion planner.
- Added
SignalReactionComponenttests (realUnityEventDispatcherService+ServiceLocatorBridge): a matching signal invokes the response, a different signal type does not, and disabling unsubscribes.
1.1.1 — Composite Views, Horizontal Menus, Inspector Signal Authoring, View Preview, Input-Gate Return & Music Start-Point Controls
Added
- Composite Views — a flexbox screen-composition system.
UnityCompositeViewDefinition(Serenity/Ui/CompositeView) composes anyIViewBasechildren (menus or nested composites) into one screen with CSS-style per-child sizing (Fixed px/Flex fr/Percent %/Auto, with min/max), Row/Column direction, alignment, padding and gap, and two content modes:STACK(all children visible) andSWITCHER(one active child). Backed by a pureFlexboxSolverdomain service and a layout model (LayoutDirection,LayoutSizeUnit,LayoutAlignment,LayoutScrollAxis,LayoutSize,LayoutPadding,LayoutConfig,ContainerContentMode). Direction reads in table/grid sense:ROW= stacked horizontal bands,COLUMN= side-by-side columns. - Menu hosting inside composites — a menu can render into a composite region (
IHostableView). Each composite slot that references a menu builds its own instance (UnityMenuService.CreateHostedInstance), decoupling the per-instance routing id from the shared definition id, so the same menu can appear in several regions at once without being stolen from standalone use. - View Router —
IViewRouter/ViewRouter/IViewProvider(Global.Application). The initial screen moved off the menu-service settings ontoIUiSettings.InitialViewId(a picker that accepts a menu or a composite). The router tracks the current top-level view, auto-hides the previous one, and shows the initial view at boot and on return from gameplay. Menu transitions route through it (RouterMenuTransitionateToView). - Scrollable views —
Scrollable+ScrollAxisonUnityViewDefinition, with programmatic scrollbars (UnityScrollbarBuilder). Menus scroll with aVisible Options Countclamp (MenuScrollPolicy) and auto-scroll to keep the selected option in view. - Cross-menu focus traversal — stacked menus in a composite pass keyboard/gamepad focus between each other at their boundaries (
ICrossMenuHost/IFocusableMenuView), with an optional wrap-around. Input control follows the activeSWITCHERchild (ICompositeViewService.GetActiveInputView). - Composite View Builder wizard (Tools ▸ Serenity ▸ UI ▸ Composite View Builder) — pick a parametric template (N columns, N rows, single scrollable column, navbar+content, navbar+columns/rows, sidebar), name the sections, and Generate creates the composite + menu
.assettree with navigation auto-wired (no manual::path plumbing). Per-section and navbar layout direction are selectable. - View Preview tool (Tools ▸ Serenity ▸ UI ▸ View Preview) — a live, themed render of a menu or composite built from the real theme prefab templates at a chosen device resolution, plus a structural wireframe mode. Includes selected-option highlight, click hit-testing, fit-to-view zoom, edit-mode localization (real translated labels instead of raw keys), and an optional backdrop image.
- Horizontal menus —
MenuDirection(Vertical/Horizontal) on menu definitions lays options out side by side.HorizontalOptionWidthMode(Content/Uniform/Fill/Explicit) withHorizontalOptionWidthcontrols column width;OptionsGapandVisible Options Countapply horizontally, with a horizontal scrollbar. - Inspector-authored signal dispatch definitions —
UnityEventDispatcherSignalDefinition(Serenity/EventDispatcher/Signal Definition): pick a concreteEventDispatcherSignaltype, choose a constructor, and populate its parameters entirely from the Inspector;IEventDispatcherService.Dispatch(IEventDispatcherSignalDefinition)builds and emits it. Supports primitives, Unity math types, enums,UnityEngine.Objectreferences, ScriptableObject-backed interface parameters, recursively nested DTO/value-object parameters (up to 6 deep), and nullable optionals. - Signal-parameter authoring attributes —
FloatRangeAttribute(range + percentage slider + reset button),AssetPathReferenceAttribute(draws an asset object field for a string path), andFoundationIdReferenceAttribute(settings-id picker). Applied toAudioPlayerClip(volumeas a 0–100% slider,panStereowith reset,filePathas an AudioClip field) andAudioPlayerPlayClipInput(serviceId). SignalEmitterComponent— a MonoBehaviour holding signal-definition assets;Dispatch(id)/DispatchFirst()emit a configured signal from collision/trigger callbacks, animation events, input, orUnityEventwiring. Failures are logged and swallowed so gameplay flow is never broken.- Audio rolloff mode — engine-agnostic
AudioRolloffModedomain enum (Logarithmic/Linear/Custom) plusRolloffModeonAudioPlayerClip, controlling 3D distance attenuation (values mapped to Unity at the boundary). - Per-view OnCancel signals — an
OnCancelsignal list onIMenuSettingsDefinition/UnityMenuSettingsDefinition, authored through a reorderable inspector list, dispatched when a cancel input reaches that menu. - Return to the primary input gate —
ReturnToPrimaryInputGateSignal. Authored on the main menu'sOnCancel, it tears down the menu input context, unpairs the device (IPlayerInputService.ReleasePrimaryDevice→IUiInputRouter.Unpair), and re-arms the device-selection gate so a fresh device can join. - Start From Loop Point —
StartFromLoopPointonUnityMusicTrackDefinition/IMusicTrackDefinition/MusicTrack. When enabled, a track's first playback begins at the loop start time instead of00:00:000, skipping the intro. Applies to any track with a loop region — tail-preserving (the first voice and its seam start at the loop point) and native/one-shot tracks (cut/fade/cross-fade all honor the offset). The music track inspector's Loop section was reworked: the loop region stays editable whenever either toggle consumes it, and the tail fade-out controls are gated to tail-preserving looping. - Ignore If Already Playing —
IgnoreIfAlreadyPlayingonUnityAudioPlayerSettings/IAudioPlayerSettings. When enabled, a request to play the song that is already playing is ignored so it keeps playing uninterrupted instead of audibly restarting (music player). Default off preserves the always-restart behavior.
Changed
- The first screen is configured on
UnityUiSettings.InitialViewId(menu or composite) instead of the menu-service settings;InitMenuIdwas retired from the menu-service settings definition. - UI authoring tools are grouped under Tools ▸ Serenity ▸ UI (Composite View Builder, View Preview).
UnityMenuControllerroutes Navigate/Submit/Cancel through the active composite input view when one is shown, falling back to the current menu otherwise.
Features
- Multiple existing menus and nested composites can be composed into a single screen (e.g. a nav rail + scrollable settings content + detail region) with flexbox sizing, scrolling, and cross-region keyboard/gamepad focus traversal — authored visually with the Composite View Builder and previewed live in the editor.
- The same menu can be hosted in several composite regions simultaneously, each with its own selection/focus state, while sharing the underlying game setting.
- Menus can be laid out horizontally with selectable column-width behavior and horizontal scrolling.
- Authoring and dispatching event-dispatcher signals — including signals with complex nested DTO parameters — entirely from the Inspector, and trigger them from the scene via
SignalEmitterComponent. - A cancel input that no option consumes now dispatches the view's
OnCancelsignals and then navigates back; composites use a two-tier go-back (close the open detail region, or leave the whole composite). From the main menu, cancel can return the player to the press-to-start device-selection gate.
Fixed
- The primary input gate (device-selection prompt) now completes the join on button release rather than press, so the joining press no longer leaks into the menu shown immediately after joining (e.g. instantly submitting its focused option). The press latch resets if the latched device is disconnected mid-hold, and the gate re-arms cleanly when re-shown.
- UI input routing now applies control-scheme masks so a paired gamepad's bindings resolve, and pairs keyboard + mouse as one unit when they are not configured to split — fixing input not reaching the UI after joining with those devices.
SignalEmitterComponent(and any other Unity-sideServiceLocatorBridgeconsumer) can now resolveIEventDispatcherServiceat runtime, soDispatch(id)/DispatchFirst()emit instead of logging "no IEventDispatcherService is registered yet."UnitySerenityInstaller.RegisterServicenow mirrors every service into the runtimeIServiceLocator(not just the init-time container), with last-wins overwrite semantics that match the dualILogServiceinstall.- Audio clips built from a
IAudioPlayerClipDefinition(e.g. an Inspector-authoredPlayAudioClipSignaldispatched throughSignalEmitterComponent) now play audibly. TheAudioPlayerClip(IAudioPlayerClipDefinition, AudioPlayerType)constructor previously leftvolumeandpitchat C#'s0default, so the clip played at volume 0 / pitch 0 — silent, with no error. It now initializes volume, pitch, loop, pan, reverb mix and rolloff to the same defaults as the other constructors.
Infrastructure
- Added tests for the
FlexboxSolver,UiAnchorMapper, Composite View Builder + generator, composite cross-navigation / host-path / hosted-size paths, layout and scrollbar builders, and the menu scroll policy. - Added tests for the event-dispatcher signal builder and dispatch-from-definition flow, configured-signal parameters, the
AudioPlayerClipauthoring attributes, the menuOnCanceldefinition, the primary input gate, and the view-model routing-id setter. - Updated assembly definitions for the new cross-layer references introduced by composites, the editor preview/builder, horizontal menus, and the signal-definition editor.
- Added tests for
MusicTrack.StartFromLoopPoint(default and custom),AudioPlayerClipaudible playback defaults when built from a definition, and extended the audio-player settings test double with theIgnoreIfAlreadyPlayingmember.
Changed
- The first screen is configured on
UnityUiSettings.InitialViewId(menu or composite) instead of the menu-service settings;InitMenuIdwas retired from the menu-service settings definition. - UI authoring tools are grouped under Tools ▸ Serenity ▸ UI (Composite View Builder, View Preview).
UnityMenuControllerroutes Navigate/Submit/Cancel through the active composite input view when one is shown, falling back to the current menu otherwise.
Features
- Multiple existing menus and nested composites can be composed into a single screen (e.g. a nav rail + scrollable settings content + detail region) with flexbox sizing, scrolling, and cross-region keyboard/gamepad focus traversal — authored visually with the Composite View Builder and previewed live in the editor.
- The same menu can be hosted in several composite regions simultaneously, each with its own selection/focus state, while sharing the underlying game setting.
- Menus can be laid out horizontally with selectable column-width behavior and horizontal scrolling.
- Authoring and dispatching event-dispatcher signals — including signals with complex nested DTO parameters — entirely from the Inspector, and trigger them from the scene via
SignalEmitterComponent. - A cancel input that no option consumes now dispatches the view's
OnCancelsignals and then navigates back; composites use a two-tier go-back (close the open detail region, or leave the whole composite). From the main menu, cancel can return the player to the press-to-start device-selection gate.
Fixed
- The primary input gate (device-selection prompt) now completes the join on button release rather than press, so the joining press no longer leaks into the menu shown immediately after joining (e.g. instantly submitting its focused option). The press latch resets if the latched device is disconnected mid-hold, and the gate re-arms cleanly when re-shown.
- UI input routing now applies control-scheme masks so a paired gamepad's bindings resolve, and pairs keyboard + mouse as one unit when they are not configured to split — fixing input not reaching the UI after joining with those devices.
Infrastructure
- Added tests for the
FlexboxSolver,UiAnchorMapper, Composite View Builder + generator, composite cross-navigation / host-path / hosted-size paths, layout and scrollbar builders, and the menu scroll policy. - Added tests for the event-dispatcher signal builder and dispatch-from-definition flow, configured-signal parameters, the
AudioPlayerClipauthoring attributes, the menuOnCanceldefinition, the primary input gate, and the view-model routing-id setter. - Updated assembly definitions for the new cross-layer references introduced by composites, the editor preview/builder, horizontal menus, and the signal-definition editor.
1.1.0 — Positional & Priority Audio, Music Loop Tails, Mixer Effect Loops, Lazy Menus & GameMode Input Gate
Breaking Changes
SpawnPoseno longer exposes the seven flat float fields (PositionX/Y/Z,RotationX/Y/Z/W). It is now backed byPosition(System.Numerics.Vector3) andRotation(System.Numerics.Quaternion). Construction is unaffected — the seven-float constructor andFromPosition(x, y, z)remain — but code that read the individual float fields must now readpose.Position.*/pose.Rotation.*.
Added
- Primary input gate as a GameMode — a
PrimaryInputGatevalue on theGameModeenum lets the primary-input prompt reuse the existing per-mode enter/exit transition-signal machinery (serialized storage, retrieval, and the reorderable inspector enter/exit lists are generated automatically for the new mode). - Tail-preserving music loops —
StartTime,EndTime,TailPreservingLoop,TailFadeOutDuration, andTailFadeOutCurveonIMusicTrackDefinition/MusicTrack/UnityMusicTrackDefinition. A second voice carries the previous pass's reverb/ambience tail across the loop seam, scheduled sample-accurately viaAudioSettings.dspTime/PlayScheduledso the loop never clicks. Loop points are authored asHH:MM:SS:MMMtime codes or in DAW terms (tempo, time signature, start/end bar) viaMusicBarTimeCalculator; the tail fade follows a Linear/Exponential/Logarithmic/S-Curve/Custom curve. - Positional audio playback —
AudioWorldPositionvalue object and an optionalPlaybackPositiononAudioPlayerPlayClipInput; a clip played with a position is 3D at that point, without one it stays 2D. Works from both a direct use-case call and aPlayAudioClipsignal (no gateway/service signature changes). - Audio sound-priority allocation — when the AudioSource pool is full, a clip can take over a lower-priority playing sound instead of being dropped, governed by per-clip
Priority/PriorityPolicy/CanBeReplacedand anAudioPriorityCandidateSelector(AudioPriorityPolicy: IgnoreIfNoSourceAvailable / ReplaceLowerPriority / ReplaceLowerOrEqualPriority / AlwaysReplace). Serenity priority semantics (higher = more important) are mapped to Unity's invertedAudioSource.priorityonly at the boundary. - AudioMixer Effect Loop authoring tool (
Tools ▸ Serenity ▸ Audio ▸ Create Audio Mixer Effect Loop) — creates a mixer group with aReceive → effects → Attenuationchain and a reusableUnitySoundMixerEffectLoopDefinitionasset describing it. - Effect Loop sync window (
Tools ▸ Serenity ▸ Audio ▸ Sync Effect Loops) — reconciles the AudioMixer andSoundMixerSettingsto the project's effect-loop definitions: creates a per-source Send into the loop's Receive, exposes it as{Source}_{Loop}_Send, and registers the definition. Idempotent and additive. - Source-group selection in the Create tool — choose which sibling groups feed the loop, with Select All / None.
- Auto-generated enable/disable action scripts — for each selected source group, generates an Enable + Disable
EventDispatcheraction/signal pair (reusing the shared Action Script generator) pre-filled to apply/clear the loop for that group, written to a configurable Events folder. - Runtime effect-loop apply/clear:
ISoundMixerService.ApplyEffectLoop/ClearEffectLoop,SoundMixerApplyEffectLoopSignal/SoundMixerClearEffectLoopSignal, their use cases, intent-only DTOs, and a pure engine-agnosticSoundMixerEffectLoopRouteResolver. UnitySoundMixerEffectLoopDefinition/UnitySoundMixerEffectLoopSourceScriptableObjects with a custom inspector, plus anEffectLoopsregistry onSoundMixerSettings.- Editor-only
AudioMixerYamlReader(reads.mixerstructure) andAudioMixerEffectLoopReflectionAdapter(isolates the internalUnityEditor.AudioAPI behind one class). - Per-menu instantiation mode —
MenuInstantiationMode(PreloadOnStartup/LazyOnFirstOpen) onIMenuSettingsDefinitionandUnityMenuSettingsDefinition, editable under an Advanced section in the menu settings inspector. - Lazy menu instantiation pipeline:
IMenuInstanceGate,MenuLifecycleResolver,EnsuringMenuTransitionateToView,UnityMenuLazyBuildContext,UnityMenuLazyRegistration, andIUnityMenuViewInstanceFactory/UnityMenuViewInstanceFactory. - Per-mode exit transition signals —
IGameModeSettingsDefinition.GetExitSignalsForGameMode; the GameMode settings inspector now renders separate reorderable enter/exit signal lists per mode. - Pause-during-scene-load — a
PauseDuringSceneLoadGameMode setting (default on) with a settings-editor toggle, freezing the game clock while the additive gameplay scene loads and restoring it (viatry/finally) once the load completes, so newly instantiated objects do not simulate behind the loading overlay. - First-run config generation — on a fresh install the detected OS/browser language is now persisted to
gameSettings.cfgat detection time (standalone viaUnitySystemConfigurationSnapshotStore; WebGL/ResourcesOnly viaSerenityFallbackLocalizationService), guarded by a file-existence check so a returning player's saved preference is preserved.
Changed
SpawnPoseis now backed bySystem.NumericsVector3 Position+Quaternion Rotation(replacing the seven flat floats), matching GameRail'sRailNodePositionvalue-object pattern; it stays pure C# (no engine dependency).UnityWaveServicereadspose.Position.*/pose.Rotation.*. See Breaking Changes.UnityAudioPlayerService.ApplyPlaybackPlacementis now the single source of truth forAudioSource.spatialBlend(with a position →1and the emitter is moved there; without →0and the emitter is left in place);ApplyClipToSourceno longer applies the clip's spatial blend.UnityGameModeServicedispatches the exited mode's signals afterOnExitMode, mirroring the existing enter signals; enteringPrimaryInputGatefires its enter signals and leaving it fires its exit signals through the sameSetModedispatch.- The pause mixer effect loop is now driven by GameMode enter/exit signals (Enable on Pause enter, Disable on Pause exit) instead of dedicated action classes.
UnityMenuServicebuildsLazyOnFirstOpenmenus on first show (cached and reused);PreloadOnStartupmenus stay eager. Initial and pause menus configured lazy are treated as preload to avoid first-open hitches. Default behavior is unchanged (PreloadOnStartup remains the default).UnitySoundMixerSettingsEditornow reads exposed parameters live from the in-memory AudioMixer (auto-updates as you edit, no save needed) and labels the registered-definitions list distinctly from the section header.- Effect-loop definitions use a single normalized
DefaultWet(dry is its complement,1 - wet), shown as a "Dry/Wet" slider; the Create tool takes separate Media and Events destination folders. - The loop's output level is treated as a static mixer trim (not an exposed runtime parameter); the source Send tracks the source group's current level.
UnityYamlUtilswas kept a generic YAML helper — all AudioMixer-specific YAML knowledge moved into the SoundMixer module.
Features
- The device-selection prompt is now an observable GameMode (
PrimaryInputGate) that fires signal-driven enter/exit side effects without transitioning game modes itself — on device selection it raisesOnPrimarySelectedand the composition root dispatchesEnterMenuSignal, letting theEnterMenuaction change the mode. - Music can loop between authored start/end points while a second voice carries the previous pass's reverb tail across the seam, with a bounded, curve-shaped tail fade-out (a
0duration cuts cleanly at the loop point). - Sounds can be played at a world position (3D) and can reclaim a busy pool slot from a lower-priority sound instead of being dropped.
- An effect loop can be authored, wired, registered, and toggled from gameplay (e.g. a pause low-pass/reverb on Music) end-to-end from the editor, without hand-writing routing or action scripts.
- Menus can opt into lazy creation on first open, reducing startup work, while preserving eager startup for menus that need it.
- Game modes can run signal-driven side effects on both entering and exiting a mode.
Fixed
- Menu value changes now apply to the option that actually changed (not the currently selected one) and resolve the selected option by its logical
GetIndex()rather than hierarchy position, fixing entwined slider values where two options aliased oneUiOptionValue(e.g. master/ambient). ISoundMixerServiceis now registered in the runtimeServiceLocator, soEventDispatcheractions can resolve it.- Per-source Send mix-level GUIDs are pre-allocated when the Send is created, so exposing each source's Send level now succeeds.
- Removed dangling
[SerializeReference]references to deleted action signal types from sample assets (an unknown managed type was nulling the other valid signals on entering Play).
Removed
- Redundant
EnablePauseMixerEffectLoopAction/DisablePauseMixerEffectLoopActionclasses and thePauseEffectLoopsample asset (superseded by GameMode exit signals and the action-script generator). - A bogus
SoundMixerSettingsmapping (Music_SucutruleLoop_Send→Audio_MasterVolume) that referenced a non-existent exposed mixer parameter.
Infrastructure
- Added tests for the SoundMixer effect-loop route resolver, effect loop, installer, use cases, and coverage.
- Added tests for the Menu lifecycle resolver, the ensure-transition use case, and the menu instantiation-mode enum.
- Added tests for the music bar/time calculator, fade-curve evaluator, and music-track getters; audio world-position and placement; audio priority candidate selection and clip priority;
SpawnPoseconstruction; and the GameMode primary-input-gate actions/signals.
1.0.12 — WebGL Support, Serenity Theme & Runtime Localization
Added
- Serenity Theme — a complete new UI theme with a full component set (Background, Title, Label, Input, Dropdown, Selector, Slider, Toggle, Submit, Modal, PrimaryInputPrompt, Highlight), including animator controllers for the highlight color loop and modal show/hide transitions.
- WebGL build support — the first WebGL build target for Serenity.
- WebGL Resources export tooling —
SerenityWebGLResourcesExporter,SerenityWebGLResourcesCleaner,SerenityWebGLResourcesValidator,SerenityWebGLResourcesPaths, andSerenityWebGLExportManifestfor exporting Serenity assets into a consumer'sResourcestree for WebGL builds. - Runtime localization fallback —
SerenityFallbackLocalizationServiceloads per-(table, locale) JSON fromResourcesand answers a newILocalizationService.TryTranslate(key, out value), enabling translation and live language switching in ResourcesOnly (WebGL) mode. - Per-theme loading-progress bar — a
LoadingProgressTemplateslot on the UI theme components and aLoadingBarprefab variant for every theme (Default, Alternative, Alternative2, Animated, Animated2, Futuristic, Serenity, Writings). SerenityAssetLoadingModeenum andIAssetLoadingModeProvider/UnitySerenityAssetLoadingModeProviderto select how assets are loaded (Addressables vs Resources-only).ILocalizationService.GameLanguageChangedevent, fired on real language-value changes.- Editor menu command (
Serenity ▸ UI ▸ Generate LoadingProgress Prefabs) that generates the per-theme loading-bar prefab variants and wires them into the theme definitions. - "Loading Progress Prefab" field in the UI theme definition inspector.
- Inter font family (variable + static weights with SDF assets) and supporting images (
WhiteBackground,square-roundborder).
Changed
- The gameplay loading overlay now builds its progress bar from
LoadingProgressTemplate, falling back toSlideableTemplatewhen no dedicated prefab is assigned. UnityUiTMP_TextLocalizationUpdaterComponentnow callsTryTranslatein fallback mode, caches the original localization key across language switches, and re-captures it when the displayed text diverges from the last translation.UnityLocalizationServicekeepsGameLanguageChangedas a no-op, deferring refresh to Unity Localization's ownOnSelectedLocaleChangedchain.UnityPrimaryInputPromptViewbehavior corrected for WebGL builds.InitializationPipelineService,UnityCutscenePlayerService,ReflectionCallTask,AddressablesAssetLocator,UnityAddressableUtils,UnityAssetUtils,AudioMixerDependencyCache, andUnityMainThreadDispatcherupdated to support Resources-only loading and WebGL constraints.- The Serenity Addressables group and addressable settings were updated to register the new assets.
Features
- ResourcesOnly mode now performs real translation and supports switching language at runtime through the settings UI language selector.
- WebGL Resources export uses move semantics during export and falls back to the browser language as the initial locale.
- Localization JSON is loaded via a recursive
Resources.LoadAll<TextAsset>("")scan with a string-table shape filter, requiring noUnity.Localization.Editorasmdef coupling.
Fixed
- Fixed the loading bar's selector disappearing on mouse-exit by sourcing the bar from a dedicated loading-progress prefab instead of reusing the interactive slider template.
- Fixed ResourcesOnly builds previously showing raw localization keys on screen with no way to switch language at runtime.
- Fixed the language selector (whose values are themselves localization keys) translating the stale cached key instead of the current one.
Infrastructure
- Added editor tooling for WebGL Resources export, cleanup, validation, and manifest tracking.
- Reflection-based localization export avoids
Unity.Localization.Editorasmdef coupling. - Added tests for localization use cases and the localization installer.
1.0.8 — Editor Pickers, Addressables Auto-Labeling & TMP Essentials Validation
Added
SerenityTmpEssentialsValidator, an editor-only validator that detects missing TextMeshPro Essential Resources and attempts to import them automatically when possible.- Play Mode protection for missing TMP Essentials, cancelling Play Mode entry before Unity/TMP runtime errors can occur.
- Manual TMP Essentials recovery dialog with options to open the TMP importer, ignore the warning for the current session, or recheck.
- Serenity import postprocessor that schedules a TMP Essentials check whenever Serenity assets are imported into an already-open Unity editor session.
SerenityAddressablesAutoLabeler, an editor-only postprocessor that automatically registers newly imported Serenity ScriptableObject assets as Addressables.- Automatic Addressables label assignment for Serenity ScriptableObject assets based on exact type mappings and namespace-prefix fallback rules.
- Centralized
ModuleLabelsconstants for all Serenity module labels and type labels. ModuleLabels.Typesconstants for type-based Addressables labels such as font, image, audio, and character assets.- Additional module labels for Character, GameMode, SequencePlayer, and Wave systems.
- Additional common label combinations for GameSettings + Localization and GameSettings + UI.
RenderIdObjectField<TAsset>(...)helper inFoundationEditorfor rendering Unity ObjectFields backed by serialized string ids.EventDispatcherSignalTypePicker, a shared searchable selector for concreteEventDispatcherSignalsubtypes.EventDispatcherSignalTypeAdvancedDropdown, anAdvancedDropdown-based searchable picker for signal-type string fields.module:game-modeAddressables label.- Addressables registration and labeling for
GameModeSettings.
Changed
SerenityPackageDependencyInstallernow treats TextMeshPro as satisfied when the TMP runtime types are available, even ifcom.unity.textmeshprois not listed as a standalone package.- TextMeshPro dependency detection now supports Unity 6 / UGUI 2.0+ setups where TMP is bundled with
com.unity.ugui. - Addressables label strings are now routed through
Serenity.Shared.Constants.ModuleLabelsinstead of hard-coded string literals. InstallationConstants.ModuleLabelsnow acts as a compatibility shim that re-exports the canonicalModuleLabelsvalues.InstallationConstants.TypeLabelsnow acts as a compatibility shim that re-exportsModuleLabels.Types.UnityAddressablesLabelernow uses centralizedModuleLabelsconstants for managed labels, path rules, and type rules.UnityAddressablesLabelernow manages additional Serenity labels for Character, GameMode, SequencePlayer, and Wave modules.UnityAudioPlayerInstaller,UnityMusicPlayerInstaller,UnityGameSettingsInstaller,UnityLocalizationInstaller,UnityMenuInstaller,UnityModalInstaller,UnityPlayerInputInstaller,UnitySoundMixerInstaller,UnitySystemConfigurationInstaller,UnityCharacterInstaller, and Cutscene/Sequence related services now use centralized module label constants.AudioMixerDependencyCachenow defaults toModuleLabels.AUDIO_MIXERinstead of a hard-coded Addressables label.UnityUiSettingsEditornow rendersScaleKeyandFontSizeKeyas Unity ObjectFields backed byUnityUIGameSettingsDefinitionassets.UnityGameGraphicsSettingsEditornow rendersQualityLevelKey,ScreenResolutionKey, andIsFullScreenKeyas Unity ObjectFields backed byUnityGraphicGameSettingsDefinitionassets.UnityLocalizationSettingsEditornow rendersGameLanguageKeyandVoiceLanguageKeyas Unity ObjectFields backed byUnityLocalizationGameSettingsDefinitionassets.UnityMenuServiceSettingsDefinitionEditornow rendersInitMenuIdas a Unity ObjectField backed byUnityMenuSettingsDefinitionassets.UnityGameModeSettingsDefinitionEditornow rendersPauseMenuIdas a Unity ObjectField backed byUnityMenuSettingsDefinitionassets.UnityActionDefinitionEditornow rendersSignalthrough a searchable signal type selector instead of a plain dropdown.UnityModalSettingsEditornow rendersSignalTypethrough a searchable signal type selector instead of a plain dropdown.UnityModalSettingsEditornow shares signal type discovery throughEventDispatcherSignalTypePicker, avoiding duplicated reflection logic.UnityMenuSettingsDefinitionEditornow uses centralized module label constants when resolving game settings and menus.UnitySoundMixerSettingsEditornow uses centralized module label constants when resolving audio game settings.- Serenity sample menu assets were reserialized to include explicit
ViewIdvalues on options and values. - Serenity sample menu assets now include explicit empty
OnShowandOnHidearrays. GameModeSettingssample asset now includes transition signal entries for the newer GameMode enum values.
Features
- Newly created Serenity ScriptableObject assets can now be automatically added to the Serenity Addressables group with the correct module labels.
- Addressables auto-labeling now supports exact type mappings for known Serenity assets and namespace fallback for future assets inside existing modules.
- Editor selectors for string-id-backed ScriptableObject references now support drag-and-drop from the Project window.
- Editor selectors for string-id-backed ScriptableObject references now support Unity's standard Object Picker search flow.
- Signal type fields now provide searchable selection while preserving the original serialized string contracts.
UnityActionDefinition.Signalcontinues to storeType.FullName.UnityModalSettings.SignalTypecontinues to storeType.AssemblyQualifiedName.UnityModalSettings.SignalTypekeeps the<None>option, storing an empty string for no selection.- TMP Essentials validation runs both on editor startup/import and synchronously when entering Play Mode.
- TMP Essentials auto-import attempts to locate the package through TMP editor utilities, Package Manager metadata, or
Library/PackageCache.
Improved
- Inspector UX is now closer to standard Unity workflows for asset-backed references.
- Reduced accidental invalid selections caused by long non-searchable dropdowns.
- Reduced duplicated dropdown and reflection code across custom editors.
- Addressables label management is now safer and easier to maintain through a single source of truth.
- Addressables auto-labeling is idempotent and non-destructive: it does not remove existing labels and only adds known Serenity labels.
- TMP package detection is more robust across Unity versions.
- TMP Essentials detection now distinguishes between the TMP runtime being installed and the actual TMP Essential Resources being present in
Assets/. - TMP Essentials diagnostics now log TMP font asset hits without treating them as proof that Essentials are installed.
- Installer and editor code now avoids scattering hard-coded Addressables labels across the codebase.
- Assembly definitions were updated where needed so modules can reference the shared label constants.
Fixed
- Fixed false missing-dependency detection for TextMeshPro in Unity versions where TMP is bundled through UGUI rather than installed as
com.unity.textmeshpro. - Fixed missing
module:game-modelabeling forGameModeSettings. - Fixed several editor fields that previously required dropdown selection even though they represented asset-backed ids.
- Fixed
UnityActionDefinition.SignalandUnityModalSettings.SignalTyperemaining as non-searchable dropdowns after the initial picker refactor. - Fixed duplicated signal type discovery logic between modal signal selection and modal button signal menus.
- Fixed hard-coded Addressables label usage across several installers and editor utilities.
- Fixed Addressables managed label coverage for newer Serenity modules such as Character, GameMode, SequencePlayer, and Wave.
Infrastructure
- Added editor utilities for automatic Addressables registration and label assignment.
- Added editor utilities for TMP Essentials validation and recovery.
- Added shared editor picker infrastructure for signal type selection.
- Added shared editor helper for ObjectField-to-string-id bridging.
- Added assembly definition references to
Serenity.Shared.Constantswhere centralized label constants are now used. - Updated Addressables settings to remove stale labels and include the new
module:game-modelabel. - Updated the Serenity Addressables group so
Media/GameMode/GameModeSettingsis labeled withmodule:game-mode. - Updated sample serialized assets to match the current menu and game mode data model.
1.0.5 — Music Player Transitions, GameMode Signals & Menu Integration
Added
MusicPlayerTransitionTypeenum with three transition strategies:CUT,FADEIN_FADEOUT, andCROSS_FADE.- Configurable transition parameters on
IMusicPlayerService.PlaySong(...)and newPlaySongById(...)method. MusicPlayerPlaySongByIduse case andMusicPlayerPlaySongByIdInputDTO for playing specific tracks by identifier with explicit loop and transition control.PlaySongByIdgateway method onIMusicPlayerGateway.SetGameModeService(IGameModeService)contract onIMenuServicefor cross-service coordination.GetSignalsForGameMode(GameModeEnum)contract onIGameModeSettingsDefinitionfor per-mode signal configuration.InitializationandCutscenevalues to theGameModeenum, establishingInitializationas the default starting mode.- Per-mode
EventDispatcherSignaltransition sequences toUnityGameModeSettingsDefinition. DispatchModeTransitionSignals(...)orchestration inUnityGameModeServicethat fires configured signals after every mode change.- Full ReorderableList-based inspector for per-mode transition signals in
UnityGameModeSettingsDefinitionEditor. ServiceLocatorregistration forIMusicPlayerServiceduring music player installation.
Changed
UnityGameModeServicenow initializes inInitializationmode instead ofMenu, deferring the first real mode transition until the menu system is ready.UnitySerenityInstaller.ShowMenu()now wires the resolvedIGameModeServiceinto the menu service before invokingShowInitialMenu(), ensuring the game mode is synchronized on startup.UnityMusicPlayerInstallernow receivesServiceLocatorInstallerfor runtime service discovery.Serenity.GameMode.Domain.asmdefreference format standardized to GUID.- Production-ready asset naming:
Audio_SoundToTest→Audio_SoundToTrigger,Audio_TrackToTest→Music_TrackList. AudioTestingMenusettings updated to reference the renamed production assets.
Features
- Music playback now enforces a single active track rule through coroutine-based volume lerping.
- Rapid-fire playback requests safely supersede previous transitions ("latest request wins") preventing orphaned audio sources.
CROSS_FADEautomatically falls back toCUTwhen insufficient audio channels are configured.- GameMode transition signals are dispatched in exact inspector-configured order, with null entries safely skipped and logged.
GameMode.Menuis now automatically asserted wheneverShowInitialMenu()is executed, keeping the menu system and mode state in sync.
Improved
UnityGameModeSettingsDefinitionEditorinspector now renders one dedicated reorderable signal list perGameModevalue with subtype selection dropdowns and drag-and-drop ordering.- Signal list elements display the concrete
EventDispatcherSignalsubtype name for at-a-glance identification. Serenity.Menu.ApplicationandSerenity.UnityMenu.Infrastructureassembly definitions now reference GameMode contracts for cross-layer coordination.
Fixed
- Prevented potential recursive mode transitions by relying on
SetModeshort-circuit when the target mode matches the current mode. - Music player gateway stub signatures updated to maintain interface compatibility with the new transition-enabled contract.
Infrastructure
- New assembly definition references added to bridge MusicPlayer, Menu, and GameMode layers without circular dependencies.
- Tests assembly definition extended to include
Serenity.UnityMusicPlayer.Installationfor installer-level validation coverage.
1.0.3 — Menu Lifecycle Signals & Inspector Improvements
Added
- Added
OnShowandOnHidelifecycle signal collections toUnityMenuSettingsDefinition. - Added menu lifecycle signal support to
IMenuSettingsDefinition. - Added runtime lifecycle signal dispatching for menu visibility transitions.
- Added lifecycle signal wiring in
UnityMenuViewFactory. - Added
SetLifecycleSignals(...)support toUnityMenuView.
Features
- Menus can now dispatch custom
EventDispatcherSignalsequences when shown or hidden. - Lifecycle signal execution order now follows the exact order configured in the inspector.
- Lifecycle signal collections now support drag-and-drop reordering through standard Unity reorderable lists.
Improved
- Enhanced
UnityMenuSettingsDefinitionEditorwith a dedicatedLifecycle Signalssection. - Lifecycle signal lists now provide:
- add/remove controls,
- drag-and-drop ordering,
- subtype selection menus,
- consistent inspector styling with the rest of Serenity editors.
- Improved inspector UX consistency by reusing the same signal creation patterns already present in other Serenity systems.
Fixed
- Fixed lifecycle signal inspector rendering so
EventDispatcherSignalimplementations can be selected correctly. - Fixed serialization flow for polymorphic lifecycle signals using Unity managed references.
- Ensured legacy menu assets continue working safely with empty lifecycle signal collections.
Infrastructure
- Reused existing
EventDispatcherSignalinfrastructure and dispatch flow without introducing parallel lifecycle systems. - Kept Clean Architecture boundaries intact by exposing lifecycle signals through read-only business-layer abstractions.
1.0.2 — Editor & Localization Inspector Improvements
Added
UnityLocalizationLocaleEditorUtils, a reflection-based editor helper for safe Unity Localization locale discovery without assembly dependency overhead.
Changed
- Enhanced
LocalizationSettingsDefinitionEditorto improve the UX forUnityLocalizationGameSettingsDefinitionassets. - Hardened Serenity import workflow and localization recovery process.
- Refactored modal settings editor button signal flow for cleaner editor interactions.
Features
- Locked the
ValueTypefield toSELECTABLEwith automatic normalization and safety validation to prevent configuration errors. - Replaced the free-text "Key" input in the Options table with a dynamic dropdown populated from Unity Localization locales.
Improved
- Added fallback support for unknown keys and informative HelpBoxes to guide users when Localization settings are missing or unconfigured.
- Package initialization stability after importing Serenity into a fresh Unity project.
Fixed
- Loading overlay background color resolution when using rendering cameras.
Infrastructure
- Reused existing
FoundationEditorandUnityGameSettingsDefinitionEditorUI utilities to maintain visual and functional consistency.
1.0.0 — Initial Release
✨ Features
Decoupled game logic with zero engine dependencies in core layers. All domain and application code compiles under noEngineReferences: true, ensuring business rules are fully portable, testable, and free of Unity coupling.
Extensible, layered persistence system. A unified storage hierarchy supports key-value stores (backed by PlayerPrefs), file-based blob stores with atomic writes, and append-only streams — all behind swappable contracts that can target local files, cloud services, or custom backends.
Advanced asset preloading with memory budgets. A priority-aware prefetch engine with LRU eviction, configurable memory budgets, sliding-window and on-demand strategies, and Addressables-based label resolution provides predictable asset availability with controllable resource pressure.
Typed, repository-persisted game settings. A generic settings system supports Boolean, Integer, Float, and Selectable option types with value-change notifications, automatic persistence, and reactive integration with audio, graphics, and localization modules.
State-driven character management. Characters follow a well-defined lifecycle (Spawning → Active → Dying → Dead) with hit-point tracking, immutable snapshots, and virtual extension points for game-specific specialization.
Game-agnostic combo counter. A pure counting model with immutable snapshots that imposes no gameplay semantics — timeout, multiplier, and scoring logic remain the consuming layer's responsibility.
Opaque checkpoint persistence. Named save slots with extensible metadata (timestamp, label, stage) store arbitrary binary payloads without interpreting or validating their contents, leaving serialization strategy to consumers.
Configurable initialization pipeline. An ordered phase-and-task startup system with weighted progress tracking, per-task criticality (Critical vs. NonCritical), and pluggable execution policies (sequential or parallel per phase).
Complete procedural animation system. A data-driven, key-based procedural expression engine supports layered pose composition (oscillation, drift, noise, impulse), material property animation, transform scale animation, discrete one-shot actions (flinch, recoil, stumble), rule-based activation with hysteresis conditions, and real-time tuning — all fully product-agnostic.
Type-safe publish/subscribe event system. A centralized event dispatcher with auto-registering actions, typed signal classes, and attribute-based discovery enables decoupled inter-module communication.
Multi-category audio playback. A gateway-routed audio system supports SFX, Music, Voice, Ambient, Environment, and UI channels with per-category pooling and settings-driven clip configuration.
Dedicated music player with crossfade support. Background music management provides play, stop, fade-in, fade-out, and crossfade operations independently from the short-form audio system.
Audio mixer abstraction. Group-based volume and mute management (Master, Music, SFX, Voice, UI) with automatic persistence through game settings integration.
Stage lifecycle management. A top-level stage aggregate tracks start, completion, and failure states with signal-based notifications consumed by downstream modules such as waves, timers, and scoring.
Sequential wave progression. Wave-by-wave stage structure with automatic clear detection and cascading signals for wave start, wave cleared, and all-waves-cleared events.
Dynamic multi-metric scoring. An unbounded scoring model addressed by named keys supports runtime metric registration and full arithmetic operations (add, subtract, multiply, divide, set, reset) with repository-backed persistence.
Application mode management. A game-mode service coordinates transitions between Menu, Game, and Pause states with pluggable pause strategies, input action-map switching, and signal-driven coordination.
Session lifecycle tracking. Per-session state management with engine-agnostic time sources, frame-by-frame tick accumulation, and immutable session snapshots.
Timer management system. Named timers with countdown, elapsed, and repeating modes provide normalized progress, pause/resume control, and signal-based lifecycle notifications.
Menu navigation with stack support. A navigation-stack-based menu system supports show, hide, push, pop, and peek operations with per-menu configuration and lifecycle signals.
Modal dialog system. Configurable modal dialogs with button factories, callback-based result handling, and pre-built signals for common confirmations (exit application, restart game, reset settings).
Platform-agnostic UI foundation. A view hierarchy, theme/style system, and component model enable composable UI construction without engine dependencies in the domain layer.
Game UI state management. Abstract HUD and results-screen state models with presenter-port rendering delegation enable testing UI logic in isolation from rendering infrastructure.
Localization with settings integration. Game and voice language management with automatic language switching driven by persistent game settings changes.
Graphics settings management. Reactive quality level, screen resolution, and fullscreen mode management driven by game settings value-change events.
System configuration detection. Hardware capability queries (memory, GPU, display) with recommended quality profile generation for automatic configuration.
Generic spawning and pooling model. Handle-tracked entity creation and destruction with pool-state queries, decoupled from instantiation mechanics via a factory port.
Gameplay entity identity. GUID-based entity identity with semantic classification (Player, Character, Hazard) provides a shared reference vocabulary across gameplay systems.
Rail-based movement model. Named rail paths with normalized progress tracking enable externally-driven on-rails motion without coupling to interpolation or easing logic.
Weapon state management. Trigger mechanics, fire-mode switching, and magazine/ammo tracking with read-only snapshots — independent of visual representation or projectile systems.
Sequence orchestration engine. A generic ordered-execution system provides completion-based stage iteration consumed by vertical aggregates such as the cutscene player.
Cinematic cutscene playback. Timed stage execution with fade, timeline, wait, and dialog stage types built on top of the sequence orchestration foundation.
Structured logging with category-based verbosity. A configurable logging system with severity levels, per-category overrides, log routing profiles, and component loggers consumed by every module.
View browser navigation. Forward/back screen browsing with navigation state queries for UI-driven browsing flows.
Minimal service locator. A dictionary-backed service resolution contract for narrow use cases where constructor injection is impractical (e.g., reflection-instantiated event actions).
Composable task system. Async work-unit contracts with criticality levels, reflection-based method invocation, service-aware argument resolution, and main-thread dispatching support.
File-based persistence with atomic writes. A file-system blob store with write-then-rename safety, platform-specific path resolution, and append-only stream support.
🧱 Architecture
Clean Architecture enforcement. Every aggregate follows a strict Domain ← Application ← Installation layering with inward-only dependency arrows. Domain layers have zero or minimal external dependencies; application layers depend only on domain contracts and cross-cutting foundation services; installation layers wire platform-specific implementations.
Engine isolation via assembly definitions. Core business assemblies declare noEngineReferences: true, guaranteeing compile-time enforcement that no Unity API leaks into domain or application logic.
SOLID principles throughout. Single-responsibility aggregates, interface-segregated service contracts, open/closed extension via abstract installers and factory ports, and dependency inversion through platform-agnostic interfaces.
Domain-Driven Design vocabulary. Entities carry mutable state with guarded transitions, value objects provide immutable identity and snapshots, and aggregates define bounded contexts with explicit integration points.
Use-case-driven API design. Consumer-facing operations are encapsulated in typed use-case classes with dedicated input DTOs, bundled into injectable containers for clean dependency graphs.
Immutable snapshot pattern. All stateful aggregates expose read-only snapshots for queries, ensuring consumers cannot inadvertently mutate internal state.
Abstract installer pattern. Each aggregate defines an abstract installer that declares the wiring contract; concrete platform layers (Unity, tests, or custom targets) provide implementations without modifying business code.
Signal-based inter-module communication. Typed event signals flow through a centralized dispatcher, keeping aggregates decoupled while enabling reactive coordination.
📦 Modules
Global — Foundation contracts, lifecycle events (exit/restart), use-case interface hierarchy, component model for UI composition, and the abstract installer base consumed by every other aggregate.
EventDispatcher — Type-safe publish/subscribe event system with auto-registering actions, typed signal classes, and attribute-based discovery.
Logging — Configurable logging with severity levels, category-based verbosity overrides, log routing profiles, component loggers, and file/console output support.
ServiceLocator — Minimal typed service resolution with a dictionary-backed default implementation.
Task — Async work-unit contracts with criticality, reflection-based method invocation, and extensible argument resolution.
InitializationPipeline — Ordered phase-and-task startup system with weighted progress tracking, criticality-based failure handling, and pluggable execution policies.
Persistence — Layered storage hierarchy: key-value stores, stream-based blob stores, and append-only stores — all behind swappable platform contracts.
FilePersistence — File-system blob store with atomic write-then-rename safety and platform-specific path resolution.
PlayerPrefsPersistence — Lightweight Unity PlayerPrefs-backed key-value store with Base64 encoding.
GameSettings — Typed settings system (Boolean, Integer, Float, Selectable) with repository persistence and value-change notifications.
Checkpoint — Opaque binary checkpoint persistence with named slots (Slot1–3, Auto, Quick) and extensible metadata.
Score — Dynamic multi-metric scoring model with unbounded key-based metrics, full arithmetic operations, and repository persistence.
Combo — Game-agnostic combo counter with immutable snapshots and virtual extension points for multiplier, timeout, or decay behavior.
Character — State-driven character lifecycle (Spawning → Active → Dying → Dead) with hit-point management, inheritable status enums, and immutable snapshots.
GameplayEntity — GUID-based entity identity with semantic classification and lightweight cross-system references.
GameSpawner — Handle-tracked entity spawning and pool-state management with a factory port for instantiation strategy.
Stage — Top-level stage lifecycle (NotStarted → InProgress → Completed/Failed) with spawn-point resolution and rail-path authoring contracts.
Wave — Sequential wave progression with automatic clear detection and cascading lifecycle signals.
Timer — Named timer management with countdown, elapsed, and repeating modes, normalized progress, and lifecycle signals.
GameMode — Application mode state machine (Menu, Game, Pause) with pluggable pause strategies and signal-driven transitions.
GameSession — Per-session lifecycle tracking with engine-agnostic time sources and tick-based elapsed time accumulation.
AudioPlayer — Multi-category audio playback with gateway routing, channel pooling, and use-case-driven operations.
MusicPlayer — Background music management with play, stop, fade, and crossfade operations.
SoundMixer — Group-based volume and mute management with reactive game settings integration.
GameGraphics — Reactive quality level, resolution, and fullscreen management driven by game settings changes.
SystemConfiguration — Hardware capability detection with recommended quality profile generation.
PlayerInput — Platform-agnostic input abstraction with action-map switching and input-action binding contracts.
Ui — View hierarchy, theme/style system, and component model for composable, engine-independent UI construction.
Menu — Navigation-stack-based menu system with per-menu configuration and lifecycle signals.
Modal — Configurable modal dialogs with button factories, callback-based results, and pre-built confirmation signals.
GameUi — Abstract HUD and results-screen state management with presenter-port delegation.
ViewBrowser — Forward/back screen navigation with state queries.
Localization — Game and voice language management with automatic settings-driven language switching.
SequencePlayer — Generic ordered-execution orchestration engine for completion-based stage iteration.
CutscenePlayer — Cinematic playback with timed stages (fade, timeline, wait, dialog) built on the sequence orchestration foundation.
GameRail — Named rail-path registration with normalized progress tracking for on-rails movement.
GameWeapon — Trigger mechanics, fire-mode switching, and magazine/ammo tracking with read-only snapshots.
ProceduralExpression — Data-driven procedural animation system with layered pose composition, material/transform animation, rule-based activation, discrete actions, and real-time tuning support.
Shared — Cross-cutting constants (service names, module labels, context identifiers) and utility classes (parsing, reflection, GUID generation).
🛠️ Tooling
DocFX-based API documentation generator. An integrated documentation builder accessible from Tools → Serenity → Docs compiles all assemblies with Roslyn XML documentation and generates a navigable static API site via DocFX — with automatic installation, configuration generation, and branded template support.
Procedural Expression setup tool. A one-click setup wizard (Tools → Serenity → Procedural Expression → Setup Minimal Idle) auto-detects skeleton bones, generates all required configuration assets, and wires a procedural animation profile to any prefab — supporting rigged characters, simple objects, props, and UI elements.
Asset Prefetcher diagnostics inspector. A custom Editor inspector for the prefetch service provides cache refresh, clear, clipboard export, diagnostics display, auto-refresh polling, and color-coded asset category visualization.
System Configuration inspector. A custom inspector for system configuration settings provides comprehensive interface for data collection timing, scope, and heuristic tuning.
Menu and Modal inspectors. Custom Editor inspectors for menu views and modal components provide read-only configuration display, signal binding management, and button configuration interfaces.
ScriptableObject-based configuration. Prefetch policy profiles, procedural expression profiles, state keys, layers, actions, rules, audio settings, game settings definitions, and localization tables are all authored as ScriptableObject assets — enabling non-programmer configuration and version-controlled presets.
Abstract installer pattern for platform wiring. Each aggregate defines an abstract installer with explicit dependencies; Unity-specific concrete installers handle MonoBehaviour creation, Addressables integration, and service locator registration.
Procedural Expression debug panel. A runtime GUI overlay (toggled via F12) displays live state-key values with color-coded sliders, range hints, and reset controls for real-time tuning in Play Mode.
Procedural Expression custom property drawers. Bone ID reference drawers with profile-aware dropdown selection, rule editors with inline condition configuration, and profile editors with validation and derived-property display.
🎯 Purpose
Serenity exists to eliminate the recurring boilerplate that accompanies every Unity project: persistence wiring, settings management, audio routing, initialization sequencing, mode transitions, and event plumbing. Rather than providing opinionated gameplay systems, it supplies the architectural spine — clean contracts, layered boundaries, and composable modules — that game-specific code builds upon.
By enforcing strict engine isolation in core layers, Serenity ensures that business logic remains testable outside Unity, portable across platforms, and resilient to engine API changes. The abstract installer pattern means swapping a persistence backend or input system requires implementing a single interface, not refactoring a dependency tree.
Every module follows the same structural conventions: domain entities with guarded state transitions, immutable snapshots for safe queries, use-case classes with typed inputs, and signal-based integration points. This consistency reduces onboarding time and makes cross-module patterns immediately recognizable.
Serenity is not a game template. It provides no characters, no levels, no win conditions. It provides the foundation that makes those systems cleaner, faster to build, and easier to maintain across the lifetime of a project.
✨ Features
Decoupled game logic with zero engine dependencies in core layers. All domain and application code compiles under noEngineReferences: true, ensuring business rules are fully portable, testable, and free of Unity coupling.
Extensible, layered persistence system. A unified storage hierarchy supports key-value stores (backed by PlayerPrefs), file-based blob stores with atomic writes, and append-only streams — all behind swappable contracts that can target local files, cloud services, or custom backends.
Advanced asset preloading with memory budgets. A priority-aware prefetch engine with LRU eviction, configurable memory budgets, sliding-window and on-demand strategies, and Addressables-based label resolution provides predictable asset availability with controllable resource pressure.
Typed, repository-persisted game settings. A generic settings system supports Boolean, Integer, Float, and Selectable option types with value-change notifications, automatic persistence, and reactive integration with audio, graphics, and localization modules.
State-driven character management. Characters follow a well-defined lifecycle (Spawning → Active → Dying → Dead) with hit-point tracking, immutable snapshots, and virtual extension points for game-specific specialization.
Game-agnostic combo counter. A pure counting model with immutable snapshots that imposes no gameplay semantics — timeout, multiplier, and scoring logic remain the consuming layer's responsibility.
Opaque checkpoint persistence. Named save slots with extensible metadata (timestamp, label, stage) store arbitrary binary payloads without interpreting or validating their contents, leaving serialization strategy to consumers.
Configurable initialization pipeline. An ordered phase-and-task startup system with weighted progress tracking, per-task criticality (Critical vs. NonCritical), and pluggable execution policies (sequential or parallel per phase).
Complete procedural animation system. A data-driven, key-based procedural expression engine supports layered pose composition (oscillation, drift, noise, impulse), material property animation, transform scale animation, discrete one-shot actions (flinch, recoil, stumble), rule-based activation with hysteresis conditions, and real-time tuning — all fully product-agnostic.
Type-safe publish/subscribe event system. A centralized event dispatcher with auto-registering actions, typed signal classes, and attribute-based discovery enables decoupled inter-module communication.
Multi-category audio playback. A gateway-routed audio system supports SFX, Music, Voice, Ambient, Environment, and UI channels with per-category pooling and settings-driven clip configuration.
Dedicated music player with crossfade support. Background music management provides play, stop, fade-in, fade-out, and crossfade operations independently from the short-form audio system.
Audio mixer abstraction. Group-based volume and mute management (Master, Music, SFX, Voice, UI) with automatic persistence through game settings integration.
Stage lifecycle management. A top-level stage aggregate tracks start, completion, and failure states with signal-based notifications consumed by downstream modules such as waves, timers, and scoring.
Sequential wave progression. Wave-by-wave stage structure with automatic clear detection and cascading signals for wave start, wave cleared, and all-waves-cleared events.
Dynamic multi-metric scoring. An unbounded scoring model addressed by named keys supports runtime metric registration and full arithmetic operations (add, subtract, multiply, divide, set, reset) with repository-backed persistence.
Application mode management. A game-mode service coordinates transitions between Menu, Game, and Pause states with pluggable pause strategies, input action-map switching, and signal-driven coordination.
Session lifecycle tracking. Per-session state management with engine-agnostic time sources, frame-by-frame tick accumulation, and immutable session snapshots.
Timer management system. Named timers with countdown, elapsed, and repeating modes provide normalized progress, pause/resume control, and signal-based lifecycle notifications.
Menu navigation with stack support. A navigation-stack-based menu system supports show, hide, push, pop, and peek operations with per-menu configuration and lifecycle signals.
Modal dialog system. Configurable modal dialogs with button factories, callback-based result handling, and pre-built signals for common confirmations (exit application, restart game, reset settings).
Platform-agnostic UI foundation. A view hierarchy, theme/style system, and component model enable composable UI construction without engine dependencies in the domain layer.
Game UI state management. Abstract HUD and results-screen state models with presenter-port rendering delegation enable testing UI logic in isolation from rendering infrastructure.
Localization with settings integration. Game and voice language management with automatic language switching driven by persistent game settings changes.
Graphics settings management. Reactive quality level, screen resolution, and fullscreen mode management driven by game settings value-change events.
System configuration detection. Hardware capability queries (memory, GPU, display) with recommended quality profile generation for automatic configuration.
Generic spawning and pooling model. Handle-tracked entity creation and destruction with pool-state queries, decoupled from instantiation mechanics via a factory port.
Gameplay entity identity. GUID-based entity identity with semantic classification (Player, Character, Hazard) provides a shared reference vocabulary across gameplay systems.
Rail-based movement model. Named rail paths with normalized progress tracking enable externally-driven on-rails motion without coupling to interpolation or easing logic.
Weapon state management. Trigger mechanics, fire-mode switching, and magazine/ammo tracking with read-only snapshots — independent of visual representation or projectile systems.
Sequence orchestration engine. A generic ordered-execution system provides completion-based stage iteration consumed by vertical aggregates such as the cutscene player.
Cinematic cutscene playback. Timed stage execution with fade, timeline, wait, and dialog stage types built on top of the sequence orchestration foundation.
Structured logging with category-based verbosity. A configurable logging system with severity levels, per-category overrides, log routing profiles, and component loggers consumed by every module.
View browser navigation. Forward/back screen browsing with navigation state queries for UI-driven browsing flows.
Minimal service locator. A dictionary-backed service resolution contract for narrow use cases where constructor injection is impractical (e.g., reflection-instantiated event actions).
Composable task system. Async work-unit contracts with criticality levels, reflection-based method invocation, service-aware argument resolution, and main-thread dispatching support.
File-based persistence with atomic writes. A file-system blob store with write-then-rename safety, platform-specific path resolution, and append-only stream support.
🧱 Architecture
Clean Architecture enforcement. Every aggregate follows a strict Domain ← Application ← Installation layering with inward-only dependency arrows. Domain layers have zero or minimal external dependencies; application layers depend only on domain contracts and cross-cutting foundation services; installation layers wire platform-specific implementations.
Engine isolation via assembly definitions. Core business assemblies declare noEngineReferences: true, guaranteeing compile-time enforcement that no Unity API leaks into domain or application logic.
SOLID principles throughout. Single-responsibility aggregates, interface-segregated service contracts, open/closed extension via abstract installers and factory ports, and dependency inversion through platform-agnostic interfaces.
Domain-Driven Design vocabulary. Entities carry mutable state with guarded transitions, value objects provide immutable identity and snapshots, and aggregates define bounded contexts with explicit integration points.
Use-case-driven API design. Consumer-facing operations are encapsulated in typed use-case classes with dedicated input DTOs, bundled into injectable containers for clean dependency graphs.
Immutable snapshot pattern. All stateful aggregates expose read-only snapshots for queries, ensuring consumers cannot inadvertently mutate internal state.
Abstract installer pattern. Each aggregate defines an abstract installer that declares the wiring contract; concrete platform layers (Unity, tests, or custom targets) provide implementations without modifying business code.
Signal-based inter-module communication. Typed event signals flow through a centralized dispatcher, keeping aggregates decoupled while enabling reactive coordination.
📦 Modules
Global — Foundation contracts, lifecycle events (exit/restart), use-case interface hierarchy, component model for UI composition, and the abstract installer base consumed by every other aggregate.
EventDispatcher — Type-safe publish/subscribe event system with auto-registering actions, typed signal classes, and attribute-based discovery.
Logging — Configurable logging with severity levels, category-based verbosity overrides, log routing profiles, component loggers, and file/console output support.
ServiceLocator — Minimal typed service resolution with a dictionary-backed default implementation.
Task — Async work-unit contracts with criticality, reflection-based method invocation, and extensible argument resolution.
InitializationPipeline — Ordered phase-and-task startup system with weighted progress tracking, criticality-based failure handling, and pluggable execution policies.
Persistence — Layered storage hierarchy: key-value stores, stream-based blob stores, and append-only stores — all behind swappable platform contracts.
FilePersistence — File-system blob store with atomic write-then-rename safety and platform-specific path resolution.
PlayerPrefsPersistence — Lightweight Unity PlayerPrefs-backed key-value store with Base64 encoding.
GameSettings — Typed settings system (Boolean, Integer, Float, Selectable) with repository persistence and value-change notifications.
Checkpoint — Opaque binary checkpoint persistence with named slots (Slot1–3, Auto, Quick) and extensible metadata.
Score — Dynamic multi-metric scoring model with unbounded key-based metrics, full arithmetic operations, and repository persistence.
Combo — Game-agnostic combo counter with immutable snapshots and virtual extension points for multiplier, timeout, or decay behavior.
Character — State-driven character lifecycle (Spawning → Active → Dying → Dead) with hit-point management, inheritable status enums, and immutable snapshots.
GameplayEntity — GUID-based entity identity with semantic classification and lightweight cross-system references.
GameSpawner — Handle-tracked entity spawning and pool-state management with a factory port for instantiation strategy.
Stage — Top-level stage lifecycle (NotStarted → InProgress → Completed/Failed) with spawn-point resolution and rail-path authoring contracts.
Wave — Sequential wave progression with automatic clear detection and cascading lifecycle signals.
Timer — Named timer management with countdown, elapsed, and repeating modes, normalized progress, and lifecycle signals.
GameMode — Application mode state machine (Menu, Game, Pause) with pluggable pause strategies and signal-driven transitions.
GameSession — Per-session lifecycle tracking with engine-agnostic time sources and tick-based elapsed time accumulation.
AudioPlayer — Multi-category audio playback with gateway routing, channel pooling, and use-case-driven operations.
MusicPlayer — Background music management with play, stop, fade, and crossfade operations.
SoundMixer — Group-based volume and mute management with reactive game settings integration.
GameGraphics — Reactive quality level, resolution, and fullscreen management driven by game settings changes.
SystemConfiguration — Hardware capability detection with recommended quality profile generation.
PlayerInput — Platform-agnostic input abstraction with action-map switching and input-action binding contracts.
Ui — View hierarchy, theme/style system, and component model for composable, engine-independent UI construction.
Menu — Navigation-stack-based menu system with per-menu configuration and lifecycle signals.
Modal — Configurable modal dialogs with button factories, callback-based results, and pre-built confirmation signals.
GameUi — Abstract HUD and results-screen state management with presenter-port delegation.
ViewBrowser — Forward/back screen navigation with state queries.
Localization — Game and voice language management with automatic settings-driven language switching.
SequencePlayer — Generic ordered-execution orchestration engine for completion-based stage iteration.
CutscenePlayer — Cinematic playback with timed stages (fade, timeline, wait, dialog) built on the sequence orchestration foundation.
GameRail — Named rail-path registration with normalized progress tracking for on-rails movement.
GameWeapon — Trigger mechanics, fire-mode switching, and magazine/ammo tracking with read-only snapshots.
ProceduralExpression — Data-driven procedural animation system with layered pose composition, material/transform animation, rule-based activation, discrete actions, and real-time tuning support.
Shared — Cross-cutting constants (service names, module labels, context identifiers) and utility classes (parsing, reflection, GUID generation).
🛠️ Tooling
DocFX-based API documentation generator. An integrated documentation builder accessible from Tools → Serenity → Docs compiles all assemblies with Roslyn XML documentation and generates a navigable static API site via DocFX — with automatic installation, configuration generation, and branded template support.
Procedural Expression setup tool. A one-click setup wizard (Tools → Serenity → Procedural Expression → Setup Minimal Idle) auto-detects skeleton bones, generates all required configuration assets, and wires a procedural animation profile to any prefab — supporting rigged characters, simple objects, props, and UI elements.
Asset Prefetcher diagnostics inspector. A custom Editor inspector for the prefetch service provides cache refresh, clear, clipboard export, diagnostics display, auto-refresh polling, and color-coded asset category visualization.
System Configuration inspector. A custom inspector for system configuration settings provides comprehensive interface for data collection timing, scope, and heuristic tuning.
Menu and Modal inspectors. Custom Editor inspectors for menu views and modal components provide read-only configuration display, signal binding management, and button configuration interfaces.
ScriptableObject-based configuration. Prefetch policy profiles, procedural expression profiles, state keys, layers, actions, rules, audio settings, game settings definitions, and localization tables are all authored as ScriptableObject assets — enabling non-programmer configuration and version-controlled presets.
Abstract installer pattern for platform wiring. Each aggregate defines an abstract installer with explicit dependencies; Unity-specific concrete installers handle MonoBehaviour creation, Addressables integration, and service locator registration.
Procedural Expression debug panel. A runtime GUI overlay (toggled via F12) displays live state-key values with color-coded sliders, range hints, and reset controls for real-time tuning in Play Mode.
Procedural Expression custom property drawers. Bone ID reference drawers with profile-aware dropdown selection, rule editors with inline condition configuration, and profile editors with validation and derived-property display.
🎯 Purpose
Serenity exists to eliminate the recurring boilerplate that accompanies every Unity project: persistence wiring, settings management, audio routing, initialization sequencing, mode transitions, and event plumbing. Rather than providing opinionated gameplay systems, it supplies the architectural spine — clean contracts, layered boundaries, and composable modules — that game-specific code builds upon.
By enforcing strict engine isolation in core layers, Serenity ensures that business logic remains testable outside Unity, portable across platforms, and resilient to engine API changes. The abstract installer pattern means swapping a persistence backend or input system requires implementing a single interface, not refactoring a dependency tree.
Every module follows the same structural conventions: domain entities with guarded state transitions, immutable snapshots for safe queries, use-case classes with typed inputs, and signal-based integration points. This consistency reduces onboarding time and makes cross-module patterns immediately recognizable.
Serenity is not a game template. It provides no characters, no levels, no win conditions. It provides the foundation that makes those systems cleaner, faster to build, and easier to maintain across the lifetime of a project.
English
Español
Català