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.
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.
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.
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.
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: