Blend Tree
A Blend Tree is a special Animator Controller node that mixes several Animation Clips from one or two float parameters — smooth motion by speed and direction.
Imagine...
A Blend Tree is a mixer. You have three tracks: "slow walk", "jog", "sprint". Instead of hard-cutting, the mixer crossfades them by speed — at 2 m/s you hear 70% walk + 30% jog. At 8 m/s you hear 100% sprint. The result: locomotion with no seams even as speed changes continuously.
The concept in detail
A Blend Tree replaces a State in an Animator Controller — instead of one clip, it blends several from a parameter. Three main types: 1D (one float, typically speed), 2D Simple Directional (two floats such as X/Z velocity, 8-way movement), and 2D Freeform Directional/Cartesian (more flexible influence regions).
In a 1D Blend Tree, each clip has a Threshold — when the parameter
sits between two thresholds, Unity interpolates weights. Example: Idle at 0, Walk at 2, Run
at 6 — at Speed=1 you get Idle 50%/Walk 50%. Enable
Automate Thresholds
to space clips evenly.
A 2D Blend Tree is for richer locomotion: Walk Forward/Back/Left/Right, Idle, Run Forward… blended from horizontal + vertical velocity. Unity uses Gradient Band Interpolation (Simple) or Triangulation (Freeform). Each clip has (X, Y) coordinates in parameter space.
Normalized time matters: when clips have different lengths, Unity
normalizes time so they stay in phase — the right foot always steps together even if
walk is 1s and run is 0.6s. Enable
Time Scale
per motion to control playback speed.
1D and 2D Blend Trees
1D Blend (Speed)
Idle
0
Walk
2
Walk
4
Run
6
Threshold: Idle=0 · Walk=2 · Run=6
2D Blend (Velocity X/Z)
Hands-on steps
Create a Blend Tree in a State
Animator window → right-click → Create State → From New Blend Tree. Or double-click a State → Add Motion → New Blend Tree.
Pick the Blend Tree type
Inspector → Blend Type: 1D for simple speed; 2D Simple Directional for 8-way movement.
Assign a Parameter and add Motions
1D: pick a Float parameter (Speed). (+) → Add Motion → drop an Animation Clip. Set a Threshold per clip.
Preview in the Animator window
While playing: drag the Parameter slider in the Animator window to see the blend live on the model.
Drive it from script
animator.SetFloat("Speed", velocity.magnitude) and animator.SetFloat("VelocityX", vel.x) for 2D.
Interactive simulator
Tune Speed and Direction to see how the Blend Tree weights each clip.
Blend weights loading...
Code example
BasicDrive a 2D Blend Tree from Rigidbody velocity — multi-direction locomotion.
using UnityEngine;
public class BlendTreeDriver : MonoBehaviour
{
Animator anim;
Rigidbody rb;
static readonly int VelXHash = Animator.StringToHash("VelocityX");
static readonly int VelZHash = Animator.StringToHash("VelocityZ");
static readonly int SpeedHash = Animator.StringToHash("Speed");
void Awake()
{
anim = GetComponent<Animator>();
rb = GetComponent<Rigidbody>();
}
void Update()
{
// World velocity → character local space
Vector3 localVel = transform.InverseTransformDirection(rb.velocity);
// 0.1s damping so the blend does not jump
const float damp = 0.1f;
anim.SetFloat(VelXHash, localVel.x, damp, Time.deltaTime);
anim.SetFloat(VelZHash, localVel.z, damp, Time.deltaTime);
anim.SetFloat(SpeedHash, localVel.magnitude, damp, Time.deltaTime);
}
}Code example
AdvancedRead current Blend Tree weights to know which clip dominates — useful for footstep audio.
using UnityEngine;
public class BlendTreeReader : MonoBehaviour
{
Animator anim;
void Awake() => anim = GetComponent<Animator>();
// List clips currently blending and their weights
void Update()
{
AnimatorClipInfo[] clips = anim.GetCurrentAnimatorClipInfo(0);
foreach (var info in clips)
{
Debug.Log($"{info.clip.name}: {info.weight:F2}");
}
// Dominant clip (weight > 0.5) → pick a footstep volume
string dominant = "Idle";
float maxW = 0f;
foreach (var info in clips)
{
if (info.weight > maxW)
{
maxW = info.weight;
dominant = info.clip.name;
}
}
float footVol = dominant.Contains("Run") ? 1f :
dominant.Contains("Walk") ? 0.6f : 0f;
}
}📌 Quick recap
- ▸1D: blend by 1 float (speed); 2D: by 2 floats (X, Z)
- ▸Threshold: parameter value where a clip reaches weight=1
- ▸SetFloat with damping to avoid blend jitter
- ▸InverseTransformDirection to convert into local space
- ▸GetCurrentAnimatorClipInfo to read live weights
⚠️ Common mistakes
❌ The character foot-slides when blending Walk/Run
Walk and Run clips have different root-motion speeds
✅ Enable "Adjust Time Scale" on the Blend Tree to normalize speed
❌ A 2D Blend Tree looks wrong on diagonals
No clip for the 45° direction
✅ Add a diagonal clip, or use "2D Freeform Cartesian"