Blend Space와 Aim Offset
BlendSpace1D, BlendSpace2D, AimOffset의 보간 알고리즘과 파라미터 시스템을 심층 분석합니다.
Blend Space 개요
BlendSpace1D와 BlendSpace2D의 구조와 보간 방식
Blend Space는 하나(1D) 또는 두 개(2D)의 파라미터 축에 애니메이션 샘플을 배치하고, 입력 파라미터 값에 따라 주변 샘플들을 자동 블렌딩하는 애셋입니다. 이동 속도/방향에 따른 로코모션이 대표적인 사용 사례입니다.
BlendSpace1D
단일 축(Axis) 기반. 속도(0~600) 축에 Idle, Walk, Run 샘플을 배치하면 속도에 따라 자동 블렌딩됩니다. 내부적으로 선형 보간(Lerp)을 사용합니다.
BlendSpace2D
2축(X, Y) 기반. 방향(-180~180)/속도(0~600) 평면에 샘플을 배치합니다. Delaunay 삼각측량으로 삼각형 영역을 구성하고, 무게중심 좌표(Barycentric)로 보간합니다.
// BlendSpace 파라미터 업데이트 (AnimBP에서)
void UMyAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
Super::NativeUpdateAnimation(DeltaSeconds);
FVector Velocity = GetOwningActor()->GetVelocity();
FRotator Rotation = GetOwningActor()->GetActorRotation();
// BlendSpace 입력 파라미터 계산
LocomotionSpeed = Velocity.Size2D();
LocomotionDirection = CalculateDirection(Velocity, Rotation);
// CalculateDirection: 속도 벡터와 액터 회전의 상대 각도 (-180~180)
}
Blend Space 고급 설정
축 파라미터, 스무딩, 동기화, 샘플 보간의 세부 제어
| 설정 | 설명 | 권장값 |
|---|---|---|
| Interpolation Time | 입력 파라미터 변화 시 보간 시간(스무딩) | 0.1~0.25s |
| Target Weight Interpolation Speed Per Sec | 샘플 웨이트 변화 속도 | 3.0~6.0 |
| Preferred Triangle Edge | 삼각측량 시 선호 간선 방향 | 상황별 |
| Notify Triggers | 블렌딩 중 Notify 발동 방식 | Highest Weighted |
| Sync Group | 샘플 간 페이즈 동기화 | Locomotion 시 권장 |
Blend Space에서 Walk와 Run 애니메이션의 발 타이밍이 맞지 않으면, 블렌딩 시 발이 미끄러지는(foot sliding) 문제가 발생합니다. Sync Group을 설정하면 모든 샘플이 동일한 애니메이션 페이즈에서 재생되어, 발 착지 타이밍이 자동으로 맞춰집니다.
Direction 축의 범위가 -180~180인데 입력값이 0~360이면 잘못된 영역에서 샘플링됩니다. FMath::UnwindDegrees()로 범위를 맞추거나, CalculateDirection 내장 함수를 사용하여 올바른 범위의 값을 전달하세요.
Aim Offset
Additive 방식의 Aim Offset 구조와 구현
Aim Offset은 특수한 형태의 BlendSpace입니다. 기존 포즈에 Additive로 합산하여 캐릭터의 상체 에이밍(조준)을 표현합니다. Yaw(좌우)와 Pitch(상하)를 축으로 사용하여 조준 방향에 따라 상체를 회전시킵니다.
// Aim Offset 입력값 계산
void UMyAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
Super::NativeUpdateAnimation(DeltaSeconds);
APawn* Pawn = TryGetPawnOwner();
if (!Pawn) return;
// 컨트롤러 회전과 액터 회전의 차이 = 에이밍 오프셋
FRotator AimRotation = Pawn->GetBaseAimRotation();
FRotator ActorRotation = Pawn->GetActorRotation();
FRotator DeltaRotation = (AimRotation - ActorRotation).GetNormalized();
AimYaw = FMath::Clamp(DeltaRotation.Yaw, -90.f, 90.f);
AimPitch = FMath::Clamp(DeltaRotation.Pitch, -90.f, 90.f);
}
Local Space Additive: 각 본의 로컬 트랜스폼에 델타를 더합니다. 단순하지만 기본 포즈가 변하면 결과가 달라집니다. Mesh Space Additive: 컴포넌트 스페이스에서 회전을 적용합니다. Aim Offset은 일반적으로 Mesh Space Additive를 사용하여, 기본 포즈가 달라도 에이밍 방향이 일관되게 유지됩니다.
BlendSpace + Aim Offset 통합 패턴
Locomotion Blend Space와 Aim Offset을 결합한 실전 AnimGraph 구성
Layered Blend Per Bone으로 하체(Locomotion)와 상체(Aim Offset)를 분리 블렌딩합니다. Branch Filter에서 spine_01 이상을 지정하면, 하체는 이동 애니메이션, 상체는 에이밍을 독립적으로 재생합니다. Blend Depth로 블렌딩 경계를 부드럽게 조절할 수 있습니다.
// AnimGraph 구성
BasePose = BlendSpace2D(Speed, Direction)
// 8방향 + Idle 샘플, Sync Group "Locomotion"
AimPose = AimOffset(AimYaw, AimPitch)
// 9포인트 Mesh Space Additive
BlendedPose = LayeredBlendPerBone(
BasePose: BasePose,
BlendPose: AimPose,
BranchFilter: "spine_01",
BlendDepth: 1,
BlendMode: MeshSpaceAdditive
)
FinalPose = Slot("DefaultSlot", BlendedPose)
// Montage가 재생 중이면 Slot에서 오버라이드됨
핵심 요약
- BlendSpace1D는 선형 보간, BlendSpace2D는 Delaunay 삼각측량 + 무게중심 좌표로 샘플을 블렌딩한다.
- Sync Group으로 샘플 간 페이즈를 동기화하면 발 미끄러짐(foot sliding)을 방지할 수 있다.
- Aim Offset은 Additive BlendSpace로, 기존 포즈에 에이밍 회전을 합산한다.
- Aim Offset은 일반적으로 Mesh Space Additive 모드를 사용하여 기본 포즈와 무관한 일관된 에이밍을 보장한다.
- Locomotion BlendSpace + Aim Offset을 Layered Blend Per Bone으로 결합하는 것이 표준 패턴이다.
도전 과제
배운 내용을 직접 실습해보세요
BlendSpace1D를 생성하고, Speed(0~600) 축에 Idle(0), Walk(200), Run(600) 애니메이션을 배치하세요. AnimBP의 State에서 이 BlendSpace를 사용하고, Speed 변수를 파라미터로 연결하여 자연스러운 속도 전환을 확인하세요.
AimOffset 에셋을 생성하고, Yaw(-90~90)와 Pitch(-90~90) 축에 방향별 조준 포즈를 배치하세요. AnimBP에서 컨트롤러 회전의 Yaw/Pitch를 계산하여 파라미터로 전달하고, 캐릭터가 마우스 방향을 바라보는 시스템을 완성하세요.
BlendSpace2D(Direction x Speed)를 만들어 8방향 이동 애니메이션을 구현하세요. Calculate Direction 함수로 이동 방향 각도를 계산하고, Strafe Left/Right, Forward/Backward 조합을 부드럽게 보간하세요. Target Weight Interpolation Speed로 블렌딩 속도도 조절하세요.