- Home /
Checking current Animator Controller states gives unexpected result
We are trying to set up an animation system where we can "compose" character animations based on body part animations.
We have an animator component with multiple layers, one for each extremity, where each layer has a "ready" state with no animation, and then a bunch of states springing from the "ready" state with a simple animations each (e.g. a "raise hand" state).
Each one of these has an incoming transition, from the "ready" state, that fires based on a trigger parameter of the same name as the desired destination state. Each animation state also has an exit time transition back to the "ready" state.
Our idea was to implement each "composed" animation as a "block", where each block contains the triggers we want to fire in each layer. Then we put several blocks in a queue, which fires the animations corresponding to one block, then when those are done (all layers are back in the ready state) grabs the next block from the queue and triggers the next block of animations, and so forth.
To check whether a block is done, we use the AnimatorIsReady() function to iterate over all the layers and ask if each layer is in the "ready" state. If all are ready, it returns true, and if any are not ready, it returns false.
The problem we are having is that the function we use to check whether all layers of the Animator are in the "ready" state returns true even though we should not be in the "ready" state, that is, it returns true even though we've just told the Animator to transition to some new states.
We think it is because this function checks the layer states before the state has had time to transition according to our triggers, but we don't know how to make it check the layers after the transitions are complete. What would be the way of enforcing this "sequentiality"?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AnimationCompositionController : MonoBehaviour
{
private readonly BlockQueue _blockQueue = new BlockQueue();
public Animator animatorController;
public bool isReady;
private void Start()
{
animatorController = GetComponent<Animator>(); // Asigno el controller del personaje
List <LayerInfo> d1 = new List <LayerInfo>();
d1.Add(new LayerInfo("CrossArms"));
d1.Add(new LayerInfo("HandWave"));
Block b1 = new Block(d1);
List <LayerInfo> d2 = new List <LayerInfo>();
d2.Add(new LayerInfo("CrossArms"));
Block b2 = new Block(d2);
//should fire the b1 anim, finish, then fire b2. But actually fires both
//at the same time.
_blockQueue.Enqueue(b1);
_blockQueue.Enqueue(b2);
isReady = true;
}
private bool AnimatorIsReady()
//returns true if every layer in the Animator is in the state named "ready"
{
for (int i = 1; i < animatorController.layerCount; i++)
{
string layerName = animatorController.GetLayerName(i);
// Debug.Log(layerName+".ready");
var currentAnimationStateInfo = animatorController.GetCurrentAnimatorStateInfo(i);
if (!currentAnimationStateInfo.IsName(layerName + ".ready"))
{
Debug.Log("i´m in"); //gets here
return false;
}
}
return true;
}
private void Update()
{
if (!_blockQueue.IsEmpty())
{
if (isReady)
//if all layers are in the ready state, then...
{
isReady = false;
Debug.Log("imheremyfellas"); //gets here immediately, on the first
//run it goes into the if block twice. should go in once, play the
//animations, then go in again.
Block currentBlock = _blockQueue.Dequeue();
ExecuteAnimationBlock(currentBlock);
}
}
}
private void LateUpdate()
{
isReady = AnimatorIsReady();
}
private void ExecuteAnimationBlock(Block block)
{
// Ejecuto el bloque
foreach (LayerInfo layerInfo in block.GetLayerInfos())
{
animatorController.SetTrigger(layerInfo.destinyState);
//destinyState has the name of the parameter that transitions to a
//certain state.
}
}
}
Your answer
Follow this Question
Related Questions
how to make multiple transition from one state? 1 Answer
StateMachineBehaviour.OnDestroy is getting called by SetActive 1 Answer
How to delete a StateMachineBehaviour via Editor Script? 1 Answer
State Machine Behaviour together with Animation Events 1 Answer
"Anim A -> Anim B, Anim C -> Anim B" or "Any State -> Anim B" would there be a difference? 0 Answers