Blend Tree
Blend Tree 是 Unity Animator Controller 中的特殊节点,用一到两个 float 参数混合多段 Animation Clip,按速度与方向实现平滑运动过渡。适合角色八向移动、瞄准混合与坡度适应等场景,帮助动画师减少硬切抖动,让程序用参数驱动自然、可调的运动表现效果。
想象一下...
Blend Tree 是一台混音器。你有三条音轨:"慢走"、"慢跑"、"冲刺"。不是硬切,混音器按速度交叉淡化——2 m/s 时听到 70% 走 + 30% 慢跑;8 m/s 时 100% 冲刺。结果:速度连续变化时,移动动画也没有接缝。
概念详解
Blend Tree 在 Animator Controller 中替代普通 State—— 不是一段 clip,而是按参数混合多段。三种主要类型: 1D(一个 float,通常是速度)、2D Simple Directional(两个 float 如 X/Z 速度,八向移动),以及 2D Freeform Directional/Cartesian(影响区域更灵活)。
在 1D Blend Tree 中,每段 clip 有一个 Threshold——参数落在两个阈值之间时,
Unity 插值权重。例如:Idle 在 0,Walk 在 2,Run 在 6——Speed=1 时得到 Idle 50%/Walk 50%。
开启
Automate Thresholds
可均匀分布 clip。
2D Blend Tree 用于更丰富的移动:前/后/左/右走、Idle、前跑… 由水平 + 垂直速度混合。 Unity 使用 Gradient Band Interpolation(Simple)或 Triangulation(Freeform)。 每段 clip 在参数空间有 (X, Y) 坐标。
Normalized time 很重要:clip 长度不同时,Unity 会 归一化 时间以保持同相——
即使走 1s、跑 0.6s,右脚也始终一起落地。可对每段 motion 开启
Time Scale
控制播放速度。
1D 与 2D Blend Tree
1D Blend (Speed)
Idle
0
Walk
2
Walk
4
Run
6
Threshold: Idle=0 · Walk=2 · Run=6
2D Blend (Velocity X/Z)
动手步骤
在 State 中创建 Blend Tree
Animator 窗口 → 右键 → Create State → From New Blend Tree。或双击 State → Add Motion → New Blend Tree。
选择 Blend Tree 类型
Inspector → Blend Type:简单速度用 1D;八向移动用 2D Simple Directional。
指定 Parameter 并添加 Motions
1D:选 Float 参数(Speed)。(+)→ Add Motion → 拖入 Animation Clip。为每段设 Threshold。
在 Animator 窗口预览
播放时:在 Animator 窗口拖动 Parameter 滑条,实时看模型上的混合。
用脚本驱动
animator.SetFloat("Speed", velocity.magnitude);2D 再加 animator.SetFloat("VelocityX", vel.x)。
交互模拟器
调节 Speed 与 Direction,观察 Blend Tree 如何为每段 clip 分配权重。
Blend weights loading...
代码示例
基础用 Rigidbody 速度驱动 2D Blend Tree——多方向移动。
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);
}
}代码示例
进阶读取当前 Blend Tree 权重,了解哪段 clip 占主导——适合脚步音效。
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;
}
}📌 快速记忆
- ▸1D:按 1 个 float(速度)混合;2D:按 2 个 float(X、Z)
- ▸Threshold:某 clip 权重=1 时的参数值
- ▸SetFloat 加 damping 避免混合抖动
- ▸InverseTransformDirection 转到本地空间
- ▸GetCurrentAnimatorClipInfo 读取实时权重
⚠️ 常见错误
❌ 混合 Walk/Run 时角色脚滑
Walk 与 Run clip 的根运动速度不同
✅ 在 Blend Tree 上开启 "Adjust Time Scale" 归一化速度
❌ 2D Blend Tree 斜向看起来不对
没有 45° 方向的 clip
✅ 加斜向 clip,或用 "2D Freeform Cartesian"