Monday, November 11, 2019

Practical primer to using Unity Timeline / Playables


I recently used Unity Timeline to do cutscenes in a game. Once you figure out how to use it, it works great, but that learning curve of expectations and setup is pretty annoying.

To review: Timeline is a sequencing tool. It's good for higher-level logic where you need to coordinate a bunch of objects at once. For many games, that usually means choreographing cutscenes or sequences. Many different engines and toolsets have sequencer tools and they all generally have the same workflow -- you make tracks and you put actions on those tracks. (see also: UDK Matinee, UE4 Sequencer, Source 1 Faceposer, Witcher 3's cinematic tool)

Note that Timeline is not an animation tool, it's higher level than that. Think of it like a movie director, it coordinates animation, audio, characters, and FX together, but doesn't actually make or process those assets.

In this intro workflow post, I'll start with SETUP TIMELINE, then SETUP DIRECTOR and MAKE CUTSCENES and CONTROL THE DIRECTOR VIA C# SCRIPT, and lastly how to MAKE CUSTOM TIMELINE TRACKS.

for your historical curiosity: Valve's Faceposer choreography tool used for Half-Life 2

1. SETUP TIMELINE

When you first open Timeline in a brand new Unity project, it's not very useful. You need to download some extra stuff.
  • Unity's Timeline. The Timeline package should already be enabled and installed by default, but double-check in the Unity Package Manager UI.
  • Unity's Cinemachine. Cinemachine has built-in Timeline support to easily blend between cameras. This alone is the main reason to use Timeline. Again, make sure it's installed via the Unity Package Manager UI.
  • Unity's DefaultPlayables. This "default" package isn't included by default, you must get it via Asset Store or GitHub. This package has tracks for working with Lights, NavMesh, Text, Video, and most importantly, a TransformTween track. It also has a script generator wizard to help with the painful process of making custom Timeline tracks. MAKE SURE YOU DOWNLOAD AND IMPORT THIS.
(Why aren't the DefaultPlayables included as a default?! WHY? Sigh. Anyway.)

the Playable Director inspector
2. SETUP DIRECTOR

Make a game object and put a "Playable Director" on it (a Timeline is a type of "Playable") and then open up the Timeline tab. Each Director has two main parts: (1) the timeline asset (this is what you're editing in the Timeline window) and (2) the bindings.

Bindings are slots that connect the scene's game objects to the timeline. Think of each binding as a role in a movie, and the film director chooses which actor to perform that role.
  • example: you're making an intro cutscene for a Hero. The Hero sings and dances. If you bind a "Warrior" game object to the Hero track binding, then the Warrior will sing and dance. If you bind a "Maple Tree" game object to the Hero track binding, then the Maple Tree will sing and dance like a hero.
  • Why does Unity use bindings?
    • A Timeline is a project asset. It is a file that lives outside of a scene. It doesn't know about anything inside a scene.
    • Bindings mean that Timelines are reusable across different directors and different scenes. You can make one "intro cutscene", and then reuse that sequence for all your game characters by swapping out different bindings.


3. MAKE CUTSCENE

For each game object and each type of action, you must create a new track.
  • example: you want a Hero to sing and dance. That means you need two tracks: one Animator track to play the Hero's dance animation, and one Audio track to play the Hero's singing voice over. If you want another character to sing and dance at the same time, you could create two more tracks.
Here are the most important track types for typical game cutscenes:
  • Control Track. These tracks can activate / deactivate game objects and instantiate game objects, and they can also control other Directors or time-based Playables.
    • example: activate or hide scenery, toggle props, spawn characters, manage complexity by breaking a big long Timeline into several smaller Timelines
  • Transform Tween track. This track lets you smoothly move or rotate things. This is from the DefaultPlayables package linked above, so make sure you downloaded it.
    • example: make character move or turn, animate a transform without using an animator component
  • Cinemachine Track. Lets you toggle between different Cinemachine cameras. You could technically use a Control Track to do that too, but this track type also lets you blend between the cameras.
    • example: activate a long shot camera that smoothly zooms into a close-up shot
  • Animator Track. Can override the current animation clip on the animator, even if the animator controller doesn't have that clip in its state machine. This is essential for any type of 3D humanoid game because it means you don't have to clutter your controller with all these weird one-off animator parameters or graphs just for one cutscene. With this, any humanoid rig can use any humanoid clip without any state machine setup!
    • example: make a character perform a dancing animation
  • Audio Track. This track type plays audio.
    If you're using Unity 2019.1 or later, you also have access to Timeline Signal Tracks. Signals are like animation events, but in your Timeline. When the Director plays your Timeline and comes across a Signal, it fires that message to a Signal Receiver, which fire standard Unity Events in response.

    4. CONTROLLING THE DIRECTOR VIA C# SCRIPT

    For the most part, automatically starting the director at the start of a level is pretty easy. You can either use the "Play On Awake" in the director's inspector, or in any script's Start() function just call Director.Play()

    OK but here's actually the most important thing to know -- Director.Pause() doesn't actually "pause" the director. It stops the Director and lets you resume from that point, but it does not actually hold or freeze any of the Timeline actions, nor maintain any Timeline state.

    example: You have text dialogue on screen, but you want the player to press SPACE before continuing the cutscene. If you use Director.Pause(), all animations and Cinemachine cameras will revert and the director will relinquish override control on all game objects, because "pause" means that the director has stopped any processing or playback.

    To truly pause the timeline director, you have to use this hack from the Unity forums to set the director's root logic speed to 0:

    playableDirector.playableGraph.GetRootPlayable(0).SetSpeed(0);

    Then to resume the director playback, set the speed back to 1:

    playableDirector.playableGraph.GetRootPlayable(0).SetSpeed(1);

    5. MAKING CUSTOM TIMELINE TRACKS / PLAYABLES

    If you have any custom dialogue or game system to use in your cutscenes, then the default track types will feel pretty inefficient. As of 2017, Unity has started modularizing and over-engineering everything. That extends to the Timeline / Playables system, which might require you to make up to 5 different C# scripts to implement one custom track type. Unity's DefaultPlayables package has a script template generator to try to ease that pain.

    But first, you need to understand how the Playables and Timeline system works in the code. This 2018 Unity blog post "Extending Timeline: A Practical Guide" is absolutely essential to understand what all those different C# scripts do, so make sure you read it, even if you're just skimming the post to understand the basic idea.
    MORE RESOURCES