Extending the animator playableGraph

Animator stateMachines are cool, but don’t provide solution for everything A simple thing would be to provide an animationClip from the outside somehow (for example, when the clip is bound to some object in the scene, not the character itself). My idea was this - create a playableGraph with the AnimatorControllerPlayable blend it using an animationMixer with something else, output that to the original controller. It does work, however there seems to be a huge performance penalty. The controller’s statemachine is quite complex, contains many blends and layers, but there is no performance problem, until I add the extra animation mixer.
Here’s the code I am using now

            animator.playableGraph.Destroy();
            m_playableGraph = PlayableGraph.Create();
            var externalOutput = AnimationPlayableOutput.Create(m_playableGraph, "ExternalAnimator", animator);
            m_animationMixer = AnimationLayerMixerPlayable.Create(m_playableGraph, 3);
            externalOutput.SetSourcePlayable(m_animationMixer);

            var humanAnimatorPlayable = AnimatorControllerPlayable.Create(m_playableGraph, animator.runtimeAnimatorController);
            m_animationMixer.ConnectInput((int)MixerInput.HumanAnimator, humanAnimatorPlayable, 0, 1);
            // Plays the Graph.
            m_playableGraph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);

            activityAnimationLayer = new AnimationControllerLayer((int)MixerInput.ActivityAnimator, m_animationMixer);
            speechAnimationLayer = new AnimationClipLayer((int)MixerInput.SpeechClip, m_animationMixer);
            m_animationMixer.SetLayerAdditive((int)MixerInput.SpeechClip, true);
            m_playableGraph.Play();

The Animator component culling seems to not have any effect on the performance after the custom graph is injected (from looking at the profiler before and after, and moving the camera).
Here are screenshots of the profiler, the highlighted part in the graph shows the difference when the custom graph is applied and not
4684331--441554--profiler1.jpg 4684331--441557--profiler2.jpg
I’ve also tried a version where I’d take the playableGraph from the controller, and try to swap the output playable - but that seemed to have no effect at all.
Am I missing something? Is there any other way how I could achieve blending a custom animation in?

My Animancer plugin gets slightly better performance by disconnecting weightless playables from the graph, so you might get a good result by doing the same (particularly with AnimatorControllerPlayables since they’re pretty complex).

Sounds interesting, however I am not sure how it would make a difference, in case this is a general playables problem. Can you explain to me, why did I see this drastic change in performance, even if I only added 1 animation layer mixer and 2 simplest layers to it? The animator’s controller has 9 layers and each of them quite large.Why should implementing the whole controller in a plugin using playables should perform better then?

I didn’t mean that using Animancer in that manner would improve performance, just that using playables as you are now and disconnecting them while they aren’t active might help.

I have no idea why you would see such a drastic difference, but 9 layers sounds like you are quite likely doing something very ineffective in the first place. Obviously I don’t know exactly what you’re using those layers for, but you could probably get much better performance by replacing the entire Animator Controller. Either with Animancer or by managing the playables yourself, but the point is that the individual playables only need to be created the first time they are actually used and you don’t need to brute force everything into a single giant Animator Controller.

OK I will try to explain again - using the controller alone (with all the layers) performs very well. The problem only happens (and that’s the difference highlighted in the profiler) after i take the animatorControllerPlayable and mix it with another layer (Containing one animation). I’d try to switch it on and off only for when I need the extra layer (which still doesn’t explain the performance hit) but there’s a problem of the animatorController losing it’s exact state for some reason. And my different experiments of how I could disable the extra layer (and the layer mixer) temporarily usually end up in unity crashing