Blend Tree
Blend Tree는 Animator Controller의 특수 노드로, 하나 또는 두 개의 float 파라미터로 여러 Animation Clip을 섞습니다. 속도·방향에 따른 부드러운 로코모션과 1D·2D 블렌드 가중치·Threshold를 다루는 실전 학습 가이드입니다.
상상해 보세요...
Blend Tree는 믹서입니다. "느린 걷기", "조깅", "스프린트" 세 트랙이 있을 때, 하드컷 대신 속도에 따라 크로스페이드합니다——2 m/s면 걷기 70% + 조깅 30%. 8 m/s면 스프린트 100%. 결과: 속도가 연속으로 바뀌어도 이음새 없는 로코모션입니다.
개념 자세히
Blend Tree는 Animator Controller의 State를 대체합니다——클립 하나 대신 파라미터로 여러 클립을 블렌드합니다. 주요 유형 셋: 1D(float 하나, 보통 속도), 2D Simple Directional(X/Z 속도처럼 float 둘, 8방향 이동), 2D Freeform Directional/Cartesian(더 유연한 영향 영역).
1D Blend Tree에서 각 클립에는 Threshold가 있습니다——파라미터가 두
임계값 사이에 있으면 Unity가 가중치를 보간합니다. 예: Idle 0, Walk 2, Run 6——Speed=1이면 Idle
50%/Walk 50%.
Automate Thresholds
를 켜면 클립을 균등 배치합니다.
2D Blend Tree는 더 풍부한 로코모션용입니다: Walk Forward/Back/Left/Right, Idle, Run Forward…를 수평+수직 속도로 블렌드. Unity는 Gradient Band Interpolation(Simple) 또는 Triangulation(Freeform)을 씁니다. 각 클립은 파라미터 공간에 (X, Y) 좌표를 가집니다.
Normalized time이 중요합니다: 클립 길이가 다르면 Unity가 시간을
정규화해 위상을 맞춥니다——걷기가 1초, 달리기가 0.6초여도 오른발이 함께 딛습니다. 모션마다
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; 8방향 이동은 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가 각 클립에 주는 가중치를 확인하세요.
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 가중치 읽기——발소리 오디오에 유용.
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: float 1개(속도)로 블렌드; 2D: float 2개(X, Z)
- ▸Threshold: 클립 가중치=1이 되는 파라미터 값
- ▸SetFloat에 damping을 써 블렌드 지터 방지
- ▸InverseTransformDirection으로 로컬 공간 변환
- ▸GetCurrentAnimatorClipInfo로 실시간 가중치 읽기
⚠️ 흔한 실수
❌ Walk/Run 블렌드 시 발이 미끄러짐
Walk와 Run 클립의 루트 모션 속도가 다름
✅ Blend Tree에서 "Adjust Time Scale"을 켜 속도를 정규화
❌ 2D Blend Tree가 대각선에서 이상함
45° 방향용 클립이 없음
✅ 대각선 클립을 추가하거나 "2D Freeform Cartesian" 사용