I’d like to be able to scrub through a series of animations that are operating on the same hierarchy of objects. The approach is basically this:
One Director and one Animation Track - animations are stacked back to back.
All items in track are PostExtrapolate = Continue
All Animations are LoopTime = false
All Animator nodes are WriteDefaults = false
The idea is to be ‘always playing’ the Director but setting speed to 0 when i want to pause it. The Director Pause() does not seem to work like I would expect.
The code for moving to a specfic time is something like this:
Director.Stop();
Director.time = time;
Director.timeUpdateMode = DirectorUpdateMode.GameTime;
Director.Evaluate();
SetSpeed(IsPaused ? 0 : 1);
Director.Play();
Debug.Log($"<color=cyan> Simulation: Time moved to {time}</color>");
SetSliderMax((float)CurrentScenario.Director.duration);
SetSliderValueSilently(time);
However it’s not accurate. If I slowly scrub through then it’s relatively close to what it should be, but when I jump across a lot of time it’s entirely skipping animations and only “evaluating” the animation at that point. In practice, it does not appear that it is possible to actually scrub through a timeline at all.
If this is supposed to be possible, how is it done? I simply need it to evaluate all of the animation keys from 0 up to newTime so that it can be guaranteed to capture the actual content of the timeline and not ignore huge chunks of it when time is moved. This seems like a pretty fundamental feature for a tool like this so I’m assuming that I’m just missing something.
I could circumvent this by making everything one animation and scrub through that just perfectly, but at that point Timeline would be useless and I should just be using a much simpler and accessible approach.
You are correct in that timeline is only evaluating at the current time. It is not simulating to the next time, thus clips can be skipped. I am making the assumption that this is an issue because your animation clips do not all animate the same values.
It is possible to achieve what you are trying to do using layers (i.e. override tracks), by having one clip per track, and setting the post-extrapolation to ‘hold’ of each clip, and no pre-extrapolation. Clips that start later should be on a lower layer (timeline blends top-down, so the ‘lowest’ layer always has highest priority).
Effectively this would be creating a blend of all clips on the track up to the given point. The ‘hold’ use the values at the end times of the clips. Putting all clips on one track - by contrast - only samples from the existing clip. The post-extrapolation only applies up until the next clip on the same track.
Great! This approach works exactly as expected and scrubbing through the sequence is completely accurate. It’s a little less ideal in terms of layout but the functionality is exactly what we need.
Thanks for taking the time to write a thorough response!
I have another issue with scrubbing - now I’m looking into adding Signals to tie in more scripted behaviors and noticing that the Signals are not being fired during the scrubbing. I’d like to use a Signal to do a method call which does any number of things, and at the beginning of the sequence have a reset Signal which resets anything necessary.
What I’m seeing is the Signals not being executed when the code in the OP is run which sets the scrub-to time. I’m putting the signals directly on the animation override tracks. Are Signals not a good solution for this?
Yes - Signals are only triggered when the timeline is played, not when it is scrubbed.
Using signals for method calls is fine, but if you are looking to manage the state of components over time and see the results in preview, then custom tracks and clips are generally a better option.