Search Unity

‘Wait, I’ve changed my mind’ – State Machine Transition interruptions

July 13, 2016 in Engine & platform | 5 min. read
image05
image05
Share

Is this article helpful for you?

Thank you for your feedback!

I recently investigated a tricky bug reported by a user involving the combination of empty states, override layers, and transition interruptions. As I was digging in, I found that our documentation about transition interruptions in the animation system was a bit… minimalist. A long conversation with my team later, we concluded that a blog post was in order.

So let’s dive into some intricate details of State Machine Transitions and interruptions!

By default in the animation system, transitions cannot be interrupted: once you start going from one state to the other, there’s no way out. Like a passenger on a transatlantic flight, you’re cozily nestled in your seat until you reach your destination and you can’t change your mind. For most users, this is fine.

But if you need more control over transitions, Mecanim can be configured in a variety of ways to meet your needs. If you’re unhappy with your current destination, you can hop in the pilot’s seat and can change plans midway through your flight. This means more responsive animations, but also many opportunities to get lost in the complexity.  

So let’s walk through a few examples to sort that out. We can begin with a fairly simple state machine with four states, labeled A to D, and triggers hooked to every transition on the state machine.

image05

By default, when we trigger the A->B transition, our state machine transitions towards B and nothing can keep it from reaching its destination. But if we go on the A->B transition inspector and change the interruption source from “None” to “Current State”, our journey from A to B can be interrupted by some triggers on state A.

image01

Why only “some”? Because the “Ordered Interruption” checkbox is also checked by default. This means only transitions on state A that have a higher priority than the current one are allowed. Looking at the inspector of state A, we can see that this only applies to the A->C transition.

image02

So if we activate the A->B trigger, then shortly after the A->D trigger, our transition remains uninterrupted. However, if we press the A->C trigger instead, then the transition is immediately interrupted and the state machine starts transitioning towards C. 

 

Internally, the animation system records the pose at the time of the interruption, and will now blend between that static pose (X) and the new destination animation. image04Why a static pose, instead of a possibly smoother blend between the current and new transitions? Simply put: performance. When a game faces a cascade of interruptions, keeping track of several dynamic transitions taking place simultaneously would quickly made the animation system unscalable.

Now, if we uncheck that “Ordered Interruption” checkbox, then both A->C and A->D can interrupt the transition. However, if they are both triggered on the same frame, A->C will still take precedence because it has a higher priority.

If we change the interruption source to “Next State”, A->C and A->D can no longer interrupt the transition, regardless of their order. However, if we press the B->D trigger, we will immediately start transitioning from A to D, without completing the transition towards B.

Transition order matters on state B too. The “Ordered Interruption” checkbox is not available anymore (any triggered transition on B can interrupt the transition because they do not have a priority ranking relative to A->B), but the order of the transitions on B will determine which transition wins if both are triggered within the same frame. In this case, if B->D and B->C are triggered in the same frame, B->D will be selected.

image03

Finally, for complete control, we can set the Interruption Source to “Current State Then Next State”, or “Next State Then Current State”. In that case, the transitions will be analyzed independently on one state, then the other.

So, let’s assume we have the following configuration.

image00

During the A->B transition, a very excited player triggers four transitions within the same frame: A->C, A->D, B->C and B->D. What happens?

First, “Ordered Interruption” is checked, so we can ignore A->D right away: it has lower priority than A->B. The current state gets resolved first, so we do not even have to look at state B to know that transition A->C wins.

image02
image03
July 13, 2016 in Engine & platform | 5 min. read

Is this article helpful for you?

Thank you for your feedback!