Animation Track and Animator Override Controllers

Hi! I’m creating an turn based RPG where every action (attack, generic actions, death) is based on a timeline animation, the problem is that when attacking, I want the defender to be basically any character, since every character will share an ‘hurt’ state, I’ve created a generic animator with every state and each character has it own Animator Override Controller.

The problem is that the Animation Track works only by setting the animation clip directly and it ignores completely the overrides on it controller. Is there a way to workaround this problem?

Sounds to me like you need to actually let the Animator play the animation, instead of using the timeline to override the animator.

I’m not sure if its possible to make the timeline use the animator instead (which is what you want, right? so the animator plays the right animation).

Other than that I guess you would have to use a script to change the animation clip that should be played.
Once you know what character the timeline should be applied to, you can get the characters animator, then from there the override controller.

But maybe there is a cleaner way possible that I’m not aware of, or maybe the timeline guys are working on something to make this more straightforward (which would be nice!) But then again consider having a animation that is pretty short and then overriding it with an animation that takes 5x longer… would the timeline have to scale the animation down (so it plays faster)?

Oh, I guess I never realized that the problem is that the timeline overrides the animator, instead of working with it. So that’s the “problem”.

I guess that I could create an custom track that works with the animator, playing the animation when the clip start, the problem is that it would damage our animator’s workflow, not letting them seamlessly work with the timeline in the editor, previewing the animations…

I really hope that the unity team is working on a more straightforward approach to everything related to the timeline, as it is, in my opinion, the strongest feature of unity.

And for that case with animations with different length, I don’t think the timeline should scale at all, if the overriding animation is shorter than the original, it should just repeat itself (if Loop Time is true), or, if is longer, just cut it.

1 Like

Just an update on the matter
I’ve created an AnimatorTrack and it working greatly, there is definitely room for improvements and I’m not totally satisfied with it but I wanted to share with you guys:

public class AnimatorMixerBehaviour : PlayableBehaviour
{
    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    {
        Animator animator = playerData as Animator;

        if (!animator)
            return;

        int inputCount = playable.GetInputCount ();

        string strongestName = "";
        float strongestInputWeight = 0;
        float strongestClipStart = 0;
        float time = (float)playable.GetGraph().GetRootPlayable(0).GetTime();
       

        for (int i = 0; i < inputCount; i++)
        {
            float inputWeight = playable.GetInputWeight(i);
            ScriptPlayable<AnimatorBehaviour> inputPlayable = (ScriptPlayable<AnimatorBehaviour>)playable.GetInput(i);
            AnimatorBehaviour input = inputPlayable.GetBehaviour ();

            if (inputWeight > strongestInputWeight)
            {
                strongestInputWeight = inputWeight;
                strongestName = input.animationName;
                strongestClipStart = input.ClipStartTime;
            }
        }

        if(strongestInputWeight != 0)
        {
            AnimationClip animation;

            try
            {
                animation = animator.runtimeAnimatorController.animationClips.Where(anim => anim.name == strongestName).First();
            }
            catch
            {
                throw new Exception($"Animator does not have an animation called {strongestName}");
            }

            float normalizedTime = (time - strongestClipStart) / animation.length;

            animator.Play(animation.name, 0, normalizedTime);

            if (Application.isEditor)
                animator.Update(Time.deltaTime);
        }
    }
}
3 Likes

That’s pretty awesome! Could you share the AnimatorBehaviour.cs?

Thanks for sharing this script. This help me a lot
Instead of putting animationclips on a animation track.
I also try to use a custom timeline track which only controlls an animators current state.

I’m exactly in the same case as the OP, with a bunch of generic animations reused across my characters, but each with their override.

So, what was it doing exactly? I thought it would find the override animation associated to some base animation set on the AnimatorMixerBehaviour track, but I don’t see references to AnimatorOverrideController. Maybe that part of the logic is in the AnimatorBehaviour class?

A custom track where you can set animator states would be great too! Although that seems harder to pass a reference to an animator state.

Personally I’m using a custom integer parameter for my animations, so I would only need to pass an integer. Either:
a. defining a custom track and placing custom clips with an int parameter
b. using Signal Track with Signal Receiver and placing custom Signal Emitters (markers) that can take an integer (in this case I need one marker to start the animation and one to stop it (revert to default animation)