Manual

Cutscenes

Several actors on one clock — camera cuts, animation, events and sound on a timeline, previewed in the editor and played in the game.

Sequences

Overview

A cutscene is a Sequence asset: one timeline that drives several entities of a scene at once. Its bindings name the actors — a door, a character, two cameras — and its tracks say what each of them does over time. A Sequence Player component plays it in the game; the Cinematic tab authors and previews it in the editor. Both evaluate the sequence with the same code, so what the tab shows at a given second is what the game shows.

  • Create one from the Content Browser: Create ▸ Animation ▸ Sequence. Double-click it to open the Cinematic tab.
  • Actors are bound by identity, not by name. A binding stores the entity's id, so renaming or moving the entity keeps the cutscene working. The name is a label; when the entity is gone the binding shows it in red as (missing), and its tracks are skipped instead of failing.
  • Sequences are separate from Property Animation clips. The Sequencer tab still edits a single entity's looping property clip (a platform, a pulsing light); a Sequence is for scenes with several actors and a camera.

What moves

Tracks

Each track belongs to one actor, except camera cuts and — when they have no actor — events and sounds, which belong to the sequence itself.

TrackWhat it does
Property Keys on one value: position, rotation or scale per axis, material colour, metallic, roughness, opacity, a camera's Field of View, or Visible. Values between keys are interpolated linearly; Visible is a switch and holds the last key's value until the next one.
Skeletal Sections that each play an animation clip on the actor's skeleton, with a start, an end, a clip offset, a play rate and an optional loop. While a section is live the sequence poses the skeleton in place of the entity's Animator; layers and IK still apply on top.
Camera Cuts Which camera the game looks through, from each cut on. A cut can blend in over a number of seconds with a Linear, Smooth Step or Ease Out curve. One per sequence.
Event Named markers, delivered to scripts and graphs as an animation notify — a marker with a duration sends a begin and an end.
Audio Sounds started at a time, with volume and pitch; with an actor they play at its position.
◆

Events and sounds only fire while a cutscene plays. Scrubbing the timeline in the editor, or jumping with sequence.setTime, fires nothing in between and does not start a sound halfway through — dragging the playhead back and forth never sets off twenty explosions.

Author

The Cinematic Tab

The tab shows the camera-cut row at the top, then one foldable group per actor with its tracks, and finally Unbound — tracks whose actor was removed, kept so you can delete them. Keys are diamonds, sections are bars, cuts, events and sounds are flags on their rows; a cut with a blend draws its ramp.

  • Transport — Play/Pause (Space), Stop, Loop, the length, zoom. Click the ruler to scrub; the mouse wheel zooms.
  • Actors — select entities in the scene and use Bind Selected; Rebind to Selected points an existing binding at a different entity; Remove Binding takes its tracks and every cut to it along.
  • Editing — Add Track offers what fits the focused actor; Add at Playhead or a double-click adds a key, event or cut; drag items along the row, drag a section's edges to trim it, Delete removes. The panel below shows the selected item's values. A new property track starts with a key holding the actor's current value.
  • Preview — the tab renders its own picture of the scene at the playhead, through the live cut's camera (Through Camera, blends included) or through the editor camera. The preview writes the sequence into the scene only for the length of that one picture and puts everything back before anything else can see it: saving, undo, play mode and a collaboration session never see a cutscene frame, and the scene is never marked modified by previewing.
  • Undo, Save and reload work like every other asset tab; a sequence cannot end before its last key, cut, event, sound or section.

Frame the shot

Looking Through a Camera

In the Scene window, select a camera entity and choose View ▸ Look Through Selected Camera in the viewport toolbar. The viewport renders through that camera — its position, heading and field of view — and the View cell reads Camera. The lock is on the camera, not on the selection: select and move the actors while the shot stays on screen, or move the camera itself with the gizmo and the picture follows.

  • Flying, orbiting or zooming ends the lock and carries on from the camera's position, so you can nudge the view and then place the camera there.
  • A view preset, a bookmark, F or Stop Looking Through Camera returns to the editor camera. Deleting the camera or starting play does too.
  • Editor icons are hidden while looking through — the picture is the shot.

Run it

Playing a Cutscene

Add a Sequence Player component (Add Component ▸ Animation) to any entity — a trigger volume, an empty "Director" — and give it the sequence. The entity with the player is the cutscene's owner: scripts address the cutscene through it, and it receives the end notification.

SettingMeaning
Autoplay Starts when the scene starts.
Loop Wraps around at the end instead of finishing.
Play Rate Speed; negative plays backwards.
Blend Out, Blend Out Curve How the view returns to the player's camera rig when the cutscene ends or is stopped.
Lock Player Input The player's character ignores movement input while the cutscene runs.

A cutscene runs on game time: time.setTimeScale slows it and a pause holds it. Switching the owner off (deactivating it) stops the cutscene; destroying it mid-shot still hands the camera back. Assets a sequence uses — its clips and sounds — are loaded with the scene, so a cutscene does not start with a missing animation in a packaged game.

The view

Cuts, Blends and Control

While a playing sequence has camera cuts, it owns the camera: the player's camera rig and the editor's fly camera leave it alone. Each cut makes its camera the main one; a cut with a blend-in moves position, rotation and field of view from the previous camera to the new one. The first cut blends from wherever the gameplay camera was when the cutscene started. Only one sequence owns the camera at a time; a second one takes over when the first lets go.

At the end — or on sequence.stop — the view goes back to the player's rig over the player's Blend Out time. Lock Player Input locks movement, not looking: a cutscene without camera cuts still lets the mouse turn the rig.

Control it

From Scripts

Eight functions under sequence, the same in Lua, Python, HorizonCode and C++. Every one takes the owner — the entity with the Sequence Player.

FunctionDoes
play(owner) → started Starts, or resumes from a pause.
pause(owner) Holds the clock and the sounds; actors, camera and input lock stay with the cutscene.
stop(owner) Ends and rewinds: sounds stop, the camera returns, the lock lifts. This is a skip button.
setTime(owner, seconds) Jumps; nothing in between fires.
getTime(owner), duration(owner) Where the playhead is, how long the sequence is.
isPlaying(owner) True while the clock runs (false when paused).
bindSlot(owner, binding, entity) Plays a binding — addressed by its name — with a different entity, e.g. the player character spawned at runtime in place of a stand-in. 0 restores the authored actor.

When a cutscene finishes — at its natural end, or when a running one is stopped — the owner receives the animation notify SequenceFinished. Because a skip is stop, whatever waits for the end runs after a skip as well. A looping cutscene never finishes by itself.

intro_director.lua
local M = {}

-- On the entity with the Sequence Player (Autoplay off).
function M.onStart(self)
    -- The sequence was authored against a stand-in called "Hero".
    local player = horizon.entity.findByName("Player")
    horizon.sequence.bindSlot(self.entityId, "Hero", player)
    horizon.sequence.play(self.entityId)
end

function M.onUpdate(self, dt)
    -- "Skip" is an Input Action (Project Settings ▸ Input) bound to a key.
    if horizon.input.actionPressed("Skip") then
        horizon.sequence.stop(self.entityId)   -- a skip still finishes
    end
end

function M.onAnimationNotify(self, name)
    if name == "SequenceFinished" then
        horizon.scene.load("Levels/Chapter1.hescene", false)
    end
end

return M
intro_director.py
import horizon

class IntroDirector(horizon.Behavior):
    # On the entity with the Sequence Player (Autoplay off).
    def on_start(self):
        # The sequence was authored against a stand-in called "Hero".
        player = horizon.entity.findByName("Player")
        horizon.sequence.bindSlot(self.entity_id, "Hero", player)
        horizon.sequence.play(self.entity_id)

    def on_update(self, dt):
        # "Skip" is an Input Action (Project Settings ▸ Input) bound to a key.
        if horizon.input.actionPressed("Skip"):
            horizon.sequence.stop(self.entity_id)   # a skip still finishes

    def on_animation_notify(self, name):
        if name == "SequenceFinished":
            horizon.scene.load("Levels/Chapter1.hescene", False)

In HorizonCode the same eight are nodes in the Sequence category (Play Sequence, Stop Sequence, …), and the end arrives at On Animation Notify. Your own event markers arrive the same way, under the name you gave them.

Automate

From an AI Client

With Editor Remote Control on, an MCP client can read and write sequences. sequence_info lists every sequence, or returns one as a document — bindings, tracks and who each binding is in the open scene. sequence_write takes that document back, changed. Actors are named by the entity id entity_list reports, clips and sounds by their content path, targets and blend curves by name. A document the runtime would get silently wrong — two actors on one slot, keys out of order, a second camera-cut track, content past the end — is refused with the reason, and nothing is written. A sequence open with unsaved edits in a Cinematic tab is refused as well; a clean tab reloads. New sequences come from asset_create.

Know the edges

Limits

  • Keys interpolate linearly; there are no curve tangents yet.
  • No nested sequences (shots), and no actors spawned only for the cutscene — bind existing entities, or bind at runtime with bindSlot.
  • Skeletal sections do not blend into each other, and do not drive root motion.
  • No subtitle track — use an event and set the text from a script — and no fade, particle or video-export tracks.
  • A sound started by a cutscene cannot begin mid-way: a jump into the middle of a sound skips it.
  • The Cinematic tab's preview poses skeletons from the clip alone; layers and IK are applied only when the game plays.
  • A cutscene runs locally on each machine; starting it on every client of a networked game is up to your scripts.