Skip to main content

Animator Controller Events

Animator controller events are implemented in the form (just like animation events) of a component buffer that is filled by the animator state machine processing engine.

The following field excerpt describes the package component; do not redeclare it in your project:

public struct AnimatorControllerEventComponent : IBufferElementData, IEnableableComponent
{
public enum EventType
{
StateEnter,
StateExit,
StateUpdate
}

public EventType eventType;
public int layerId;
public int stateId;
public float timeInState;
}

Rukhanka Animation's state machine compute engine will fill this buffer with events that occurred in the current processing frame and clear all events from the previous frame. State machine events exist in the following types:

  • StateEnter - this event appears in the frame when the state machine enters some state.
  • StateExit - this event appears in the frame when the state machine exits some state.
  • StateUpdate - this event appears in the frames when the state machine advances through some state and there are no StateEnter and StateExit for such state.

These event types have a close relation to the OnStateEnter, OnStateExit, and OnStateUpdate of the StateMachineBehaviour Unity component.

The component fields are:

  • eventType - type of the event.
  • layerId - index of the layer of baked animator controller. Layer data can be accessed by using this index in the AnimatorControllerLayerComponent buffer.
  • stateId - index of the state of the baked animator controller layer. State data can be accessed by using this index in LayerBlob.states array of controller blob.
  • timeInState - normalized state time. It is not clamped to 0–1 and can exceed one during repeated playback.

Read these events after RukhankaAnimationSystemGroup in a local/client animation world. Do not clear the shared buffer or retain its elements across updates without copying them. stateId is a baked layer-local index, not a state-name hash; it can change when the controller is rebaked.

using Rukhanka;
using Unity.Entities;
using UnityEngine;

[UpdateInGroup(typeof(SimulationSystemGroup))]
[UpdateAfter(typeof(RukhankaAnimationSystemGroup))]
public partial struct LogControllerEventsSystem : ISystem
{
public void OnUpdate(ref SystemState state)
{
foreach (var events in SystemAPI.Query<DynamicBuffer<Rukhanka.AnimatorControllerEventComponent>>())
{
foreach (var controllerEvent in events)
Debug.Log($"{controllerEvent.eventType}: layer {controllerEvent.layerId}, state {controllerEvent.stateId}");
}
}
}

These events provide ECS data comparable to state callbacks; they do not invoke Unity StateMachineBehaviour objects at runtime. For predicted Netcode worlds, event-driven gameplay must also account for prediction and resimulation rather than assuming each event is delivered once.

Enabling Animator Controller Events​

By default, the animator controller events component buffer is not added to the animated entity. RigDefinitionAuthoring has a checkbox named Has Animator Controller Events which orders to add AnimatorControllerEventComponent buffer to the rig entity at the baking stage.

HasAnimatorControllerEvents checkbox