4
\$\begingroup\$

Question

Why doesn't an animation transition with an Exit Time of 0 immediately transition to the next state?


Minimal example

Using Unity 2018.3, I set up an AnimatorController with two states: Initial and Next. I wanted Initial to transition to Next immediately, so I tried setting an Exit Time of 0. However, this doesn't transition immediately:

ExitTimeZeroResult

As shown above, Initial state still runs instead of transitioning immediately to the Next state. (There is no Motion attached to the AnimationState, so perhaps it's using a default duration.)

Below are screenshots of my animation transition settings.

Initial-to-Next Next-to-Initial


Strange behaviour with small non-zero ExitTime

I also tried using an Exit Time of 0.01 (i.e. transition after 1% of the animation has played), and it transitions almost immediately as I expect most of the time. However, occasionally it will still play the Initial state:

ExitTime-0.01 Initial-To-Next-For-ExitTime-0.01

In this case, even though it transitions to Next immediately most of the time, it still occasionally waits for the Initial state to complete. (It happens much less frequently than the image above suggests, but the issue becomes more frequent if I set the ExitTime even lower, e.g. 0.003).


Workaround

From searching online, the recommended solution for immediate animation transitions seems to be to turn off Exit Time and use a condition (e.g. bool or trigger) to transition immediately instead.

(Edit: in my case, I've defined an animator bool parameter called ImmediateTransition and set it to true by default instead of using Exit Time 0.)

This seems to work, but I would like to better understand how Exit Time works and why it's not working the way I expect.

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

I'm trying to focus on the question being about how Exit Time might work and WHY this specific behaviour happens.

I think what's likely happening, is that the way Animator States evaluate/tick their logic, including exit time and conditions, is that when a State is updated it's normalized time is incremented first and logic is run only after that. So a State that just starts to play almost never starts at normalized time zero, rather at zero plus whatever the delta time was for the animator that frame.

I tested this by creating a StateMachineBehaviour Script that prints out the StateInfo.normalizedTime in OnStateUpdate(...) method, but only once per State entry (so only on first frame of it updating) and the results we're like expected, never zero, but always just a tiny bit over.

You can repeat the test yourself, by making a StateMachineBehaviour with these contents and attaching that SMB to some State.

    private bool FirstFrameConsumed;
    
    /// <summary>
    /// OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
    /// </summary>
    override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        FirstFrameConsumed = false;
    }
    
    /// <summary>
    /// OnStateUpdate is called on each Update frame between OnStateEnter and OnStateExit callbacks
    /// </summary>
    override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        if ( FirstFrameConsumed )
        {
            return;
        }
    
        FirstFrameConsumed = true;
        Debug.Log(stateInfo.normalizedTime);
    }

I think this also explains why exit times like 0.01 and lower occasionally seem to cause and immediate transition, but why that behaviour is irregular (the delta time on first frame of state is inconsistent, at least when Animator updates in Update Mode: Normal).

Secondly, this brings to light how States seems to handle their conditional checks for Exit Time. Since Exit Time = 0 won't transition if State starts at normalizedTime = 0.00056 (random, small increment of delta time at state entry), it's reason to suspect that a transition only occurs if it's conditions (Exit Time being a condition) are fulfilled before the normalizedTime passes its Exit Time.

This second assumption I tested by creating a simple AnimatorController setup with empty states (which have some default duration or around a second or so), then slowed down the states so I can manually toggle some AnimatorControllerParameters and observe how the transitions are evaluated.

Transitions:

  • Reset (Trigger) parameter immediately transitions to state A, 0-length transition.
  • A-to-B: TriggerB Condition, Exit Time 0.5, 0.5 normalized length transition.

Scenario 1: I set TriggerB right at start of A. At 0.5 normalizedTime the trigger is consumed and transition to B starts to proceed.

Scenario 2: I set TriggerB after Exit Time (normalizedTime > 0.50), TriggerB remains unconsumed until next loop when normalizedTime just passes the Exit Time.

While this behaviour is handy for guaranteeing you can setup transitions that always start at a fixed point and produce a consistent-looking blend between two states, this does sometimes feel unintuitive (I'd personally expect the conditions to trigger the transition anywhere between exit time and end of state/loop), often making it tricky to create dynamic transitions with the builtin tools.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you for your detailed answer. I didn't repeat your tests but this seems like a good explanation. \$\endgroup\$
    – sonnyb
    Commented Jul 24, 2020 at 15:37
3
\$\begingroup\$

Has Exit Time: Exit Time is a special transition that doesn’t rely on a parameter. Instead, it relies on the normalized time of the state. Check to make the transition happen at the specific time specified in Exit Time.

Exit Time: If Has Exit Time is checked, this value represents the exact time at which the transition can take effect. This is represented in normalized time (for example, an exit time of 0.75 means that on the first frame where 75% of the animation has played, the Exit Time condition is true). On the next frame, the condition is false.

Fixed Duration: If the Fixed Duration box is checked, the transition time is interpreted in seconds. If the Fixed Duration box is not checked, the transition time is interpreted as a fraction of the normalized time of the source state.

Transition Duration: The duration of the transition, in normalized time or seconds depending on the Fixed Duration mode, relative to the current state’s duration. This is visualized in the transition graph as the portion between the two blue markers.

enter image description here

Transition Offset: The offset of the time to begin playing in the destination state which is transitioned to. For example, a value of 0.5 means the target state begins playing at 50% of the way through its own timeline.

Interruption Source: Use this to control the circumstances under which this transition may be interrupted.

Ordered Interruption: Determines whether the current transition can be interrupted by other transitions independently of their order.

Conditions: A transition can have a single condition, multiple conditions, or no conditions at all. If your transition has no conditions, the Unity Editor only considers the Exit Time, and the transition occurs when the exit time is reached. If your transition has one or more conditions, the conditions must all be met before the transition is triggered.

A condition consists of:

  • An event parameter (the value considered in the condition).
  • A conditional predicate (if needed,for example, ‘less than’ or ‘greater than’ for floats).
  • A parameter value (if needed).

If you have Has Exit Time selected for the transition and have one or more conditions, note that the Unity Editor considers whether the conditions are true after the Exit Time. This allows you to ensure that your transition occurs during a certain portion of the animation.

For more information please visit: Unity Manuel.

\$\endgroup\$
3
  • \$\begingroup\$ Thanks for the details, but I still don't understand why an exit time of 0 doesn't cause an immediate transition. According to the definition here, shouldn't a 0 exit time mean that on the first frame where 0% of the animation has played, the Exit Time condition should be true? \$\endgroup\$
    – sonnyb
    Commented Aug 28, 2019 at 15:01
  • \$\begingroup\$ Ok. "Exit time" is not the only property which cause the transition but there is impact of the "transition duration" and "fixed duration". i can see you have setup the "transition duration" to 0 which is good also disable the "fixed duration" check box and set "exit time" to 0 and unchecked the "has exit time". please let me know if it worked, because i kinda curious know. hehehe \$\endgroup\$
    – Swati
    Commented Aug 29, 2019 at 4:27
  • \$\begingroup\$ Yes, unchecking "Has Exit Time" and using a condition instead will work. I mentioned this already in my question in the "Workaround" section. \$\endgroup\$
    – sonnyb
    Commented Aug 29, 2019 at 15:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .