---
title: "Blend idle, walk and run animations in C#"
url: https://recursiveai.org/onegame/cookbook/blend-walk-run-animation/
description: "A blend space mixes animation clips by speed. Idle, walk and run must already exist in the model; this does not create new walk cycles."
version: "2.0.0"
---

# Blend idle, walk and run animations in C#

**onegame** is a free, open-source game engine for .NET from Recursive AI. MIT or Apache-2.0, no editor required.

[NuGet](https://www.nuget.org/packages/RecursiveAI.OneGame.Gltf) · [GitHub](https://github.com/recursive-ai-oss/onegame) · [Docs](https://recursiveai.org/onegame/docs/) · [Download example (.zip)](https://recursiveai.org/onegame/cookbook/blend-walk-run-animation/blend-walk-run-animation.zip)

A blend space mixes animation clips by speed. Idle, walk and run must already exist in the model; this does not create new walk cycles.

```shell
dotnet add package RecursiveAI.OneGame.Gltf
```

Requires [.NET 10](https://dotnet.microsoft.com/download/dotnet/10.0) (net10.0); .NET 9 and earlier aren’t supported.

`figure.glb`, the skinned sample, is in the zip.

```csharp
using OneGame.Gltf;
var rig = new Rig(
    GltfLoader.LoadFile("figure.glb"));
var anim = new Animator(rig, rig.Node("Root"));
anim.AddFloat("speed");
anim.AddState("move", new BlendSpace1DMotion(
    new BlendSpace1D(0, 1, 2), rig.Clip("idle"),
    rig.Clip("walk"), rig.Clip("run"))
    { XParameter = "speed" });
anim.SetFloat("speed", 1.5f);
anim.Play("move", 0.25f);
Console.WriteLine(anim.CurrentState);
```

Prints `move`: the animator is in its movement state.

```text
move
```

Unzip [the example](https://recursiveai.org/onegame/cookbook/blend-walk-run-animation/blend-walk-run-animation.zip), then `dotnet run`.

## Full program

```csharp
using OneGame.Gltf;

var rig = new Rig(GltfLoader.LoadFile("figure.glb"));
var animator = new Animator(rig, rig.Node("Root"));
var motion = new BlendSpace1DMotion(new BlendSpace1D(0, 1, 2),
    rig.Clip("idle"), rig.Clip("walk"), rig.Clip("run")) { XParameter = "speed" };
animator.AddFloat("speed");
animator.AddState("move", motion);
foreach (float speed in new[] { 0f, 0.5f, 1f, 1.5f, 2f })
{
    animator.SetFloat("speed", speed);
    animator.Play("move", 0.25f);
    var shin = animator.Pose.Rotation[rig.Node("ShinR")];
    Console.WriteLine($"Speed {speed:F1}; phase {animator.StateProgress:F2}; shin X {shin.X:F4}");
}
```

```text
Speed 0.0; phase 0.25; shin X 0.0000
Speed 0.5; phase 0.25; shin X -0.1983
Speed 1.0; phase 0.25; shin X -0.3886
Speed 1.5; phase 0.25; shin X -0.4718
Speed 2.0; phase 0.25; shin X -0.5509
```

The full program shows the blend changing: it samples several speeds at the same quarter-cycle phase and prints the right shin’s changing rotation component. The console inspects poses without opening a window.

An undeclared animator parameter throws `UnknownAnimatorNameException`; a missing model clip throws `KeyNotFoundException`.

The fixture is the public repository’s code-generated box figure, redistributed under MIT or Apache-2.0 with both license texts in the zip. Its [generator source](https://github.com/recursive-ai-oss/onegame/blob/60d5573da204de68cafd5896dc8d41b16c72ff9d/examples/character/art/Program.cs) shows the skeleton and animation inputs.

## Variations

**Glide to a speed instead of snapping.** Append this to the snippet at the top:

```csharp
anim.MoveFloat("speed", 2f, 4f);
anim.Update(0.1f);
Console.WriteLine($"{anim.GetFloat("speed"):F1}");
```

The additional line printed is:

```text
1.9
```

## Related recipes

- [Bake deterministic root motion in C#](https://recursiveai.org/onegame/cookbook/bake-deterministic-root-motion/)
- [Solve two-bone inverse kinematics in C#](https://recursiveai.org/onegame/cookbook/solve-two-bone-ik/)
- [Play a glTF character animation](https://recursiveai.org/onegame/cookbook/animate-gltf-character/)

## The short answer

Use `BlendSpace1DMotion` with a `BlendSpace1D` containing the speed positions for idle, walk and run. Add that motion to an `Animator` state and connect its `XParameter` to a declared float parameter. In this example, 0 is idle, 1 is walk and 2 is run. A speed of 1.5 blends walk and run equally; it is a gait parameter, not an automatically measured velocity.

onegame separates simulation, which decides and records what happens, from the view, which draws it; synced state is the game data saved and replicated with the world. Keep the animator and parameter updates in view code. Read the character’s synced gait or movement state to choose a value, but do not use the resulting floating-point bone pose to move the simulation. Blending changes how the character looks. It does not by itself move its entity, perform collision handling or determine which movement command the player sent.

## How do I blend walk and run animations in C#?

Load clips from the same rig and place them in the same order as the blend-space coordinates. The full program places idle at 0, walk at 1 and run at 2. The positions are application choices: use thresholds that match the values your game feeds into the parameter. There must be one clip for each sample position or construction throws `ArgumentException`.

A one-dimensional space blends the two neighboring samples and clamps outside the endpoints. That means speed 0.5 blends idle and walk, while 1.5 blends walk and run. It does not mix all three equally. Above 2, this configuration uses the run endpoint rather than inventing a faster gait or extrapolating the skeleton.

The output deliberately inspects a joint that differs between the fixture’s poses. The shin’s X quaternion component is a compact observable value, not a bend angle in degrees. Changing the model changes those numbers. To draw the result in a game, register the same model in the scene’s model library and submit the animator’s pose from the character’s view, as in [playing a glTF character](https://recursiveai.org/onegame/cookbook/animate-gltf-character/).

## How do I keep walk and run animations synchronized?

The motion samples each clip at a shared phase: the fraction of its own duration. A quarter-phase sample therefore means a quarter of the walk cycle and a quarter of the run cycle, even if their durations differ. The full program cuts to phase 0.25 for each speed so the printed results compare the same point in the cycle rather than different elapsed times.

The source animations still need compatible cycle alignment. Sharing a phase does not identify which foot should be planted or repair unrelated clips. Export cycles with corresponding contacts at corresponding phases. This blend space uses the clips already present in the model; it does not retarget a second skeleton or generate missing frames from a static mesh.

In a continuous view, update the animator once per frame with `UpdateTo` using view time derived from scene ticks. The [animation guide’s `Describe3D` example](https://recursiveai.org/onegame/docs/animation/) shows the call using `scene.Tick` (completed simulation ticks) and `scene.Alpha` (the fraction toward the next tick). Its fixed-step view clock is separate from simulation state. When restoring a view to an exact moment after a large gap, `Play(state, progress)` selects that moment explicitly, as this console does for comparisons.

## How do I make the walk-to-run transition smooth?

Use `SetFloat` when the parameter must change immediately. Use `MoveFloat` to glide it toward a goal at a specified rate; the variation advances view time so you can see the updated parameter. Merely requesting the glide without advancing the animator does not demonstrate the change.

This is different from crossfading between states. Here one movement state continuously blends neighboring clips. State transitions are useful for separate actions such as a jump, while a speed parameter handles movement within the blend space. Avoid recreating the animator every frame: it owns playback and parameter state for one drawn character. The [animation guide](https://recursiveai.org/onegame/docs/animation/) describes both operations and their view-only role.
