I’m using the animator component to animate my character in my game and C# to code it, and I want the game to know if an animation is playing or has finished, because they are a lot of things I intend to code into the game that would require knowing if an animation is playing of finished.
I’ve looked it up, and the only solutions I’ve found were in Javascript and for the Animation component.
If it helps, I’ll put my situation in, my character pulls out a gun, I want the game to know that while it does that, the player cannot shoot, reload or change weapons until that animation is finished, how would I do that?
I’m talking about the “Animator” component, not “Animation”.
If you use the animator and mecanim, then I think you should do something like that :
if (this.animator.GetCurrentAnimatorStateInfo(0).IsName("YourAnimationName"))
{
// Avoid any reload.
}
Be aware that your animation name should be similar to “Layer_Name”.“State_Name” but if you use a “sub-state machine” in mechanim then the animation name must be “Sub-StateMachine_Name”.“State_Name”.
I check it with the time … after i switch to another animation (like with a trigger) i have following condition:
if (Animator.GetCurrentAnimatorStateInfo(0).normalizedTime > 1 && !Animator.IsInTransition(0))
works like a charm for me
the check for animator is in transition check is mandatory cause otherwise there will be for 1 or 2 frames the time of the last state
unity resets the time after the transition is completed
I cannot add some code in the comment space, so I have answered there… sorry…
There is no “StateEnded” or “TransitionEnded” event for now on the mecanim system…
So the only way to do that is to pull the “CurrentAnimatorStateInfo” and check if you enter the state/leave it.
if(this.animator.GetCurrentAnimatorStateInfo(0).IsName("YourAnimationName"))
{
// Avoid any reload.
this.InMyState = true;
}
else if (this.InMyState)
{
this.InMyState = false;
// You have just leaved your state!
}
The number is the layer index. Basically, if you have not created a new layer in your mecanim window, you only have one layer at index 0.
Hello, I had this same sort of problem recently. Basically I had a phone object with an animator containing logic and animation clips for “PowerOff” and “PowerOn”. The goal was to play either of the animations, only under the condition that the other has finished playing.
When playing an animation I set a local bool allowTogglePower to false. To detect the end of the animation I used an AnimationEvent through the animation editor attaching a function which sets allowTogglePower to true.
Something like:
public class PhoneEx : MonoBehaviour
{
public Animator anim;
bool allowTogglePower = true;
// Called by UI Button Input
public void ToggleAnimation()
{
if(anim.GetBool("PowerOn") && allowTogglePower)
{
anim.SetBool("PowerOn", false); // Plays OffAnim
allowTogglePower = false;
}
else if(allowTogglePower)
{
anim.SetBool("PowerOn", true); // Plays OnAnim
allowTogglePower = false;
}
}
// Called by AnimationEvent on last frame of each animation
public void SetToggleOk()
{
allowTogglePower = true;
}
}
It is worth noting that I also set anim.enabled to false in SetToggleOk(). I then set it back to true when playing an animation… Might not be practical for big animator systems, but I don’t like how the animator iterates through the frames of an animation, even though it has finished and looping is turned off.
,
The following code will help you.
The method returns true if the playing of an animation state on animator is still playing.,
otherwise returns false.
If the layer is “Base Layer” in the Animator View, you should use 0 for the animLayer.
bool isAnimationStatePlaying(Animator anim, int animLayer, string stateName)
{
if (anim.GetCurrentAnimatorStateInfo(animLayer).IsName(stateName) &&
anim.GetCurrentAnimatorStateInfo(animLayer).normalizedTime < 1.0f)
return true;
else
return false;
}
Unfortunately, it’s not working for me. Because it’s always True. Maybe it’s caused by my animator setting as the picture.
However, I figure out another way(by checking its elapsed time and overall duration) and working. Here it is:
var animDuration = animator.GetCurrentAnimatorStateInfo(0).length;
var elapsedTime = animator.GetCurrentAnimatorStateInfo(0).normalizedTime;
var bFinished = (elapsedTime > animDuration/2f);
If you do not have any transitions and would like to to be notified when the animation has ended for the “stateName” in layer 0, I did by calling the following IEnumerator :
public IEnumerator PlayAndWaitForAnim(Animator targetAnim, string stateName)
{
targetAnim.Play(stateName);
//Wait until we enter the current state
while (!targetAnim.GetCurrentAnimatorStateInfo(0).IsName(stateName))
{
yield return null;
}
//Now, Wait until the current state is done playing
while ((targetAnim.GetCurrentAnimatorStateInfo(0).normalizedTime) % 1 < 0.99f)
{
yield return null;
}
//Done playing. Do something below!
EndStepEvent();
}
The main logic is once the state is entered, we should check if the fractional part of ‘normalizedTime’ variable reached 1, which means the animation has reached its end state.
this work perfectly for me
i tried to use is with different setting and it still work.
return !AnimatorIsPlaying() && animator.GetCurrentAnimatorStateInfo(0).IsName(stateName);
don’t remove ! from start
when you use { animator.GetCurrentAnimatorStateInfo(0).IsName(stateName); } in start it return false but after 1 or 2 frame it will return true thats what was causing issue
just try it and see the result