Custom Timeline Asset: Pause and wait for Player Input (Part 3/3)

06/17/23


Part 2 went over how to make a custom clip that pauses playback. Part 3 will show how to add more functionality to our clip to allow the timeline to resume play when the player presses spacebar. Then we will modify it so that instead of spacebar, you can assign any key you like.


Part 2

3.1 Adding a player prompt

To let the player know they should press a button to proceed when the timeline pauses, we need to enable some kind of on screen message.


Create a new Canvas, and add a prompt image to it.

This guide won't go over how to do those things in-depth but there are many great guides for this online.

My end result looks like this:



In the timeline, add a new Activation Track:

Drag and drop the GameObject with your prompt image into the track's GameObject field.


Right-click on the track and add a new Activation Clip. Make it nice and short and line up the start of the clip with your pause clip:


This will activate your prompt image when the timeline freezes. Here's how it looks:


3.2 Resuming Play when Space is Pressed


Just like pausing, resuming is a behaviour -- so let's add it to the PauseBehaviour script.


Now, we have a bit of a conundrum here. The moment the timeline pauses, it is going to freeze and be unable to do anything else until it is resumed. In other words, our frozen timeline can't resume itself, the same way someone frozen in a block of ice can't thaw themself out -- they need an outsider who isn't frozen to help them.


So to create this "outside helper", I'll have my timeline do one last thing right before it goes fully frozen: fire off a coroutine. This coroutine will act as a separate "helper" process that keeps running and listens for input -- it will "thaw out" the timeline when it hears that input.


Here I've added the coroutine "helper" WaitForInput. I've also added a couple new 'isPaused' and 'alreadyPlayed' boolean flags to help handle the logic.


Now this is all great except -- I can't run StartCoroutine! 

This is because Coroutines can only be run by MonoBehaviours and scripts that derive from them. 

My script derives from PlayableBehaviour, which, sadly, is not a monobehaviour. : (


To get around this, I'm going to make a monobehaviour instance in my scene and use that instead. 

Create a new empty GameObject called CoroutineRunner.

Copy and paste this code into the script. (It is a nice boilerplate instance, nothing fancy.)

Add this CoroutineRunner script component to your CoroutineRunner game object.

In the PauseBehaviour script, now i can easily get and use that instance to start a coroutine:

There is still a bug where the timeline doesn't start moving after i hit spacebar -- after some trial and error, i found this required me force-moving the playable's time slightly forward in time to "wake it up" and get it moving again.



Now, when the game runs, it works like this:






3.3 Dropdown to pick which key resumes playback

This clip is pretty cool, but it has “Space” hardcoded in as the required key to press, which is not ideal.

 

What would be really nice is if each pause clip had its own dropdown in Unity where we could pick which key the player needs to press, to continue.


To accomplish this, we’ll need to make some changes to the PauseClip script, and the PauseBehaviour script.

First go to PauseClip and change it to match the parts marked in red:


Notice that if you go back into unity, and select your pause clip, you will now be able to see Key as a dropdown item in the Inspector!


This dropdown doesn’t do anything yet though.

Next go into the PauseBehaviour script and change it to match the parts marked in red:


This tells our PauseBehaviour to use the key specified by that variable, instead of a hardcoded space key.

The last thing we need to do is find a way to pass the info of “which key was picked in the dropdown” from the PauseClip to the PauseBehaviour. To do this:

This code passes in the dropdown value of the key to the PauseBehaviour, at the moment when the PauseBehaviour instance is created at runtime.


Now you can add multiple pauses to your cutscene and have them each respond to a different key!



ENDING NOTES

All final code is here on Github: LINK


Some notes I found while researching this:


Good luck and happy cutscene-ing!