I’m trying to optimise the performance cost of several Animators (and potentially other components such as Particle System after I figure out this correctly), by updating them X times per second rather than on each frame, depending on the distance towards the player and other factors.
However, using the Update methods of Animator is single-threaded.
So I read that I can use PlayableGraph to batch multiple animators simultaneously using multi-threading.
However, when doing so I notice that the PlayableGraph.Evaluate method’s internal jobs are waited, leading to dead-time in the main thread… is there a wait to prevent that? (In the picture I post the wait is not very large, but with greater workloads, you can see an Idle section forming in the profiler).
Also, this dead time becomes more of a bother when I have to run multiple PlayableGraphs on the same frame (when multiples of X times per second match, for example). If there were a way to queue the evaluation of various PlayableGraphs at the same time (even if their preparations are still in the main thread), their inner C# Job might run in parallel with the execution of other PlayableGraphs, avoiding having to wait in order to continue the evaluation of the PlayableGraph. Being able to queue this to be run in parallel with the next Director.ProcessFrame (which AFAIK has its own PlayableGraph) or something like that would be interesting. Is there some way to do something like that?
I must admit this is my first time using PlayableGraph, so I may be missing something obvious.
I got the idea of using PlayableGraphs from PlayableGraph Evaluate performance/best practices - Unity Forum when looking at how to manually step on Animators with performance.
I know that in the provided thread, it’s said that PlayableGraph.Evaluate is intended to be synchronous, but I wonder if there is some way to run something similar asynchronous for example.
Maybe the only way is by using the Animator.speed and Animator.enable trick provided at the end of that thread? That sounds more like a dirty hack… and only works in Animator, not for other types.
Do you have any updated on this? How can we batch graphs together?
It seems very wastefull to simply wait for a single graph to be completed before evaluating the second one
@DavidGeoffroy maybe you can help?
otherwise - this thread Are Playables updated using multi-threading?
also points to the same answer - Evaluate is single threaded, and proposed solutions is to use custom jobs and simply set time/weights, but I’m not sure that this will update actual positions from those nodes ( playable should apply clip onto root gameObject\apply transform data)
I end up not using PlayableGraphs, instead, I turn off the animators, wait a few frames, turn them up and increase speed variable so it runs what it should in previous frames.
Not the best but I noticed this approach impacts less performance as it’s still inside the Unity main graph…
if anybody is still interested - you simply switch Graph.SetTimeUpdateMode(DirectorUpdateMode.UnscaledGameTime);
and in your update method where you are using actual Evaluate(delta) → _animator.speed = deltaTime / Time.unscaledDeltaTime;
Note: this is not exactly evaluated as you wish, as PlayableDirecotr will schedule and batch all of the graphs somewhere from update to lateUpdate - only once per frame.
there seems to be a way to get AnimatorControllerPlayable from animator after first frame, but I’m not sure if there are any API available to schedule custom playables into it ( to batch them using default global Director)
Not sure if it will improve perfomance - but there seems to be and option to hold animation on the last frame with PlayableDirector.playableGraph by setting playableDirector.extrapolationMode = DirectorWrapMode.Hold