Search Unity

Extending the animator playableGraph

Discussion in 'Animation' started by Pangamini, Jun 25, 2019.

  1. Pangamini

    Pangamini

    Joined:
    Aug 8, 2012
    Posts:
    54
    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
    Code (CSharp):
    1.  
    2.             animator.playableGraph.Destroy();
    3.             m_playableGraph = PlayableGraph.Create();
    4.             var externalOutput = AnimationPlayableOutput.Create(m_playableGraph, "ExternalAnimator", animator);
    5.             m_animationMixer = AnimationLayerMixerPlayable.Create(m_playableGraph, 3);
    6.             externalOutput.SetSourcePlayable(m_animationMixer);
    7.  
    8.             var humanAnimatorPlayable = AnimatorControllerPlayable.Create(m_playableGraph, animator.runtimeAnimatorController);
    9.             m_animationMixer.ConnectInput((int)MixerInput.HumanAnimator, humanAnimatorPlayable, 0, 1);
    10.             // Plays the Graph.
    11.             m_playableGraph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);
    12.  
    13.             activityAnimationLayer = new AnimationControllerLayer((int)MixerInput.ActivityAnimator, m_animationMixer);
    14.             speechAnimationLayer = new AnimationClipLayer((int)MixerInput.SpeechClip, m_animationMixer);
    15.             m_animationMixer.SetLayerAdditive((int)MixerInput.SpeechClip, true);
    16.             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
    profiler1.jpg 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?
     
  2. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    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).
     
  3. Pangamini

    Pangamini

    Joined:
    Aug 8, 2012
    Posts:
    54
    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?
     
  4. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    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.
     
  5. Pangamini

    Pangamini

    Joined:
    Aug 8, 2012
    Posts:
    54
    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