~3 min read

Animation and the Animator Controller

Animation clips, state machine, blend trees — how a character doesn't look like a puppet.

In Unity, animation is not just Transform movement. It is the Mecanim system: Animation Clip + Animator Controller (state machine) + parameters + transitions.

Animation Clip

A Clip is a .anim file with recorded property values over time. Sources of clips:

  • Imported from FBX — animations made in Blender/Maya/Motion Capture.
  • Recorded in the editor via the Animation window (Window → Animation → Animation).
  • Bought from the Asset Store (Mixamo and the like).

Each track of a clip is a path to a property relative to the root (for example, Hips/Spine/Head -> rotation) and a set of keyframes. Unity interpolates between the keys.

Animator Controller

This is a state machine: the nodes are states (clips or sub-state machines), the edges are transitions with conditions. The conditions are controller parameters:

  • Float — speed
  • Int — combo number
  • Bool — isJumping
  • Trigger — a one-shot “fire a transition”, reset automatically
        Idle  ───── Speed > 0.1 ────►  Run
          ▲                            │
          │ Speed < 0.1                │
          └────────────────────────────┘

       Any state ── isJumping=true ──► Jump

                                        ▼ on Land trigger
                                      (return to Idle)

Any State is a special node that transitions anywhere when its condition is met. Convenient for “took damage → reaction”, but be careful: the transition also fires on itself if you don’t disable “Can Transition To Self”.

public class PlayerAnim : MonoBehaviour
{
    private Animator _animator;

    private void Awake() => _animator = GetComponent<Animator>();

    public void OnMove(float speed) {
        _animator.SetFloat("Speed", speed);
    }

    public void OnJump() {
        _animator.SetTrigger("Jump");
    }
}
Hash the parameter names

Looking up parameters by string in SetFloat("Speed", ...) is more expensive than by hash: _animator.SetFloat(Animator.StringToHash("Speed"), ...). Cache the hashes in static fields.

Blend Tree

Often you need not “one animation → another”, but a smooth transition between similar ones. For example, walk ↔ run ↔ standing. This is a Blend Tree: inside a state, clips are blended by a parameter.

1D Blend Tree: one float (speed), blends Idle (0), Walk (2), Run (6). 2D Blend Tree: two floats (for example, InputX + InputY), blends 8 walk directions.

This is the standard technique for locomotion in shooters and action games.

Root Motion

By default the Animator changes the skeleton’s poses but does not move the GameObject’s root. If a clip has a “step forward” animation — the player stays in place, the legs “will be stepping”.

Root Motion enables using the displacement of the root bone as actual movement of the GameObject. Useful for cinematic animations (a grappling fight, a finisher) where the movement matches the animation exactly.

When not to use it: a classic shooter, where speed is determined by code and logic. Then Root Motion is disabled, and the Animator only shows the animation.

Avatar and humanoid retargeting

Unity distinguishes Generic and Humanoid skeletons. A Humanoid Avatar is a standardized bone map (hips, spine, chest, head, shoulders/arms/hands, legs/feet — and optional finger bones) onto which the actual bones of your skeleton are mapped. This enables retargeting: an animation recorded for one skeleton also runs on another — an NPC and the player have different models, one animation library.

When importing an FBX, choose Rig → Animation Type → Humanoid, then “Configure Avatar” — there Unity automatically assigns the bones; check them and save.

Animation Events

The Animation Window has a timeline with events — you can call methods of your C# code on a specific frame of the clip. The classic example is a footstep sound exactly when the foot touches the ground:

// The method must be on a component of the same GameObject (or its children)
public void FootStep_AnimEvent() {
    AudioSource.PlayClipAtPoint(_footstepClip, transform.position);
}

When importing a clip you can add an event on the desired frame and specify the method name. As for arguments — only one parameter (float/int/string/object).

Animation Rigging — procedural animation

The Animation Rigging package lets you apply procedural constraints on top of the Animator:

  • TwoBoneIK — tilt the arm so the hand reaches a point.
  • Aim Constraint — turn the head or a weapon toward a target.
  • Multi-Parent Constraint — a hand holds onto a door when the character opens it.

This saves you in situations where pure clip animation is not enough, but you don’t want to write a full-fledged IK solver.

Animator vs Animation: what they even are

There are two components, and they have historically been confused:

  • Animator — modern, with a state machine. Used in 99% of new projects.
  • Animation — old (legacy), without a state machine. A simple API: animation.Play("clip"). Do not use in new code.

In a new project — only the Animator.

In the next chapter — sound, which is no less important for the feel of the world.