- Home /
MecAnim SubState Animation Complete
Hi folks,
Browsing around online, I've seen a lot of questions and answers revolved around determining if a specific animation is playing or not. What I need to do is check if any animation in a particular sub-state is playing.
Instead of storing the hash for every animation in a sub-tree (and having to add code each time a new animation is added), I'd rather simply make a check to see if any animation inside my sub-state is playing or not.
Is that feasible at all?
I asked this exact same question a few hours ago, and haven't seen it "approved" yet... very interested in the answer. I've had to create a "canPlay" bool in the meantime, which is just sloppy but works
I actually resorted to using tags ins$$anonymous$$d. At least with that approach it doesn't require any code changes...but there is, of course, the concern that any new animation states added don't get the appropriate tag set.
yea, Animator.SubState("X").IsPlaying or something would be VERY useful... not sure if it can be done though?
Answer by Ash-Blue · Jun 08, 2015 at 01:47 PM
Attempting this in Unity 4.6 and below will result in a huge mess of unmaintainable code (made that mistake a while back). But with Unity 5's shiny new State Machine Behaviours you can easily monitor a sub-state with a few lines of code. In order to do this we'll need to monitor a bool parameter on our Animator component.
Add a new bool to the animator representing when you are in your sub-state such as "attacking." This worked best for me since I'm monitoring the end of my attack animation sub-state.
On your desired sub-state machine, add this script by selecting it and clicking "Add Behaviour".
public class SubStateMonitor : StateMachineBehaviour {
[SerializeField] string myBool;
override public void OnStateEnter(Animator anim, AnimatorStateInfo stateInfo, int layerIndex) {
anim.SetBool(myBool, true);
}
override public void OnStateExit(Animator anim, AnimatorStateInfo stateInfo, int layerIndex) {
anim.SetBool(myBool, false);
}
}
You can now check if the sub-state machine is running anywhere with the following code snippet.
Animator anim = GetComponent<Animator>();
bool isSubState = anim.GetBool(myBool);
For more info on State Machine Behaviors please see the following resources.
Works perfectly! I think you forgot to mention that you have to set the animator variable name in the new behaviour in the editor. In your case, "attacking". Thanks!
Animator var would have to be set like you said. I skipped over that since I was guessing that would be assumed. Good point though for people who aren't used to working with the Animator component.
Ah, unfortunately doesn't work for me since an AnyState transition can occur in the root, bypassing any Exit's from the SS$$anonymous$$ i.e. the OnStateExit() never fires and the boolean stays true.
I thought any state always triggered OnExit for the currently playing item. You could always have the any state command reset your variables to the original defaults with a script or component.
You meant to type OnState$$anonymous$$achineEnter()
and OnState$$anonymous$$achineExit()
. Doing OnStateEnter()
and OnStateExit()
will cause the new boolean value to turn on and off every time it enters and leaves an animation state inside the state machine.
Depends on which you want. I usually use OnStateEnter
only so I can toggle bools with specific states.
Answer by RickshawDerpyDerp · Jan 04, 2020 at 07:35 AM
SOLUTION!!!
The above author might have made a typo. We do not want to overwrite OnStateEnter()
or OnStateExit()
; we want to overwrite OnStateMachineEnter()
and OnStateMachineExit()
. Put this in your new script and remember to define your boolean in the Animator state machine, and enter the name in the serialized field in the editor:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SubStateMonitor : StateMachineBehaviour
{
[SerializeField] string myBool;
override public void OnStateMachineEnter(Animator animator, int stateMachinePathHash)
{
animator.SetBool(myBool, true);
}
override public void OnStateMachineExit(Animator animator, int stateMachinePathHash)
{
animator.SetBool(myBool, false);
}
}
You can do the same boolean check as before (`animator.GetBool("YourBooleanNameHereInQuotes")`);
ORIGINAL POST
So, I can test when I'm inside a state machine now but it doesn't seem to recognize when I am inside a state anymore with (for example)
if (animator.GetCurrentAnimatorStateInfo(0).IsName("First_Punch"))
inside the state machine "Attack_Punch"
EDIT I have confirmed that when I am inside an animation state INSIDE a submachine, that inside the new behaviour script we wrote for the submachine, we automatically go through OnStateExit()
, which turns our new boolean to false
. This may be because I am already checking to see if I am inside another animation state (see IF statement above) and Unity can't allow me to be in two animation states at once (or check for it, or perhaps it has something to do with indexing). During the transition between animations, the I can see that OnStateEnter() is ran again and the new boolean's value is true
again.
So this is either an unfortunate oversight or (preferably) I am forgetting to do something when I run my existing code inside an IF statement that does if (animator.GetBool("sm_Attack_Punch")){ //Existing code, if statements here}
.
Can somebody please clarify?
In the above state machine, if I attach the behaviour to Battle_JumpAttack
, check that I am inside that state machine, and provided that is true, check that I am inside the first state called Jump_Start_Beginning
, the current state will not be Battle_JumpAttack
anymore when I am running the first animation.
Your answer
Follow this Question
Related Questions
Animator Transition between layers ? 0 Answers
Animation state not transitioning at 100% 1 Answer
Javascript controlling Mecanim? 1 Answer
How to Determine What AnimationClip/AnimationState Generated an AnimationEvent? 0 Answers
How can I tell what AnimationState mecanim Animator is in from script? 1 Answer