Search Unity

Problem with manual update

Discussion in 'Timeline' started by Alex__, Apr 30, 2019.

  1. Alex__

    Alex__

    Joined:
    Mar 23, 2015
    Posts:
    5
    I'm having some trouble getting the manual update mode working the way I want it to.

    I'm trying to have a timeline that animates the transform of several objects. The objects themselves have an Animator Controller, so they already have an animation running 'locally', as well as being animated 'globally' by the timeline. This works correctly when I set the timeline's update mode to Game Time & play on awake. So far so good.

    Now, for reasons I won't get into, I want to be able to manually drive the speed at which this timeline plays (instead of using global timeScale), so I added a script to the timeline gameobject with the following:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Playables;
    3.  
    4. public class TimelineVelocityController : MonoBehaviour
    5. {
    6.     PlayableDirector timeline;
    7.  
    8.     float velo = 1;
    9.  
    10.     // Start is called before the first frame update
    11.     void Awake()
    12.     {
    13.         timeline = GetComponent<PlayableDirector>();
    14.         timeline.initialTime = 0;
    15.         timeline.time = 0;
    16.     }
    17.  
    18.     // Update is called once per frame
    19.     void Update()
    20.     {
    21.         timeline.time += Time.unscaledDeltaTime * velo;
    22.  
    23.         timeline.DeferredEvaluate();
    24.     }
    25.  
    26.     public void SetVelocity(float v)
    27.     {
    28.         velo = v;
    29.     }
    30. }
    31.  
    Problem #1
    PlayableDirector is set to Manual & PlayOnAwake is off & script is enabled
    The first weird behavior happens when I leave this script enabled and start up the scene. My timeline anim is about 360 frames (6 sec) and for some reason it will always start around frame 150 (2:45 sec).

    No idea why that's happening, but I managed to avoid that bug by leaving this script disabled at first and then enabling it once the scene is loaded & running.
    It even plays the animation on the timeline correctly (moving the object's transform), but

    Problem #2
    PlayableDirector is set to Manual & PlayOnAwake is off & script is disabled at first
    The objects will move on the trajectory defined in the timeline, but are stuck in a resting pose instead of playing their 'local' animation properly, like when Game Time is the updateMode. I'm guessing I somehow need to trigger the evaluation of that animator controller manually as well?

    I tried to look into how this works by checking out the Unity source code, and I found [this](https://github.com/Unity-Technologi...r/ScriptBindings/PlayableDirector.bindings.cs) but I'm a bit stuck and don't know where to look further. Where can I see the code that handles Game Time updating? I figured I could reverse engineer it that way perhaps, but I admit I don't entirely understand the timeline mechanism yet.

    Any ideas/help appreciated, thanks!
     
  2. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    I just report a bug that manual updating could not make audio track play, and also could not trigger 2019.1's new marker feature. It is unrelated to your case but maybe you should also submit a bug report.

    Also try to move the time + evaluate on the playable graph directly instead of asking the playable director to do it? (though, I tried that and it didn't fix my reported bug) That version of Evaluate could add time before evaluation.

    playableDirector.playableGraph.Evaluate(Time.unscaledDeltaTime * velo);


    Anything inside UnityEngine.Playables are closed source, I had trouble figuring out what was happening inside the black box too. (Now UnityEngine.Timeline is open as a package)

    *Also, the playable API actually contains a settable "speed" modifier so that any delta time that goes into them got multiplied. Your premultiplying way works too, but just in case this new way could somehow fix your bug :

    pd.playableGraph.GetRootPlayable(0).SetSpeed(0.1f);


    This make even PlayableDirector's auto update runs slower, because you hack its generated (root) playable to go slower. Though the director has no easy interface to this speed.
     
    Last edited: Apr 30, 2019
  3. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    Problem #1
    - Try start instead of awake, or skip updating the time on the first frame. I'm not sure off hand, but unscaled delta time may not have the 1/30 frame limitation deltatime does between Awake() and the first Update() call.

    Problem #2
    - You may need to call Stop() on the director in OnDisable() to get rid of the graph when the script is disabled.

    @5argon - using manual time won't play Audio or Trigger notifications, because it is effectively scrubbing the timeline, instead of _playing_ it. (Playing it defined as the engine is driving time). Audio and Notifications require continuity of time, and manual doesn't guarantee that.

    You are correct on using the root playable speed to alter the playback speed...that's something we should have exposed, and would like to expose, in the playable director.

    PlayableDirector and Playables are (mostly) implemented in native code, so digging into them isn't easy.
     
    5argon likes this.
  4. Alex__

    Alex__

    Joined:
    Mar 23, 2015
    Posts:
    5
    Interesting, using unscaledDeltaTime was indeed the culprit for the initial timeline skip. Seems like it's a large value on the first frame, so this shouldn't be a problem in the end!

    The second problem remains as long as I try using manual time. I've now solved the problem by using
    pd.playableGraph.GetRootPlayable(0).SetSpeed(0.1f);
    together with leaving it on Game Time, this works! Thanks @5argon & @seant_unity . The other solution made the timeline move forward, but did not actually play any of the animations on the timeline, so that's weird.

    And yes it would indeed be good to expose this speed property in the playable director.