Whenever I need to check for the current Mecanim state, I use Animator.StringToHash and then compare it to the current state’s fullPathHash.
But what should I do when I want to check if the current state is in a sub state machine (ideally without adding state behaviors to manually keep track)? Maybe the current sub state machine can be extracted from the fullPathHash with some bit tricks?
I’ve seen this asked a half dozen times over the last couple days. @CDF@dreasgrech - what are some common reasons to want/need this information? (what sub-state machine is mecanim in)
I’m guessing maybe to fire off an event when the specific sub-state is recognized as the active state, but that doesn’t seem right since events are readily available? It’s just a little bothersome not to understand the ‘why’ to this question when it has been asked several times.
Why do you guys ‘check’ the states?
Thanks - Any help/clarification is greatly appreciated.
Imagine having two state machines, one for idle stance and one for combat stance, and from the code you need to check which stance the player is in according to the animation tree.
If you were able to check if the current state is under a specific state machine, then you would be able to determine whether the player is in idle or combat.
Unity doesn’t support this functionality, but supports State Tags instead i.e. you tag specific states (rather than state machines) and then in the code you check if the current state’s tag matches a specific tag.
^ yep. Sometimes I need to know if my animation is currently in an “Air” substate, “Attack” substate or “Normal” substate. The logic controlling the character needs to know this in order to tailor functionality around those states.
Maybe unnecessary if we created bools defining current state, but things tend to get out of whack when transitions occur and your animation can get out of sync from your logic, I also find it cleaner if I can grab the substate name rather than define all these bools or enums.
Can you give a simple example of tailored functionality that uses the state information? I might be really trying too hard to think around this.
Possibly a fall from a specific height causes damage if the registered state is falling for a long duration? Is that a simple type of functionality that would use the state information to update -50 health - fire a ‘ugh’ sound, maybe activate the limping animation sub-state for the character?
Haha - my mind is going crazy trying to figure this out, trying to understand the use/usefulness of knowing which state/sub-state the animation is in.
Recently I had to create a simple fighting game. I was using subStates for attack animations, grouping them all under an “Attack” subStateMachine. I needed to know when the character had successfully transitioned into one of the states within “Attack” subStateMachine so I could allow attack combos. Pressing the attack key again while in the “Attack” subStateMachine would advance the current type of attack to the next animation. If the player didn’t press quickly enough the animator would return to an “Idle” state and as a result, the attack combo script would be disabled.
I ended up using Tags to achieve this which is fine. But could probably get messy if the animator became very complex.
Have you guys thought of a LayerMask type setup? Assigning masks to states and subStateMachines, we could do bitwise logic to determine states.
attackMask = NormalAttack | SpecialAttack;
if ((animator.currentMask & attackMask) != 0) {
//we're in some kind of attack state
}
I’m trying to figure out how to get code to run anytime you exit a substatemachine to change some details about a character. When you enter certain subStateMachines, it hides their weapons and when you exit them, it shows them.
Currently I use OnStateMachineExit… however that ONLY runs if you hit the exit node for the subStateMachine. If an AnyState transition happens while you’re in the subStateMachine, that event won’t fire.
I was planning on making a StateMachineBehavior that uses OnStateExit, which will run anytime you exit any state in the subStateMachine and then check if the state it’s transitioning to is in the current subStateMachine… however this seems impossible as well.
As far as I can tell so far, it’s impossible to implement functionality that runs whenever you exit a subStateMachine for any reason (including transitions to “Any State”).
The only work around is to tag everything in every state… but this is incredibly impractical and it wastes the tags. I won’t be able to use them for any other functionality.
This is a terrible oversight and must be addressed.
Does anyone have any suggestions for any non-horrific workarounds?
For the exact reason you’re pointing out, I’ve had to create a script that collects data about all the states in the animatorController in edit time, and saves them. Then, in runtime, the script checks which state the machine is currently in, and sends custom version of OnStateMachineEnter/Exit whenever a state machine is entered or exited.
It’s ugly, and probably has an overhead, but OnStateMachineEnter/Exit is very useful concepts, so creating a script that implements them properly was worth it.
I see, so that’s how you did it… that’s really frustrating lol. I wish there was a native way to do this correctly… I guess I’ll either try to implement a similar solution or try to work around the problem by trying to force all my statemachines to always enter through the entry node.
The main issue I’m having right now is that I toggle something off upon entering a few subStateMachines and then I turn it back on upon exiting. If I exit via AnyState interrupting the process, it never gets reenabled.
The “thing” that I’m toggling is the currently equipped weapon, so I guess I can toggle it back on when I reenter a “normal” combat statemachine… assuming I always make sure they enter the machine in the prescribed manner.
Unity needs to be able to tell when it’s inside a substate machine for all the reasons described above. I have several substate machines with LOTS of states inside, and it would be tedious, if not too much overhead, to add the same tag (in addition to whatever other tag I need) to every state in that machine. Example:
I use the names of animation states in my Update() and FixedUpdate() methods to do checks in IF statements. that check looks like (for one example):
if (animator.GetCurrentAnimatorStateInfo(0).IsName("Run_Back_Home"))
{
//Do stuff
}
Now, a lot of these animation states are inside of other state machines. Take the Battle_JumpAttack state machine:
It would be most simple for me (I think) to access animations based primarily on whether I am inside this machine. How do I check for that?
More info: Some animations can happen immediately after another ends; others need to be triggered manually (in the Update() loop) only after a Lerp() has completed. But I only want to test for these conditions while I am inside this state machine
Fighting with the exact same problem right now and I really would like to avoid having to add Tags to every single state inside every single sub-statemachine. Is there still no easy/native way to check if the animator is in a specific sub-statemachine?
Yeah, but I’d rather avoid doing it that way. I don’t want to have to carry over this kind of inpsector-variable information into the runtime with a script that needs to run at editor-time. I do it manually now inside a StateMachineBehaviour that sits on the substatemachine by naming the sub-states that need to be monitored in a public string list variable… Out of all the inconvenient solutions I prefer the “do it manually” one I guess… Next time I’m going to avoid the Animator component altogether.