Cutscene Player

An ordered, timed cutscene player that plays fades, Unity Timelines and waits safely during boot, with a wizard and a live Timeline preview for authoring.

What the system is for

A splash screen, an intro cinematic or a boss-defeat cutscene all need the same thing: play a sequence of timed beats — fade to black, run a Timeline, wait, fade back in — in order, without ever hanging the game if one beat misbehaves. Hand-rolled coroutine chains get this working once, then break the moment someone adds a stage or ports the project to WebGL, where a stalled audio context can freeze anything waiting on it.

The Cutscene Player in Serenity models a cutscene as an ordered list of stages played by a single service. Each stage — and the cutscene as a whole — runs under a hard wall-clock timeout, so playback is safe to call during boot, before the rest of the game has spun up, without risking a stuck loading screen.

The Unity problem

Cinematic sequencing in Unity tends to accrete: a coroutine here, a PlayableDirector call there, an Invoke for the fade, and no single place that owns the order or the timing. Adding a stage means editing code. Testing a cutscene means entering Play mode and watching it happen in real time, stage by stage, with no way to scrub back to the part that just broke.

Boot-time cutscenes are riskier still. A splash screen that plays before the game has finished initializing cannot assume a healthy frame rate or a running audio context, especially on WebGL. A stage that waits on something that never resolves can hang the entire boot sequence, leaving players staring at a frozen logo.

How Serenity approaches it

Serenity models a cutscene as a UnityCutsceneDefinition — an ordered list of UnityCutsceneStep stages, each typed as fade in, fade out, play a Unity Timeline, wait or custom. ICutscenePlayerService.PlayAsync(id, ct) plays a definition end to end, one-shot or looping, driving a full-screen fade overlay and a PlayableDirector on the cutscene's own rig prefab as it advances through the stages.

Every stage runs under its own hard timeout, and the whole cutscene runs under a second, outer timeout, both measured against wall-clock time rather than frame delta. That means a hung Timeline or a stalled fade can never block the caller indefinitely — playback always completes or times out, which is what makes it safe to trigger from the boot pipeline before the rest of the game exists.

How it fits into Serenity

Cutscene Player composes the generic Sequence Player's stage-orchestration contracts — ISequenceDefinition and ISequenceStage — while owning its own stage execution, fade overlay and rig handling through CutsceneStageType. The rig prefab is instantiated for the duration of playback and destroyed afterward, so a cutscene with no rig plays nothing but a plain fade transition.

The service is registered into the ServiceLocator during installation, so any code — including a generated no-code trigger action — can resolve ICutscenePlayerService without manual wiring. Definitions are discovered by Addressables label from a UnityCutscenePlayerSettings asset, keeping authored cutscenes decoupled from the code that plays them.

Practical workflow

  1. Open Tools ▸ Serenity ▸ Create ▸ Cutscenes ▸ Cutscene Wizard and pick a template — Logo splash, Timeline cutscene, Fade transition or Blank — on the Template step.
  2. Reorder, add or remove stages on the Stages step, setting duration, fade color or the Timeline asset for each one.
  3. Choose a rig on the Rig step — none, an existing prefab, or a new empty prefab with a PlayableDirector — for stages that need visible content.
  4. Optionally generate a no-code play trigger and a boot task on the Trigger step, so the cutscene can fire from a SignalEmitterComponent or from the initialization pipeline with no game code.
  5. Create the definition, then open the Cutscene Outline window to scrub through every stage with a live Timeline preview rendered through the rig's own camera, entirely outside Play mode.
  6. Call ICutscenePlayerService.PlayAsync(id, ct) from game code, or dispatch the generated trigger signal, to play the cutscene at runtime.

What you get

  • ICutscenePlayerService.PlayAsync(id, ct) with one-shot or looping playback, self-bounded by hard wall-clock timeouts
  • UnityCutsceneDefinition authored as an ordered list of UnityCutsceneStep stages — fade in, fade out, play Timeline, wait, custom
  • Five-step Cutscene Wizard — Template ▸ Stages ▸ Rig ▸ Trigger ▸ Create — with an optional no-code play trigger and boot task
  • Cutscene Outline window with a live, scrubbable Timeline preview rendered through the rig's own camera, no Play mode required
  • Per-stage and whole-cutscene hard timeouts, safe to call from the boot pipeline without risking a stuck splash screen
  • Full-screen fade overlay driven automatically for FadeIn/FadeOut stages, reused across every cutscene
  • Built on the generic Sequence Player's stage-orchestration contracts, kept independent from cinematic-specific concerns
  • ServiceLocator registration so generated triggers and game code can resolve the player with no manual DI wiring

When to use this

  • Splash screens and intro cinematics that must play safely during boot, before the rest of the game has initialized, including on WebGL.
  • Boss intros, level transitions or story beats that combine a Unity Timeline with fades, authored without writing coroutine code by hand.
  • Projects that want a no-code way to trigger a cutscene from a button, an input action or a trigger volume through a generated Signal.
  • Teams that need to review a cutscene's timing and content in the editor — scrubbing every stage — without entering Play mode each time.

Related systems

Use Serenity when you want cinematic cutscenes that are authored, previewed and triggered without code, but still play with the hard timing guarantees a boot-time splash screen needs.

Back to the home page