Problem with StateMachineBehaviour OnStateExit()?

Hi, I think I’ve discovered what I this is a bug in the Animator. It seems that OnStateExit() is not called on an Animator state when a transition is interrupted.

I have a state machine with some animation states and those state have properties associated with them. I use StateMachineBehaviours to set and track these properties like a reference counter only this idea doesn’t work as sometimes some a state never calls OnStateExit even though it called OnStateEnter.

It doesn’t make sense that you can ‘Enter’ a State and never ‘Exit’ it, yet still somehow exit it.

Is this a known issue?

There’s a lot of weirdness going on with the State Machines. As far as I can tell, you don’t have any guarantees that the Exit functions will be called - both OnStateExit and OnStateMachineExit have a ton of conditions under which they simply won’t be called.

There is also no relation whatsoever between what causes an Enter function to be called, and what causes an Exit function to be called. In general, the state machine behaviours are a great idea, and if the functions did what they were named, it would be a fantastic system.

For now, it’s seriously flawed by design.

I had to write my own solution to guarantee that OnStateMachineExit gets called, I might take the time to write a general solution that runs all of the messages reliably.

Do you know if it is reliable now? I remember reading about these issues but I can’t find the link anymore.

It’s realiably bad, by design.

It’s been a while since I’ve used the Animator much (we’ve rolled our own thing based on Playables), but the general idea is this:

OnStateMachineEnter/Exit is only called when the state machine is entered or exited though the entry/exit nodes. Ie. if you transition to a state in a state machine, or use an any-state transition, those methods are not called.

OnStateEnter is called on the first frame a state starts playing, and OnStateExit gets called on the frame after a state is done. This means that the order is inverse of what you expect when transitioning from A to B, as A.OnStateEnter gets called long before B’s OnStateExit. Note that this is different from the timing of when the Animator changes what state it “is in” - ie. what gets returned by GetCurrentAnimatorStateInfo.

This means that you really shouldn’t use an SMB for anything else than modifying the animation on the state the SMB is placed on.

1 Like

Thanks a lot. I understand what you said, it will take a little experimenting to fully grasp the concept however.
Now I know what to look for at least.

Oh god, it is still heavily broken now! The total design of state machine callbacks is rubbish, wasting me a lot of time to fix a “unfixable” bug!

Unity has alot of design flaw … the root bone on floor and nonoption to choose rip bone is also a flaw

I’m sorry to necro this post but what you are saying is unclear to me. Why do you think it is the inverse of what we would expect?

The only way it would be inverse is if we followed this logic:

[OnStateExit()—STATE A—OnStateStart()] Transition> [OnStateExit()—STATE B—OnStateStart()]

Which assumes that OnStateStart() is called when the transition to another state starts, as opposed to the actual state itself being active. Otherwise why would it be surprising that A.OnStateStart() is called long before B.OnStateExit?

For me personally this was the logic I would expect:

[OnStateStart()—STATE A—OnStateExit()] Transition> [OnStateStart()—STATE B—OnStateExit()]

Again, sorry to necro but I’m just trying to understand the logic.

Right, my explanation from back then is a bit convoluted.

The thing you’d expect is the same thing I expected then, but the actual flow you get is:

StateA OnStateStart()
// start transition A->B
StateB OnStateStart()
// transition A-B finishes
StateA OnStateExit()

In essence, the Animator is not a state machine, as it’s in several states at the same time during a transition.

1 Like