Quick answer: Animation events only fire from the clip with the highest blend weight in a Blend Tree. If your event is on a clip that’s being blended out or has low weight, it won’t trigger. Use StateMachineBehaviour callbacks or time-based checks in your update loop instead of animation events for any logic that must fire reliably during blended animations.

You’ve placed an animation event on your walk cycle to play a footstep sound. It works perfectly in a standalone state. But the moment you put the walk clip into a Blend Tree — blending between idle, walk, and run — the footstep event stops firing. Or it fires inconsistently, sometimes playing and sometimes not, depending on the blend parameter value. This is one of Unity’s most frustrating animation gotchas, and it’s entirely by design.

How Animation Events Work in Blend Trees

Unity’s Animator evaluates animation events only from the clip with the highest blend weight in a Blend Tree. When you have three clips blending — idle (0.1), walk (0.6), run (0.3) — only events on the walk clip will fire because it has the highest weight. Events on the idle and run clips are suppressed.

This means that as the blend parameter changes smoothly, events jump between clips. At a blend value where walk has the highest weight, walk events fire. At a value where run takes over, suddenly run events fire and walk events stop. There’s no smooth transition or overlap — it’s a hard switch based on which clip is dominant.

The problem gets worse at threshold boundaries. When two clips have nearly equal blend weights, tiny fluctuations in the blend parameter can cause the dominant clip to flip back and forth between frames, leading to events firing from the wrong clip or not firing at all. If your blend parameter is driven by player input velocity, this flickering happens constantly.

Additionally, animation events can be skipped entirely if the Animator jumps past the frame where the event is placed. This happens during fast blend parameter changes, transitions, or when the game’s frame rate drops and the Animator advances by more than one frame’s worth of animation time in a single update.

Workaround 1: StateMachineBehaviour

The most reliable alternative to animation events in Blend Trees is StateMachineBehaviour. These scripts attach to Animator states (including Blend Tree states) and provide callbacks that fire reliably regardless of blending:

using UnityEngine;

public class FootstepBehaviour : StateMachineBehaviour
{
    [SerializeField] private float _stepInterval = 0.5f;
    private float _lastStepTime;

    public override void OnStateEnter(
        Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        _lastStepTime = 0f;
    }

    public override void OnStateUpdate(
        Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        float normalizedTime = stateInfo.normalizedTime % 1f;

        // Fire footstep at specific points in the animation cycle
        if (normalizedTime >= _stepInterval &&
            _lastStepTime < _stepInterval)
        {
            PlayFootstep(animator);
        }

        if (normalizedTime >= _stepInterval * 2f &&
            _lastStepTime < _stepInterval * 2f)
        {
            PlayFootstep(animator);
        }

        _lastStepTime = normalizedTime;
    }

    private void PlayFootstep(Animator animator)
    {
        var footsteps = animator.GetComponent<FootstepAudio>();
        if (footsteps != null)
            footsteps.PlayStep();
    }
}

Attach this script to your Blend Tree state in the Animator window by selecting the state and clicking Add Behaviour. The OnStateUpdate callback fires every frame while the state is active, and stateInfo.normalizedTime gives you the animation progress regardless of which clip is currently dominant in the blend.

This approach has a key advantage: it uses the state’s normalized time, which is a composite of all blended clips. It doesn’t depend on any individual clip’s weight, so events fire consistently at the same animation progress points no matter how the blend parameter is set.

Workaround 2: Update-Based Time Checks

If you prefer to keep the logic in your own MonoBehaviour rather than a StateMachineBehaviour, you can poll the Animator’s state directly:

using UnityEngine;

public class AnimationEventPoller : MonoBehaviour
{
    [SerializeField] private Animator _animator;
    [SerializeField] private string _stateName = "Locomotion";
    [SerializeField] private int _layer = 0;

    private float _prevNormalizedTime;
    private bool _firedHalfEvent;

    void Update()
    {
        var stateInfo = _animator.GetCurrentAnimatorStateInfo(_layer);

        if (!stateInfo.IsName(_stateName))
        {
            _firedHalfEvent = false;
            return;
        }

        float t = stateInfo.normalizedTime % 1f;

        // Fire at 25% and 75% of the animation cycle
        if (t >= 0.25f && _prevNormalizedTime < 0.25f)
        {
            OnLeftFoot();
        }

        if (t >= 0.75f && _prevNormalizedTime < 0.75f)
        {
            OnRightFoot();
        }

        _prevNormalizedTime = t;
    }

    private void OnLeftFoot() { /* play left footstep */ }
    private void OnRightFoot() { /* play right footstep */ }
}

This pattern tracks the normalized time between frames and fires events when the time crosses specific thresholds. It handles the case where normalizedTime wraps from 1.0 back to 0.0 at the end of a loop, though you may need additional logic if the animation speed is very high and can skip past a threshold in a single frame.

When Animation Events Still Work

Animation events are not entirely useless in Blend Trees. They’re fine for non-critical, cosmetic feedback where occasional missed events are acceptable:

Never use animation events in Blend Trees for gameplay-critical logic like:

For these, always use StateMachineBehaviour or an explicit update-based system. The cost of a missed event in gameplay logic — a sword swing that deals no damage, a projectile that never spawns — is far higher than the extra code required for a reliable alternative.

When players report “my attacks sometimes don’t connect” or “footsteps are missing,” the root cause is often animation events in a Blend Tree. These bugs are maddening because they’re intermittent and depend on the exact blend weight at the moment the event should fire. Logging the blend parameter value and the dominant clip when the issue occurs helps you reproduce the exact conditions — which is where automated bug reporting tools like Bugnet save hours of manual investigation.

If the event must fire every time, don’t put it on a blended clip. Use StateMachineBehaviour.