Event Utilities

This page has a few simple code snippets that demonstrate how you can achieve several different behaviours with Animancer Events by using the AnimancerEvent.Current property during an event to access its details.

Delegates

Since the methods shown here are only intended for use with Animancer Events, they're declared as delegate fields rather than regular methods so that assigning them doesn't create any Garbage.

Log Current Event

public static readonly Action LogCurrentEvent = () =>
{
    AnimancerEvent.Invocation current = AnimancerEvent.Current;

    // Clicking on the log message in the Console will highlight this object.
    Object context = current.State?.Graph?.Component as Object;

    Debug.Log(
        $"An {nameof(AnimancerEvent)} was triggered:" +
        $"\n- Event: {current.Event}" +
        $"\n- Name: {current.Name}" +
        $"\n- State: {current.State.GetDescription()}",
        context);
};

If you encountered a bug and wanted to figure out when certain events were being triggered, you could go through every event in a transition and make it log the event in addition to its normal callback:

[SerializeField] private ClipTransition _Transition;

protected virtual void Awake()
{
    for (int i = 0; i < _Transition.Events.Count; i++)
    {
        _Transition.Events.AddCallback(i, LogCurrentEvent);
    }
}

Restart Current State

public static readonly Action RestartCurrentState = () =>
{
    AnimancerEvent.Current.State.Time = 0;
};

This method could be used to play a non-looping animation but force it to loop:

[SerializeField] private AnimancerComponent _Animancer;
[SerializeField] private AnimationClip _NonLoopingClip;

protected virtual void Awake()
{
    AnimancerState state = _Animancer.Play(_NonLoopingClip);
    state.Events(this).OnEnd = EventUtilities.RestartCurrentState;
}

Pause At Current Event

public static readonly Action PauseAtCurrentEvent = () =>
{
    AnimancerEvent.Invocation current = AnimancerEvent.Current;
    current.State.IsPlaying = false;
    current.State.NormalizedTime = current.Event.normalizedTime;
};

This method could allow you to play an animation which stops at certain times to wait for something else to happen without needing to separate the animation into multiple AnimationClips. If there are no other events you could just go through them all like the Log Current Event example above, but otherwise you could use Event Names to assign this callback to any events with a particular name.

public static readonly StringReference PauseEventName = "Pause";

[SerializeField] private ClipTransition _Transition;

protected virtual void Awake()
{
    _Transition.Events.AddCallbacks(PauseEventName, PauseAtCurrentEvent);
}