I’m using the following script to step my Timeline in alignment with physics (so that physics can nicely be affected by animations).
using UnityEngine;
using UnityEngine.Playables;
/// <summary>
/// Simply steps a <see cref="PlayableDirector"/> once every FixedUpdate, rather than on the display frame, which is the default.
/// </summary>
[RequireComponent(typeof(PlayableDirector))]
public class FixedUpdatePlayableDirector : MonoBehaviour
{
private void FixedUpdate()
{
PlayableDirector playableDirector = GetComponent<PlayableDirector>();
if (playableDirector != null)
{
playableDirector.playableGraph.Evaluate(Time.fixedDeltaTime);
}
}
}
This does update the animation, but doesn’t send any signals. The Unity blog post also mentions that Signals/Notifys aren’t set when using Evaluate.
Is there a way to manually send signals to workaround this? Or can an API be added that properly sends notifies when calling Evaluate (ie. a boolean in that function?).
Unfortunately there is no way to do this right now. The notification playable that sends the trigger explicitly ignores Evaluate calls.
It sounds like the solution you want is really a FixedUpdate timeline update.
1 Like
Thanks for the information. Yes, a FixedUpdate option would be fantastic, although the better solution is just a specialized method for manually stepping an PlayableGraph that doesn’t conflict with scrubbing. Seems like notifications are disabled to avoid scrubbing notifies (makes sense), but scrubbing should just use a different flag.
I’ve worked around all of this by just disabling the check in the TimeNotificationBehaviour (after pulling timeline into a custom package):
...
/// <summary>
/// This method is called during the PrepareFrame phase of the PlayableGraph.
/// </summary>
/// <remarks>
/// Called once before processing starts.
/// </remarks>
/// <param name="playable">The reference to the playable associated with this PlayableBehaviour.</param>
/// <param name="info">Playable context information such as weight, evaluationType, and so on.</param>
public override void PrepareFrame(Playable playable, FrameData info)
{
// Never trigger on scrub
// ASG: Only check for scrubbing when in the editor. This is technically incorrect, as you can scrub at playtime,
// but this is a workaround to allow a manually stepped timeline in FixedUpdate to send notifications of markers.
if (!Application.isPlaying && info.evaluationType == FrameData.EvaluationType.Evaluate)
{
return;
}
SyncDurationWithExternalSource(playable);
...
It obviously going to break if I try scrubbing in PlayMode, but seems to work fine for my purposes? I now manually step the timeline in FixedUpdate and notifies are sent as expected.
Spot on. As long as you aren’t using AudioTracks that should work just fine.
Manually evaluating the graph is considered a ‘scrub’, but having a way to advance the graph as a ‘playback’ is definitely needed.
What are the complexities / consequences if we end up using AudioTracks? We haven’t yet, but just curious.
Is the audio system a bit more complex because it needs to inject audio events into the audio system (which has its own time, etc)?
Audio doesn’t play back on an Evaluate call. The audio system is more complicated because it is always scheduled against the DSP clock, and an evaluate call doesn’t guarantee the timeline is actually playing. Evaluate is great for discrete systems like Animation, but complex for continuous systems.
A timeline playing on the game clock can have longer audio clips ‘drift’ for that reason, and we included the DSP clock on playable director in the cases where audio tracks need to sync perfectly (i.e. make everything else match the audio).
Gotcha, makes sense. Thanks for the info and help!
(You folks should consider moving Timeline open source like InputSystem and SRP! :))
Any plans to change/fix this? I’d rather not have to modify the Timeline source code and my custom editor relies on signals being sent when scrubbing (in both Edit and Play modes).
There is no current plan in place to change that right now - which of course, can change with user feedback.
1 Like
Is this the proper channel to submit that feedback, or is there an issue tracker or something?
The forums are the proper channel now.
1 Like
we are running our entire game on manual playable directors.
how come there is no way to manuallly emit signals?
We didn’t implement signal emission on an Evaluate call because it is difficult to determine user intent - Signals require a delta time, and Evaluate is used in many different ways. That makes even the last evaluate time vs current evaluate time not dependable as a deltaTime.
In hindsight, we probably should have added someway to advance the playable director manually with a given delta time. (Similar to playableGraph.Evaluate()).
1 Like
Yeah, something like PlayableDirector.Advance() would be fantastic.
When you say ‘in hindsight’, does that mean the Timeline is somewhat finished, in terms of folks who are working on it? If there’s no plans to push further on this kind of thing, it’d be fantastic if the Timeline package were open source. Then it’d be easy for someone to start a PR that kicked off this change.
You can setup Github to disable most of the other features (like Issues, etc) if you’re worried about maintenance burden.
‘In hindsight’, I just meant when we implemented signals - Timeline itself is still in active development.
As for open source, the problem (in this case) is the playable director/playableGraph is native code. The advance feature would be a Unity addition, not a timeline package addition.
However, your point is noted It would be an advantage for the timeline package to be open source, or at least available on a public github.
Ah, that’s a bummer, but makes sense. I guess you’ll just have to jobify it.
Yeah, even just a public mirror would be great. It’d make it much easier to keep our changes rebased on top of the latest.
Yeah, something like PlayableDirector.Advance() would be fantastic.
Agreed.
A PlayableDirector.timeScale value would also be very useful in this context.
Any updates on this? It’s got me completely stopped, as I need both Signals and Audio Tracks.
Is it possible to search the graph for the Signals and Audio tracks, and manage them manually?
Audio tracks currently support Time.timeScale.
Do you need your Timeline to play on a different time scale than the rest of your game?
+1 for adding an Advance() call that fires notifications
I like to run my own update loop for similar reasons as OP.
+! for advance(), I want to play a director using network time which requires me to manually update the director but also want to raise event
1 Like