PART 5 · 강의 1/3

Motion Matching 아키텍처

PoseSearch 플러그인, PoseSearchDatabase, Schema, Cost 함수의 내부 동작을 심층 분석합니다.

SECTION 01

Motion Matching 개요

전통적 State Machine 방식과 Motion Matching의 근본적 차이

Motion Matching은 애니메이션 데이터베이스에서 현재 게임 상태에 가장 적합한 포즈를 실시간으로 검색하여 재생하는 기법입니다. State Machine의 수동 전이 규칙 대신, 비용 함수(Cost Function)로 자동으로 최적의 애니메이션을 선택합니다.

전통적 방식 (State Machine)

개발자가 상태와 전이 규칙을 수동으로 정의합니다. 상태 수가 많아지면 복잡성이 기하급수적으로 증가하고, 자연스러운 전이를 위한 블렌딩 튜닝이 필요합니다.

Motion Matching

애니메이션 데이터베이스에 포즈를 등록하면, 런타임에 입력/Trajectory에 가장 가까운 포즈를 자동 선택합니다. 전이가 자연스럽고 확장이 용이합니다.

UE5 PoseSearch 플러그인

UE5.4부터 PoseSearch 플러그인이 공식 지원됩니다. 에디터 → Edit → Plugins에서 Pose SearchMotion Trajectory 플러그인을 활성화해야 합니다. 이 두 플러그인이 Motion Matching 시스템의 핵심입니다.

Motion Matching 실행 흐름
입력 수집
Trajectory 예측
현재 포즈 추출
DB 검색(Cost)
최적 포즈 선택
블렌딩/재생
SECTION 02

PoseSearchDatabase와 Schema

애니메이션 데이터베이스의 구조와 피처 스키마 정의

PoseSearch 애셋 구조
UPoseSearchSchema (피처 정의) ├── Channels[] (Feature Channels) │ ├── Pose Channel ← 본 위치/속도 │ ├── Trajectory Channel ← 이동 궤적 예측 │ └── Custom Channel ← 사용자 정의 피처 ├── Skeleton* ← 대상 스켈레톤 └── SampleRate ← 샘플링 레이트 (30fps 등) UPoseSearchDatabase (애니메이션 DB) ├── Schema* ← 피처 스키마 참조 ├── AnimationAssets[] ← 등록된 애니메이션 │ ├── AnimSequence_Walk │ ├── AnimSequence_Run │ ├── AnimSequence_Turn_L │ └── ... ├── SearchIndex ← KD-Tree 기반 인덱스 └── Normalization Set* ← 피처 정규화 설정 UPoseSearchNormalizationSet └── 각 Channel별 평균/분산 → 피처 정규화
Schema Channel 입력 데이터 역할
Pose 본 위치, 본 속도 현재 캐릭터의 포즈와 DB 포즈 비교
Trajectory 미래 위치/방향, 과거 위치/방향 이동 궤적 매칭으로 반응성 확보
Tag GameplayTag 상태 기반 필터링 (전투/비전투 등)
Schema 설계 핵심

Schema의 Pose Channel에 너무 많은 본을 추가하면 검색 비용이 증가합니다. 일반적으로 발 2개 + 손 2개 + 골반 정도의 핵심 본만 포함합니다. Trajectory Channel은 미래 3~4 포인트(0.1s, 0.3s, 0.5s, 1.0s)가 표준입니다.

SECTION 03

Cost 함수와 검색 알고리즘

최적 포즈를 선택하는 비용 계산과 KD-Tree 검색

Motion Matching의 핵심은 Cost 함수입니다. 현재 게임 상태를 피처 벡터로 변환하고, DB의 모든 포즈 피처 벡터와의 거리(비용)를 계산하여 가장 낮은 비용의 포즈를 선택합니다.

Cost 계산 공식
TotalCost = W_pose * PoseCost + W_traj * TrajectoryCost + ContinuingCost PoseCost = Sum(|CurrentBonePos[i] - DBBonePos[i]|^2 * BoneWeight[i]) + Sum(|CurrentBoneVel[i] - DBBoneVel[i]|^2 * VelocityWeight[i]) TrajectoryCost = Sum(|PredictedPos[t] - DBTrajectoryPos[t]|^2 * TimeWeight[t]) + Sum(|PredictedFacing[t] - DBTrajectoryFacing[t]|^2 * FacingWeight[t]) ContinuingCost = 현재 재생 중인 애니메이션 유지 비용 (낮을수록 전환 억제) 검색 최적화: KD-Tree로 O(N) → O(log N) 검색
개념 코드
// Motion Matching Cost 계산 (개념) float CalculateCost(const FPoseSearchQuery& Query, const FPoseSearchPose& DBPose) { float Cost = 0.f; // Pose Cost: 현재 포즈와 DB 포즈의 본 위치/속도 차이 for (int32 i = 0; i < Schema->PoseBones.Num(); ++i) { float PosDiff = FVector::DistSquared( Query.BonePositions[i], DBPose.BonePositions[i]); Cost += PosDiff * Schema->PoseBones[i].Weight; } // Trajectory Cost: 예측 궤적과 DB 궤적의 차이 for (int32 t = 0; t < Schema->TrajectorySamples.Num(); ++t) { float TrajDiff = FVector::DistSquared( Query.TrajectoryPositions[t], DBPose.TrajectoryPositions[t]); Cost += TrajDiff * Schema->TrajectorySamples[t].Weight; } // Continuing Pose Cost: 현재 포즈에서 계속 재생하는 비용 if (DBPose.IsContinuingPose()) { Cost -= ContinuingPoseBias; // 현재 포즈 유지 선호 } return Cost; }
Continuing Pose Bias

Continuing Pose Bias는 현재 재생 중인 애니메이션을 유지하는 데 보너스를 부여합니다. 이 값이 너무 낮으면 포즈가 너무 자주 전환되어 떨림(jitter)이 발생하고, 너무 높으면 입력 변화에 반응이 느려집니다. 0.1~0.3 범위에서 조정하는 것이 일반적입니다.

SECTION 04

AnimBP에서 Motion Matching 사용

AnimGraph의 Motion Matching 노드 설정과 데이터 흐름

AnimGraph 설정
// AnimGraph에서 Motion Matching 노드 사용 // 1. Motion Matching 노드 추가 // - Database: PoseSearchDatabase 애셋 참조 // - Trajectory: CharacterMovement에서 자동 생성 // 2. Trajectory Component 설정 (캐릭터 BP에서) // - UCharacterTrajectoryComponent 추가 // - HistoryCount, PredictionCount 설정 // - SampleRate 설정 // 3. AnimBP EventGraph void UMotionMatchingAnimInstance::NativeUpdateAnimation(float DeltaSeconds) { Super::NativeUpdateAnimation(DeltaSeconds); // CharacterTrajectoryComponent에서 Trajectory 자동 수집 // Motion Matching 노드가 자동으로 Query 생성 및 DB 검색 } // 4. 결과: 최적 포즈의 AnimSequence + StartTime이 자동 재생 // 5. Inertialization으로 포즈 전환 블렌딩
필수 플러그인 설정

Motion Matching을 사용하려면 다음 플러그인을 활성화해야 합니다: Pose Search(핵심 검색 엔진), Motion Trajectory(궤적 예측), Chooser(조건부 DB 선택, 선택적). 프로젝트 설정에서 해당 모듈의 의존성도 추가해야 합니다.

SUMMARY

핵심 요약

  • Motion Matching은 Cost 함수로 DB에서 최적 포즈를 자동 선택하여, State Machine의 수동 전이를 대체한다.
  • PoseSearchDatabase에 애니메이션을 등록하고, Schema로 검색 피처(Pose/Trajectory)를 정의한다.
  • Cost = PoseCost + TrajectoryCost + ContinuingCost이며, KD-Tree로 효율적으로 검색한다.
  • Continuing Pose Bias로 포즈 전환 빈도를 제어하여 떨림을 방지한다.
  • UE5.4+에서 PoseSearch + Motion Trajectory 플러그인을 활성화하여 사용한다.
PRACTICE

도전 과제

배운 내용을 직접 실습해보세요

실습 1: PoseSearch 플러그인 활성화와 기본 설정

PoseSearch 플러그인을 활성화하고, PoseSearchDatabase를 생성하세요. Schema를 만들어 Bone Position Channel(foot_l, foot_r)과 Trajectory Channel을 추가하고, 이동 애니메이션 시퀀스 3개 이상을 Database에 등록하세요.

실습 2: Motion Matching 노드 연결

AnimBP의 AnimGraph에 Motion Matching 노드를 배치하고, 생성한 Database를 할당하세요. 캐릭터를 이동시키며 자동으로 최적의 포즈가 선택되는지 확인하고, 디버그 드로잉으로 Trajectory와 매칭 결과를 시각화하세요.

심화 과제

Schema의 Channel Weight를 조절하여 발 위치 정확도 vs 궤적 예측 정확도 간의 트레이드오프를 실험하세요. Database Group으로 Locomotion/Combat/Traversal을 분리하고, 상황별로 활성 Database를 전환하는 시스템을 구현하세요.