Search Unity

Animation Overrides in code not working properly?

Discussion in 'Animation' started by Duffking, May 24, 2018.

  1. Duffking

    Duffking

    Joined:
    Oct 3, 2014
    Posts:
    24
    I've got a character whose body is controlled via timeline, and I'm leaving their head to be animated via regular animator, as the animations on the head are all lip-synced to what the character is saying. As such, I have animation clips generated for each line of dialogue.

    I'd rather not create a billion timelines, one for each line of dialogue, or a billion animator states, one for each line of dialogue, so on the head I have a basic animator set up with a single, 1 frame animation clip on the head in a single base layer which makes the character pull a neutral expression. I'm then using this (abridged) code to attempt to switch the clip in the state through the creation of an animator override controller depending on whether they are speaking or listening:

    Code (CSharp):
    1.  
    2. private Animator _animatorComponent;
    3. private AnimatorOverrideController _animatorOverride;
    4.  
    5.  
    6.     public override void Ready()
    7.     {
    8.         _animatorComponent = GetAnimator();
    9.         _animatorOverride = new AnimatorOverrideController(_animatorComponent.runtimeAnimatorController);
    10.         _animatorComponent.runtimeAnimatorController = _animatorOverride;
    11.     }
    12.  
    13.     public Animator getAnimator()
    14.     {
    15.         // Just some stuff that gets the animator
    16.     }
    17.  
    18.     public void setFacialAnimation()
    19.     {
    20.         _animatorOverride["FaceAnim"] = NewAnimationClip;
    21.     }
    22.  
    23.     public void resetFacialAnimation()
    24.     {
    25.         _animatorOverride["FaceAnim"] = DefaultClip;
    26.     }
    27.  
    I'm fairly certain that this is working to an extent - the controller in the head animator is definitely being switched to a new one created by the script, but in the editor nothing really appears to actually change. If I look in the animator, the clip in the state is still the NeutralFace clip.

    But, if I breakpoint the code after setting the override and look in the override controller object, I can see that the clip in that state has changed, so for whatever reason, it's just not updating in the editor.

    Despite this, the face isn't actually animating at all - it's as if the clip is not playing. Interestingly, if I set the import settings of the clip to loop, it will start playing (though out of sync). Additionally, if I make seemingly any change to the animator while the character is speaking (setting the speed of the clip to be 1.00001, adding a new layer, etc), the clip will suddenly start playing, until the next line starts.

    So seemingly, the correct clip is being put in the override, but it doesn't seem to actually play unless I loop the clip in the import settings (which I don't want), or I make a manual change to the animator while the game is playing.

    Does anyone know why this is?
     
  2. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    For some unfathomable reason, they decided that overrides would be based on clip names rather than state names, so if "NeutralFace" is the name of your dummy AnimationClip then that's the string you need to override. I'm not sure if this is actually your issue or not since neither of the circumstances where it does work sound like they should be applicable if you're giving the wrong name.

    It might also be worth taking a look at my Animancer plugin which does away with AnimatorControllers entirely and lets you simply pass in whatever AnimationClip you want when you call Play.
     
    sjakur likes this.
  3. sjakur

    sjakur

    Joined:
    Apr 24, 2016
    Posts:
    4
    Just wanted to say thank you, I assumed that we suppose to do the overriding based on the state's name. I mean that's the logical thing to do, well at least in my mind.