Overview
"I want to create a cutscene..." "I need a boss entrance sequence..." "I want movie-like camera work..."
In game development, you often face these kinds of cinematic challenges. Timeline is a feature that lets you edit and manage in-game animations, audio, and camera movements along a timeline. Using the same concept as video editing timelines, you can visually create event sequences without writing code.
Components
Timeline consists of the following elements.
| Element | Description |
|---|---|
| Timeline Asset | Asset file that stores timeline configuration |
| Playable Director | Component attached to a GameObject that plays the Timeline |
| Track | Timeline axis that controls a specific element (animation, audio, etc.) |
| Clip | Individual element placed on a track |
Main Track Types
Activation Track
Controls a GameObject's active/inactive state along the timeline. Used for enemy appearances, UI toggling, etc.
Animation Track
Plays existing animation clips or records keyframe animations directly within the Timeline. Controls character movement, object translation/rotation, etc.
Audio Track
Places BGM and sound effects on the timeline. Supports synchronized playback of multiple audio sources, as well as volume and pitch adjustment.
Control Track
Controls Prefabs, nested timelines, and Particle Systems.
Main use cases:
- Nested Timeline: Plays another Timeline (for breaking complex sequences into manageable parts)
- Particle System: Controls effect playback timing
- Prefab instantiation: Spawns and destroys Prefabs at specific times
Signal Track
Fires events at specific times. Combined with a Signal Receiver, it communicates with external systems. Used for executing custom logic, updating UI, changing game state, etc.
Cinemachine Track
Controls Cinemachine virtual cameras. Switches between multiple camera views to achieve cinematic camera work.
Cinemachine 3.x key changes:
CinemachineVirtualCamera->CinemachineCameraCinemachineBrainsettings integrated into the camera componentCinemachineComposer->CinemachineRotationComposerCinemachineTransposer->CinemachineFollowCinemachineOrbitalTransposer->CinemachineOrbitalFollowCheck your Cinemachine version and use the appropriate component names.
Basic Usage
Setup Steps
1. Creating a Timeline Asset
- Right-click in the Project window > Create > Timeline
- Or open Window > Sequencing > Timeline and click the Create button
2. Setting Up the Playable Director
- Create an empty GameObject
- Drag and drop the Timeline asset onto the GameObject in the Hierarchy
- A Playable Director component is automatically added
3. Adding Tracks
- Click the "+" button or right-click in the Timeline window
- Select the desired track type
- Or drag and drop a GameObject into the Timeline window
4. Placing Clips
- Drag animation clips or audio clips onto tracks
- Or use Recording mode to directly record keyframes
Recording Mode
- Click the red circle button on the track to start recording
- Move along the timeline and change the object's Transform or properties
- Changes are automatically recorded as keyframes
- When you exit recording mode, an animation clip is generated
Recorded Clip: The generated clip is embedded within the Timeline asset as a Recorded Clip. You can later replace it with a regular AnimationClip or extract it to the Project window for reuse.
Cinemachine Integration
Cinemachine is Unity's advanced camera system that uses virtual cameras to achieve professional-quality camera work.
Integration Steps
1. Adding a Cinemachine Track
Add a "Cinemachine Track" to the Timeline and bind a camera that has a Cinemachine Brain component.
2. Placing Virtual Cameras
Place multiple Cinemachine Virtual Cameras in the scene and configure each with different angles and follow targets.
3. Creating Camera Shots
Drag and drop Virtual Cameras onto the Cinemachine Track. Adjust clip length to control camera display time, and arrange clips to create camera transitions.
4. Adjusting Blends
Adjust the blend time between clips to set up smooth camera transitions or hard cuts.
Practical Examples
Creating a Cutscene
- Plan the story flow
- Determine the required camera angles
- Place character animations
- Add dialogue and BGM
- Fine-tune camera work
- Add effects and UI
Game Opening Sequence
| Track | Content |
|---|---|
| Activation Track | Title logo display |
| Cinemachine Track | Camera zoom-in |
| Audio Track | BGM playback |
| Animation Track | UI fade-in |
| Signal Track | Transition to gameplay |
Boss Entrance Sequence
| Track | Content |
|---|---|
| Signal Track | Stop player movement |
| Cinemachine Track | Point camera at the boss |
| Animation Track | Boss entrance animation |
| Audio Track | Sound effects and music playback |
| Activation Track | Display boss name |
| Signal Track | Start battle |
Script Control
Timeline Playback Control
using UnityEngine;
using UnityEngine.Playables;
public class TimelineController : MonoBehaviour
{
PlayableDirector director;
void Start()
{
director = GetComponent<PlayableDirector>();
}
public void PlayTimeline()
{
director.Play();
}
public void PauseTimeline()
{
director.Pause();
}
public void StopTimeline()
{
director.Stop();
}
public void JumpToTime(double time)
{
director.time = time;
director.Evaluate(); // Takes effect immediately even while paused
}
public void SetStartTime(double time)
{
director.initialTime = time; // Set the playback start position
}
// Scrubbing: for linking with a slider
public void OnSliderChanged(float normalizedTime)
{
director.time = normalizedTime * director.duration;
director.Evaluate(); // Can also be used for preview
}
void OnEnable()
{
director.played += OnTimelinePlayed;
director.paused += OnTimelinePaused;
director.stopped += OnTimelineFinished;
}
void OnDisable()
{
director.played -= OnTimelinePlayed;
director.paused -= OnTimelinePaused;
director.stopped -= OnTimelineFinished;
}
void OnTimelinePlayed(PlayableDirector pd)
{
Debug.Log("Timeline started!");
}
void OnTimelinePaused(PlayableDirector pd)
{
Debug.Log("Timeline paused!");
}
void OnTimelineFinished(PlayableDirector pd)
{
Debug.Log("Timeline finished!");
}
}
Using Signal Receivers
- Create a Signal Asset (right-click in Project > Create > Signal)
- Add a Signal Track and set the GameObject with a Signal Receiver in the bind field on the left side of the Timeline window
- Place a Signal Emitter on the Signal Track
- Add a Signal Receiver component to the GameObject
- Register methods for each Signal
using UnityEngine;
public class CutsceneEventHandler : MonoBehaviour
{
// Methods called from the Signal Receiver
public void OnBossAppear()
{
Debug.Log("The boss has appeared!");
// Stop player movement, display UI, etc.
}
public void OnBattleStart()
{
Debug.Log("Battle start!");
// Switch game state to combat mode
}
}
Signal Receiver Setup Steps:
- Open the Signal Receiver component
- Click Add Reaction
- Select the Signal Asset to use
- Specify the target GameObject and method
Changing Bindings at Runtime
A common pattern in practice is changing track bindings at runtime.
// Example: Swapping in a different character
foreach (var output in director.playableAsset.outputs)
{
if (output.streamName == "PlayerAnimation")
{
director.SetGenericBinding(output.sourceObject, newCharacter);
}
}
Next steps: To create custom tracks, implement by inheriting from three classes:
TrackAsset(the track itself),PlayableAsset(clip data), andPlayableBehaviour(runtime behavior).
Common Issues and Solutions
Issue 1: Timeline Won't Play
- Check if Play On Awake is enabled on the Playable Director
- Verify the Timeline asset is correctly assigned
- Confirm the objects bound to tracks still exist
Issue 2: Animation Not Applying
- Verify the Animator component is correctly bound to the Animation Track
- Check for conflicts with other Animator layers or state machines
- Make sure Recording mode has been exited
Resolving Animator and Animation Track Conflicts:
- Use Avatar Mask to limit which parts Timeline controls
- Adjust Track weight to control Timeline's influence
- Disable the Animator's state machine during Timeline playback
Issue 3: Objects Revert After Playback
Check the Playable Director's Wrap Mode.
| Wrap Mode | Behavior |
|---|---|
| Hold | Maintains the final frame state |
| Loop | Loops playback |
| None | Reverts to the original state after playback |
Common issue: With the default
None, character positions and properties revert to their pre-playback state. For cutscenes,Holdis typically used.
Issue 3.5: Choosing Update Method
Select the Playable Director's Update Method based on your use case.
| Update Method | Usage |
|---|---|
| Game Time | Normal gameplay (affected by Time.timeScale) |
| Unscaled Game Time | Pause menu UI, etc. (not affected by Time.timeScale) |
| DSP Clock | When audio synchronization is critical |
| Manual | When controlling entirely from script |
Issue 4: Camera Not Switching
- Verify Cinemachine Brain is attached to the main camera
- Check that Virtual Camera priorities are set correctly
- Confirm a Cinemachine Brain is bound to the Cinemachine Track
Issue 5: Signals Not Firing
- Verify the Signal Receiver is attached to the correct GameObject
- Check that the Signal Asset is assigned to the Signal Emitter
- Confirm Reactions are registered in the Signal Receiver
Best Practices
Naming Conventions
- Timeline assets:
Timeline_CutsceneName - Tracks: Names that describe the role (e.g.,
Track_PlayerAnimation) - Signal Assets:
Signal_EventName
Organization
- Group related Timeline assets in dedicated folders
- Organize tracks by type
- Use markers to break up long Timelines
Performance
- Remove unnecessary tracks and clips
- Compress high-resolution animations
- Split complex Timelines into smaller pieces
- Use Addressables to load/unload as needed
Summary
Timeline is a powerful tool for creating cutscenes and cinematic sequences.
- Activation Track - Control object visibility
- Animation Track - Manage animations along a timeline
- Audio Track - Place BGM and sound effects
- Cinemachine Track - Achieve cinematic camera work
- Signal Track - Fire events to integrate with game logic
You can visually create sequences without writing code, and achieve professional-quality camera work through Cinemachine integration.