Search Unity

Bug Weird animation when mixing animator controller and playable animation clip

Discussion in 'Animation' started by Bogdan_Nikolayev, May 21, 2022.

  1. Bogdan_Nikolayev

    Bogdan_Nikolayev

    Joined:
    Dec 29, 2020
    Posts:
    9
    Hello! =)

    I want to make an advanced animation system for our game that uses Animator as a base and Playables API for additional needs (for combo attacks, some complex interactions, etc.). Basically, I want to use Animator, and at the same time, I want more low-level control.

    When mixing AnimatorControllerPlayable and AnimationClipPlayable with AnimationLayerMixerPlayable, the animation looks crooked:
    WeirdAnimation.gif


    In all three cases, I use the following Avatar Mask:
    upload_2022-5-22_1-10-52.png

    Code, which is used for the second (middle) character:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Animations;
    3. using UnityEngine.Playables;
    4.  
    5. public class SetupPlayables : MonoBehaviour
    6. {
    7.     [SerializeField]
    8.     private Animator _animator;
    9.     [SerializeField]
    10.     private AnimationClip _clip;
    11.     [SerializeField]
    12.     private AvatarMask _mask;
    13.     [SerializeField]
    14.     private bool _applyFootIk = false;
    15.     [SerializeField]
    16.     private bool _applyPlayableIk = false;
    17.     [SerializeField, Range(0, 1)]
    18.     private float weight1 = 1;
    19.     [SerializeField, Range(0, 1)]
    20.     private float weight2 = 1;
    21.  
    22.     private AnimationLayerMixerPlayable _mixerPlayable;
    23.  
    24.     private void Start()
    25.     {
    26.         PlayableGraph playableGraph = PlayableGraph.Create(name + " (Custom)");
    27.         AnimationPlayableOutput playableOutput = AnimationPlayableOutput.Create(playableGraph, "Animation", _animator);
    28.  
    29.         _mixerPlayable = AnimationLayerMixerPlayable.Create(playableGraph, 2);
    30.         _mixerPlayable.SetLayerMaskFromAvatarMask(1, _mask);
    31.         playableOutput.SetSourcePlayable(_mixerPlayable);
    32.  
    33.         AnimatorControllerPlayable controllerPlayable =
    34.             AnimatorControllerPlayable.Create(playableGraph, _animator.runtimeAnimatorController);
    35.         playableGraph.Connect(controllerPlayable, 0, _mixerPlayable, 0);
    36.         _animator.runtimeAnimatorController = null;
    37.  
    38.         AnimationClipPlayable clipPlayable = AnimationClipPlayable.Create(playableGraph, _clip);
    39.         clipPlayable.SetApplyFootIK(_applyFootIk);
    40.         clipPlayable.SetApplyPlayableIK(_applyPlayableIk);
    41.         playableGraph.Connect(clipPlayable, 0, _mixerPlayable, 1);
    42.  
    43.         playableGraph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);
    44.         playableGraph.Play();
    45.     }
    46.  
    47.     private void Update()
    48.     {
    49.         _mixerPlayable.SetInputWeight(0, weight1);
    50.         _mixerPlayable.SetInputWeight(1, weight2);
    51.     }
    52. }
    This is what the PlayableGraph looks like for the second (middle) character:
    upload_2022-5-22_1-28-48.png

    I also prepared a project so that I could get into what was going on and experiment:
    https://github.com/Bodix/Animancer-Layers-Bug

    It all started when I installed Animancer. The main killer feature of this asset for me is HybridAnimancerComponent: it allows to mix the work of RuntimeAnimatorController and animations from the code. It was when working with Animancer that I noticed this bug. I wrote the issue to the developer of the plugin, he said it was a Playables API bug. I decided to double-check and it really turned out to be true.

    If you have any idea why this is happening, I would be VERY grateful.
     
    Last edited: May 21, 2022
    ModLunar likes this.
  2. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Is there any chance you could use Generic animations instead of Humanoid? It might be something weird that the Humanoid system is doing which Generic might not do so it's probably worth trying if you can (i.e. if your animations are actually made for your specific character rig so you don't need the Humanoid retargeting system).
     
  3. Bogdan_Nikolayev

    Bogdan_Nikolayev

    Joined:
    Dec 29, 2020
    Posts:
    9
    Unfortunately, Generic is not my case, because I use characters and animations from different packs and the rigs in them are different. Also, animations are already Humanoid.
     
  4. Bogdan_Nikolayev

    Bogdan_Nikolayev

    Joined:
    Dec 29, 2020
    Posts:
    9
  5. bobadi

    bobadi

    Joined:
    Jan 3, 2019
    Posts:
    674
  6. Bogdan_Nikolayev

    Bogdan_Nikolayev

    Joined:
    Dec 29, 2020
    Posts:
    9
  7. ModLunar

    ModLunar

    Joined:
    Oct 16, 2016
    Posts:
    374
    Just curious, have you tried ensuring that your animator.runtimeAnimatorController is set to null?

    I do this in my own scripts that use animation playables because the blending with my own AnimatorControllerPlayable can give incorrect results if Unity's internal animator.playableGraph is doing its own thing, despite me messing around with AnimationPlayableOutput's sorting orders and such.

    So I prevent Unity from using its own playable graph by setting the Animator's animator controller field to null in the inspector (or also checking through C# code), and then using the animator controller in my own script.
    Not sure if this helps your situation, but figured I'd ask!

    P.S. - I haven't tried using AnimationLayerMixerPlayables before.
    I wish they documented the difference between those and AnimationMixerPlayables better, since those are what I'm used to.
     
  8. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Layer mixers let you assign an AvatarMask to each layer and set them to additive, so the math is a bit more complex than regular mixers.
     
    ModLunar likes this.
  9. ModLunar

    ModLunar

    Joined:
    Oct 16, 2016
    Posts:
    374
    Ahh wow, thanks for your insight! This makes sense