Skip to main content

Animator State Query

Construct AnimatorStateQueryAspect from a rig's AnimatorControllerLayerComponent buffer to read its current state and transition. This is a plain helper struct, not an Entities IAspect.

Names are hashed with CalculateHash32() from Rukhanka.Toolbox. Use the state or transition name stored in the baked controller, not Unity's Animator.StringToHash. For example, a transition named Turn Right -> Turn Left is hashed as that complete string.

Transition Name

The following system checks layer zero after the animation group has updated. Replace the example names with names from your controller and restrict the query to the relevant rigs in your game.

using Rukhanka;
using Rukhanka.Toolbox;
using Unity.Collections;
using Unity.Entities;

public struct AnimatorQueryResult : IComponentData
{
public bool inRequestedState;
public bool inRequestedTransition;
public float normalizedStateTime;
}

[UpdateInGroup(typeof(SimulationSystemGroup))]
[UpdateAfter(typeof(RukhankaAnimationSystemGroup))]
public partial struct ReadAnimatorStateSystem : ISystem
{
uint stateHash, transitionHash;

public void OnCreate(ref SystemState state)
{
stateHash = new FixedString512Bytes("Idle Random").CalculateHash32();
transitionHash = new FixedString512Bytes("Turn Right -> Turn Left").CalculateHash32();
}

public void OnUpdate(ref SystemState state)
{
foreach (var (layers, result) in SystemAPI.Query<
DynamicBuffer<AnimatorControllerLayerComponent>, RefRW<AnimatorQueryResult>>())
{
const int layerIndex = 0;
if (layers.Length <= layerIndex || !layers[layerIndex].controller.IsCreated)
continue;

var animator = new AnimatorStateQueryAspect(layers);
var currentState = animator.GetLayerCurrentStateInfo(layerIndex);
result.ValueRW.inRequestedState = currentState.hash == stateHash;
result.ValueRW.normalizedStateTime = currentState.normalizedTime;
result.ValueRW.inRequestedTransition = animator.IsInTransition(layerIndex)
&& animator.GetLayerCurrentTransitionInfo(layerIndex).hash == transitionHash;
}
}
}

Add AnimatorQueryResult to the rig entity to opt it into this example. Layer indices are zero-based; check bounds before querying. During a transition, GetLayerCurrentStateInfo describes the source state. Use IsInTransition before interpreting transition data, since an inactive transition returns a default result.

State time is normalized by the state's duration and can exceed one for repeated playback. It is not a value clamped to the range 0–1. Transition time describes progress through the active transition.

With RUKHANKA_DEBUG_INFO enabled, RuntimeStateInfo and RuntimeTransitionInfo also contain a name field. See Animator State Query in the samples for an interactive display.