Skip to content

Animator

Drives an animator controller — the state machine that decides which clip plays. For building the controller itself, see the 2D Animation guide.

csharp
public class Player : GameEntity
{
    private Animator? m_Anim;

    protected override void OnCreate()
    {
        m_Anim = GetComponent<Animator>();
    }

    protected override void OnUpdate(float ts)
    {
        m_Anim?.SetFloat("Speed", System.Math.Abs(m_Velocity.X));
        m_Anim?.SetBool("Grounded", m_Grounded);
    }

    public void Jump() => m_Anim?.SetTrigger("Jump");
}

Parameters

Controller transitions are driven by named parameters you set from script.

MethodNotes
SetFloat(string name, float value)For blend conditions like walk speed
SetInt(string name, int value)For discrete states like a weapon index
SetBool(string name, bool value)Stays where you put it
SetTrigger(string name)A one-shot pulse, consumed by the transition that fires on it
ResetTrigger(string name)Clears a trigger that was set but never consumed
GetFloat(string name)Reads a float parameter back
GetInt(string name)Reads an int parameter back
GetBool(string name)Reads a bool parameter back

Bool or trigger?

A bool describes a lasting condition — Grounded, Crouching. A trigger describes a moment — Jump, Hit. Using a bool for a moment means remembering to clear it; using a trigger for a condition means it fires once and the state never comes back. ResetTrigger is for the case where you set a trigger and then the situation changed before any transition consumed it.

State

CurrentState

The name of the state the animator is in right now.

csharp
if (m_Anim.CurrentState == "Death")
    DisableInput();

NormalizedTime

How far through the current state's clip you are, where 0 is the start and 1 is the end. A looping clip keeps counting past 1.

csharp
if (m_Anim.CurrentState == "Attack" && m_Anim.NormalizedTime > 0.6f)
    EnableHitbox();

IsTransitioning

true while a transition between two states is in progress.

IsPlaying

true while the animator is running (not paused).

Playback

Play(string stateName, float normalizedTime = 0.0f)

Jumps straight to a state, ignoring transitions. Optionally starts partway through.

csharp
m_Anim.Play("Idle");
m_Anim.Play("Death", 0.5f);   // start halfway in

CrossFade(string stateName, float duration)

Blends into a state over duration seconds — the smooth counterpart to Play.

csharp
m_Anim.CrossFade("Run", 0.15f);

Speed

A multiplier on playback speed. 1 is authored speed, 0.5 is half, 2 is double. Read and write.

csharp
m_Anim.Speed = m_Slowed ? 0.4f : 1.0f;

Pause() / Resume()

Stop and restart playback where it is.

Reacting to state changes

Animator notifications are GameEntity overrides, not C# events — see Components for why.

csharp
protected override void OnAnimatorStateEntered(string stateName)
{
    if (stateName == "Attack")
        m_SwingSound?.Play();
}

protected override void OnAnimatorStateExited(string stateName) { }

protected override void OnAnimatorPose()
{
    // Layer procedural motion on top of the sampled clip.
    Translation += m_Recoil;
}

Exited and Entered fire once per transition, in that order. OnAnimatorPose runs after the animator has written this frame's pose, which is what lets you add recoil, a look-at or breathing on top of a clip without the next frame's sample wiping it out.

There was once an event here

Earlier versions declared Animator.StateEntered as a C# event. Nothing could ever raise it, so subscribing did nothing at all. It was removed rather than left as a trap — use the overrides above.

Animation events

A clip's event track can call a method on your script by name. Mark the method so the engine will dispatch to it:

csharp
[AnimationEvent]
private void Footstep()
{
    m_StepSound?.Play();
}

[AnimationEvent]
private void SpawnEffect(string effectName)
{
    Particles.Spawn($"Effects/{effectName}.jparticle", Translation);
}

Supported signatures are void F(), void F(string), void F(float) and void F(int). An unsupported signature is reported once in the log and the event is skipped — playback never crashes over it.

The attribute is required. A method without it can't be called from a clip, which keeps an animation from reaching arbitrary methods on a script that never opted in. See Attributes.

Animation.Sample(GameEntity entity, string clipPath, float time)

Applies one frame of a clip to an entity directly, with no animator involved — for posing something at a fixed moment. The entity needs whatever components the clip's tracks target.

csharp
Animation.Sample(this, "Animations/Wave.janim", 0.5f);

See also