Search Unity

"Pausing" Timeline Playback

Discussion in 'Timeline' started by aki_null, Jun 1, 2017.

  1. aki_null

    aki_null

    Joined:
    Apr 12, 2017
    Posts:
    1
    Hi,

    I'm new to Unity, and I'm currently examining the Timeline and Cinemachine on b7.

    I've come across a situation where I want to "pause" the Timeline at the end of a custom PlayableBehaviour I'm making.
    The use case of this would be that the user is asked to interact with the game in middle of a Timeline through GUI (which I do not have a control over how long this can take), while letting Cinemachine still control the camera.

    I'm having a problem implementing such PlayableBehaviour, because there are several issues:
    • Invoking Pause API on PlayableDirector causes Cinemachine's behaviour to release camera override, which resets the camera. The same can be said about animation track.
    • PlayableDirector has timeUpdateMode field which appears to let me pick Manual update mode, but I cannot find any information on "PlayerController.Tick" that is mentioned in the documentation.
    • Overwriting PlayableDirector's time field every frame lets me pause the PlayableDirector in a way I want (i.e. does not cause Cinemachine to release camera override), but it is not possible to lock this time before the Timeline execution goes past the end of custom behaviour. This means that game has already rendered one step ahead by the time OnBehaviourPause is invoked on custom behaviour, which is too late for me to revert the PlayableDirector's time field to the end of custom behaviour.
    After doing all of the above, I've really started thinking that maybe I'm missing some critical knowledge on how Timeline works, or is Timeline not supposed to be used for things like this?
     
    Chambers88 likes this.
  2. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    Timeline offers a ControlTrack, which can be used to control another timeline. You could use a master timeline to pause a slave timeline when the user interacts with the game. It could avoid issues with Cinemachine.
     
    wabugi likes this.
  3. akihiro-noguchi

    akihiro-noguchi

    Joined:
    Dec 9, 2015
    Posts:
    3
    Thank you!
    That clears things up for me.
     
    julienb likes this.
  4. adamgryu

    adamgryu

    Joined:
    Mar 1, 2014
    Posts:
    188
    Hi, could you elaborate a little more on this subject? I've been trying to find some documentation on the control track, but I haven't been able to find anything that explains it well yet.

    In particular, I'm working on an RPG and I'm trying to decide if Timeline would be a good fit for scripting my cutscenes. The dialog is delivered through text boxes though, and I would like to pause the timeline while the user advances a text box.

    I was also thinking I might like to write Playable Behaviours that walk a character to a certain positions using their game movement logic and then wait for the character to finish walking. This way I could utilize any walking animations / physics without having to explicitly build them into the timeline.
     
    B_HITMAN and Chambers88 like this.
  5. Lancearl

    Lancearl

    Joined:
    Jun 22, 2014
    Posts:
    2
    Echoing adamgryu here since there's been no response, has anyone been able to figure this out? I'd love to be able to use cinemachine for cutscenes in my game, and have the progress of the timeline paused while the player is clicking through dialogue. I've tried to follow julienb's suggestion by setting up ControlTracks on a master timeline asset that switches a director with only the dialogue track on, then pauses it at the end if they haven't finished clicking through it. But even when putting the camera control into another dedicated control track (so one control track for the dialogue, one for the camera movement both being controlled by the master director) invoking Pause API on PlayableDirector (master director) still causes Cinemachine's behaviour to release camera override, which resets the camera position and looks terrible (the camera suddenly snaps back to a default position).

    So maybe a way forward is for julienb (or someone else) to link to a resource or post a more detailed example of the approach he's talking about? Or if anyone has an example of getting timeline to work alongside dialogue that needs to be clicked through then that is what I'm really after.

    Also just wondering as an aside, is the camera re-positioning itself like that a bug or a feature? I expected it to retain its current position when the timeline is paused, but unfortunately that's not the case!

    Any help or advice would be hugely appreciated!
     
    B_HITMAN likes this.
  6. dadude123

    dadude123

    Joined:
    Feb 26, 2014
    Posts:
    789

    For a dialog that has pauses (where the player initiates each step) you would likely need to what you're already doing (pausing the director)

    The snapping back It is most likely intended, your camera gets "forced on" when the timeline reaches it. Even disabled cameras can be used like that (which is a great feature actually in many other situations).

    What you have to do is enable the cameras (if they are not already enabled) and set their priority high enough so they stay on even when the director gets paused.

    When the dialog/cutscene completes you turn them off again / set their priority back.
     
    B_HITMAN and Lancearl like this.
  7. Lancearl

    Lancearl

    Joined:
    Jun 22, 2014
    Posts:
    2
    Awesome, simple solution - it completely solved the problem and helped me understand timeline/cinemachine a lot better! Honestly, could not have come at a better time so thanks so much :D!
     
    B_HITMAN and dadude123 like this.
  8. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
    Here is a more elegant solution, from @seant_unity. It neatly eliminates the need to enable/disable any CM cameras:

    There's a workaround you can use instead of PlayableDirector.Pause(). The Pause() methods suspends the timeline at the current time, but stops evaluating it. That's why it 'releases' the cinemachine cameras. Instead you can keep the timeline running, but prevent time from advancing by using playableDirector.playableGraph.GetRootPlayable(0).SetSpeed(0).

    This will pause the timeline in the more traditional sense of the word. You can resume by resetting the speed back to 1. This is something on our backlog of issues to address with a better solution.
     
  9. panta

    panta

    Joined:
    Aug 10, 2012
    Posts:
    71
    @Gregoryl thanks for your reply - I'm running into a similar situation where I have a script (similar to the SimpleAnimation Playable from Unity) that is controlling my character's animation.

    We want to implement a hit-pause/bullet time in our game, and I was trying to do the
    Code (CSharp):
    1. playableGraph.GetRootPlayable(0).SetSpeed(0)
    workaround you suggested to slow down the whole animator graph (we have a fairly large graph of connected AnimationClipPlayables and AnimatorControllerPlayables). However, there was no effect on the animation. I'm using 2017.2.0p4 for this project.

    I also tried looping through all of the Playables in the graph and performing SetSpeed on them, as well as trying to set the time update mode manually via
    Code (CSharp):
    1. graph.SetTimeUpdateMode(DirectorUpdateMode.Manual);
    , but I wasn't sure how to use that function (the docs mention that you need to call
    Code (CSharp):
    1. PlayerController.Tick
    , but I can't find any examples of how to do that). I did find this example on Unity Answers - can you confirm if this is what the docs mean by "PlayerController.Tick"?

    Thank you for any reply or help you can provide! I'm really liking the new Playables system, but there isn't much in the way of documentation yet :(
     
    Vander-Does likes this.
  10. mradfo21

    mradfo21

    Joined:
    May 16, 2013
    Posts:
    194
    yeah what is this mysterious tick function that the documentation says to call but doesn't reference?
     
  11. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    @mradfo21 That method no longer exists, and should be removed from the documentation. I've opened a bug to get that fixed.

    @panta : Yes, you can use the PlayableGraph.Evaluate(deltaTime) to advance at the speed you want, but it can wreak havok with audio (which always uses the DSP clock). Setting speed on all playables may cause issues outside 0 or 1 because the speed is inherited as the graph is traversed, and it's possible that some playables ignore it or have their time updated from the timeline playable. Gregory's suggestion will write the timeline playable speed, and that will cascade to all the clips timeline controls.
     
  12. plmx

    plmx

    Joined:
    Sep 10, 2015
    Posts:
    308
    @Gregoryl @seant_unity Thanks for this information, I am trying to "pause" the timeline in this sense also. While the above code works visually, there seems to be a problem with this method and using AudioTracks in the timeline: For the paused time, the audio will be cut short at the end.

    I use playableDirector.playableGraph.GetRootPlayable(0).SetSpeed(0) in a Start() method - thus the timeline starts up paused - and later on use SetSpeed(1) to actually start it. It runs correctly, includign the (single) audio track which starts at the beginning as expected, but the audio cuts out before finish, and it seems to me that it cuts out prematurely for exactly the amount of time the timeline was "paused".

    Update: Setting playableDirector.time=0 directly before SetSpeed(1) solves the issue.

    It would be great if there would be a general Play()/Pause() method pair which takes care of this, including taking care of the audio issue. Thanks!

    Philip
     
    Last edited: Jan 29, 2019
  13. Dazi707

    Dazi707

    Joined:
    Jul 17, 2020
    Posts:
    1
    When I use PlayableDirector.Pause(), an activated animation track will resume the linetime automatically. After I implement playableDirector.playableGraph.GetRootPlayable(0).SetSpeed(0), the animation track can be properly paused. Thank U!
     
  14. Calvares

    Calvares

    Joined:
    Jul 11, 2018
    Posts:
    17
    Lol, I was struggling with the same problem. I have multiple audio clips on Audio Track, and when I was pausing the game during on of the clips, that clip particularly won't continue after unpausing. Doing "playableDirector.time = playableDirector.time" before SetSpeed(1) solves that thing, thanks.

    Just, what the hell.
     
    DeadCastles likes this.
  15. akashjohny02

    akashjohny02

    Joined:
    Mar 30, 2020
    Posts:
    6
    Great post, Really appreciate the help guys. The below code solved my issue.


    "private PlayableDirector director;
    private void Awake()
    {
    director = GetComponent<PlayableDirector>();
    }
    public void StartTimeline()
    {
    director.time = director.time;
    director.playableGraph.GetRootPlayable(0).SetSpeed(1);
    }
    public void StopTimeline()
    {
    director.playableGraph.GetRootPlayable(0).SetSpeed(0);
    }"
     
  16. duartejuca

    duartejuca

    Joined:
    Aug 23, 2018
    Posts:
    13
  17. VResearch

    VResearch

    Joined:
    Jan 6, 2021
    Posts:
    21
    It's now 2022, and I assume this is still in backlog, since I've just noticed this "not very traditional" implementation of the pause/resume function in Unity 2021 :)