Animator Bug : Playing the Default state.

I think I have found a bug, or at least a very unexpected behaviour in the Animator.

It comes down to this: repeat calls to Animator.Play() in the same frame are ignored if the requested state is the default state.

Let me break it down. I have a simple state machine like this:

Then, (for good reasons that I will not elaborate) I am calling Animator.Play() twice in a frame, expecting at least the last call to go through.

Scenario 1: Two calls in one frame.

void Start () {
    var animator = GetComponent<Animator>();

    int hashA = Animator.StringToHash("A");
    int hashB = Animator.StringToHash("B");
    int hashDefault = Animator.StringToHash("Default");

    animator.Play (hashA); // <-- This is ignored
    animator.Play (hashB);

}

I added a logging StateMachineBehaviour to the states, output is this. So far so good.

I called “B” after “A”, so I expect the animator to play “B”, because that was the last call. It “ignores” the call to “A”, that’s fine.

Scenario 2: Second call is default state.

However, under different conditions, where I call “A” then “Default”:

animator.Play (hashA);
animator.Play (hashDefault);  // <-- This is ignored, wat?

I get this:

The animator is now not ignoring my first call, but it is “ignoring” the second call and playing “A” in stead of “Default”!

Scenario 3: Waiting a frame
If I wait for a frame, the call does go through.

void Start () {
    animator.Play (hashA);
    animator.Play (hashDefault); // This is ignored.. :(

    StartCoroutine(PlayLater(hashDefault));  // <-- Animator is upset now, he'll do it next frame.
}

IEnumerator PlayLater(int stateHash)
{
    yield return null;
    GetComponent<Animator>().Play (stateHash);
}

I suspect this has something to do with calling Play() on the current or on the default state. Is this a bug or is there a rationale for this behaviour? And if it is intentional, how am I supposed to work around it?

Case 1. You cannot queue more than one clip at a time because the animator need to process the request when it get a tick.

Case 2. In this case your statemachine is already playing the default state so the second call will be ignored, If you don’t like this behaviour you can simply set normalized time = 0 which will force the state to play from beginning
animator.Play(hashDefault, 0, 0);

Ah! Thanks for the reply, that clarifies things…

Do I understand correctly that:

  • States are really “queued” when you call “Play()”…
  • When queueing a new state, it replaces the current queued state?
  • But queueing a state that is currently playing is ignored?
  • Even when another state is already queued?
  • Except when you pass time = 0, then it will always replace the queued state?

Hi noio,

I’m looking at the doc right now and all this information is already available but maybe in the wrong format
Please take a look and if you have any suggest let me know
http://docs.unity3d.com/ScriptReference/Animator.Play.html

They are queue until the next animator update, The queue can only contain one state.

Yes but only if the new queued state is accepted.

Yes if you use the short version Play(mystatehash), If you want to be sure that it will be played even if it already played use the long form Play(mystatehash, 0, 0)

1 Like

Thank you! I understand how it works now. :slight_smile:

Docs are good, though they don’t mention the (one element) queue or the fact that states have to be “accepted”. I guess those things are too nuanced to explain there, but it can lead to the unintuitive situation above.

What I would expect is that if “Default” is currently playing and then you:

  • Play(A) - “A” is put in the queue.
  • Play(Default) - “Default” is not queued, but “A” is cleared from the queue.

The latest call was to “Default”, so reasonably you expect Default to either a) continue playing or b) start playing.

Those were my expectations anyway. Not sure how the docs could help because they operate at a level that is a bit more abstract and doesn’t bother the user with the queued state and its intricacies.