# Unity: detect animation's end

I need a way to detect if animation's clip finished playing and then execute a certain code. Here's some script, that I wrote (called in Update):

    if (Input.GetButtonDown ("Fire1") && pc_atttacking == false && PlayerStats.staminaCurrent != 0) {
pc_atttacking = true;
pc_anim.SetBool("attack", true);
}

if (pc_anim.GetCurrentAnimatorStateInfo (0).IsName ("attack")) {
pc_atttacking = false;
pc_anim.SetBool("attack", false);
}


But it doesn't work as I want; it executes second code too early - when "attack" animation is at slightly more than half of playing position. I want to execute it when "attack" animation is at last frame.

I usually prefer to use Animation Events for this, so that there's not a check hitting every Update when it's rarely actually needed. You could even make a generic alert system and pass in arguments to handle different animations ending or other events.

In this example, AlertObservers is in a component on the animated object.

    public void AlertObservers(string message)
{
if (message.Equals("AttackAnimationEnded"))
{
pc_attacking = false;
pc_anim.SetBool("attack", false);
// Do other things based on an attack ending.
}
}

• I like this approach, although I might add that using Enums is a nice choice as it avoids string comparison and also allows the use of a drop-down menu in the editor – PixelCake Games May 21 '18 at 23:57
• An update, after using this approach for a while: Animation Events can still trigger during animation transitions (i.e. when cross-fading between animations), which can cause unwanted behavior if you aren't careful with the timing. – Nate Buck Jan 31 at 19:59

You can check if the animation is complete by looking at the normalizedTime property of the Animator's AnimatorStateInfo:

if(pc_anim.GetCurrentAnimatorStateInfo(0).IsName("attack") &&
pc_anim.GetCurrentAnimatorStateInfo(0).normalizedTime >= 1.0f)
{
pc_atttacking = false;
pc_anim.SetBool("attack", false);
}

• You do not need the check against the normalizedTime from what I can tell. That is just putting a 1 second delay on whatever logic you want to run after the Animator is in that state. – Shadoninja Apr 23 '18 at 17:29

Well, on the other hand sometimes Coroutines would be just like a gift of God for you.

You can use it in more good way.

void Update()
{
if (Input.GetButtonDown ("Fire1") && pc_atttacking == false && PlayerStats.staminaCurrent != 0) {
pc_atttacking = true;
pc_anim.SetBool("attack", true);
StartCoroutine("OnCompleteAttackAnimation");
}
}

IEnumerator OnCompleteAttackAnimation()
{
while(pc_anim.GetCurrentAnimatorStateInfo(0).normalizedTime < 1.0f)
yield return null;

// TODO: Do something when animation did complete
}

• Should work, but this is a bit smelly in my opinion. – Evorlor Feb 29 '16 at 13:58
• @Evorlor I think it is better than adding more lines in Update – Hamza Hasan Feb 29 '16 at 13:59
• If you are speaking from a performance point of view, I think it's the same. But not sure...now I'm curious. I do agree though that sticking it in the update method isn't nice either. I guess the smelliness is on Unity's end, unless someone comes up with a clean way to do this. – Evorlor Feb 29 '16 at 14:01
• +1 for an alternative solution, but I hope others still can think of more. This is something that I have always struggled with in Unity – Evorlor Feb 29 '16 at 14:02
• I suggest replacing your while loop with: yield return new WaitUntil(() => pc_anim.GetCurrentAnimatorStateInfo(0).normalizedTime < 1.0f); – Evorlor Feb 29 '16 at 14:12

Use StateMachineBehavior, there's OnStateExit

override public void OnStateExit (Animator animator,
AnimatorStateInfo stateInfo,
int layerIndex)
{
if(stateInfo.IsName("attack")) return;
pc_atttacking = false;
pc_anim.SetBool("attack", false);
}


Create class (a new component) that inherit StateMachineBehaviour with above code, add the component to the gameobject that has the animation.

• I could never really get this working on my loopless animation. Start would fire, but Exit would not. – Norbert Feb 5 at 8:34