Foot IK와 지형 적응
Foot Placement, LineTrace 기반 지면 감지, 경사 적응, Pelvis Offset의 구현을 심층 분석합니다.
Foot IK 파이프라인
발이 지면에 정확히 맞닿기 위한 전체 처리 흐름
LineTrace 지면 감지
발 위치에서 수직 LineTrace로 지면 높이와 법선을 구하는 방법
// Foot IK용 LineTrace
FFootIKData UMyAnimInstance::TraceFootIK(FName FootBone, float TraceDistance)
{
FFootIKData Result;
USkeletalMeshComponent* Mesh = GetSkelMeshComponent();
if (!Mesh) return Result;
// 현재 발 위치 (Component Space → World)
FVector FootLocation = Mesh->GetBoneLocation(FootBone);
// 수직 LineTrace
FVector TraceStart = FootLocation + FVector(0, 0, TraceDistance);
FVector TraceEnd = FootLocation - FVector(0, 0, TraceDistance);
FHitResult Hit;
FCollisionQueryParams Params;
Params.AddIgnoredActor(TryGetPawnOwner());
bool bHit = GetWorld()->LineTraceSingleByChannel(
Hit, TraceStart, TraceEnd,
ECC_Visibility, Params);
if (bHit)
{
// 지면 높이 오프셋 계산
float FloorZ = Hit.ImpactPoint.Z;
float FootZ = Mesh->GetComponentLocation().Z;
Result.LocationOffset = FVector(0, 0, FloorZ - FootZ);
// 지면 법선에서 발 회전 계산
FVector Normal = Hit.ImpactNormal;
FRotator FloorRotation = FRotationMatrix::MakeFromZX(
Normal, Mesh->GetForwardVector()).Rotator();
Result.RotationOffset = FloorRotation;
Result.bIsValid = true;
}
return Result;
}
// 매 프레임 양발 트레이스
void UMyAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
Super::NativeUpdateAnimation(DeltaSeconds);
LeftFootIK = TraceFootIK(FName("foot_l"), 50.f);
RightFootIK = TraceFootIK(FName("foot_r"), 50.f);
// 보간으로 부드러운 전환
LeftFootIK.LocationOffset = FMath::VInterpTo(
PrevLeftOffset, LeftFootIK.LocationOffset,
DeltaSeconds, InterpSpeed);
}
매 프레임 양발에 대해 LineTrace를 수행하면 성능에 영향을 줄 수 있습니다. 비동기 트레이스(AsyncLineTraceByChannel)를 사용하거나, 격프레임 업데이트로 트레이스 빈도를 줄이세요. 또한 TraceChannel을 전용으로 설정하면 불필요한 충돌 검사를 줄일 수 있습니다.
Pelvis Offset과 경사 적응
골반 높이 조정으로 양발 높이 차이를 해소하는 기법
양발의 지면 높이가 다를 때, IK만으로는 한쪽 다리가 과도하게 늘어나거나 축소됩니다. Pelvis Offset으로 골반을 아래로 내리면 양 다리 모두 자연스러운 굽힘을 유지합니다.
// Pelvis Offset 계산
void UMyAnimInstance::CalculatePelvisOffset(float DeltaSeconds)
{
if (!LeftFootIK.bIsValid || !RightFootIK.bIsValid)
{
PelvisOffset = FMath::FInterpTo(PelvisOffset, 0.f, DeltaSeconds, 10.f);
return;
}
// 두 발 중 더 낮은 쪽의 오프셋
float LeftZ = LeftFootIK.LocationOffset.Z;
float RightZ = RightFootIK.LocationOffset.Z;
// 골반은 더 낮은 발에 맞춰 내림 (음수 값)
float TargetPelvisOffset = FMath::Min(LeftZ, RightZ);
// 최대 오프셋 제한 (다리가 너무 접히는 것 방지)
TargetPelvisOffset = FMath::Clamp(TargetPelvisOffset, -MaxPelvisOffset, 0.f);
// 부드러운 보간
PelvisOffset = FMath::FInterpTo(
PelvisOffset, TargetPelvisOffset, DeltaSeconds, PelvisInterpSpeed);
}
// Control Rig에서 적용
// pelvis 본 Z 위치에 PelvisOffset 추가
// 각 발의 IK Goal = 원래 발 위치 + FootOffset - PelvisOffset
캐릭터가 이동 중일 때 Foot IK를 전체 적용하면 발이 미끄러지는 문제가 발생합니다. 이동 속도에 따라 IK Alpha를 줄이는 것이 일반적입니다. 서 있을 때 Alpha=1.0, 걸을 때 0.5, 달릴 때 0.0으로 설정하면 이동 중에는 원래 애니메이션이 사용됩니다.
UE5 Foot Placement 노드
UE5 내장 Foot Placement 시스템 활용
UE5.1+에서는 Foot Placement AnimGraph 노드가 내장되어 있습니다. LineTrace, Pelvis Offset, 발 회전 보정을 한 번에 처리하는 올인원 솔루션입니다.
| 설정 | 설명 |
|---|---|
| Pelvis Settings | 골반 오프셋 최대값, 보간 속도, 최대 압축/확장 비율 |
| Foot Settings | 발별 트레이스 거리, 회전 보정, 블렌딩 알파 |
| Plant Settings | 발이 지면에 고정(Plant)되는 조건과 잠금(Lock) 설정 |
| Interpolation | 위치/회전 보간 속도, Unplant 시 해제 속도 |
UE5.4+의 Motion Matching과 Foot Placement를 결합하면, Motion Matching이 자연스러운 이동 애니메이션을 제공하고, Foot Placement가 지형에 맞는 발 배치를 보정합니다. Lyra 및 최신 Epic 샘플에서 이 조합을 표준으로 사용합니다.
핵심 요약
- Foot IK 파이프라인: LineTrace → 지면 높이 → Pelvis Offset → Foot IK → 발 회전 보정
- 수직 LineTrace로 발 아래 지면의 높이와 법선을 구하고, 발 위치/회전을 보정한다.
- Pelvis Offset으로 골반을 낮은 발에 맞춰 내려 양 다리의 자연스러운 굽힘을 유지한다.
- 이동 속도에 따라 IK Alpha를 감소시켜 이동 중 발 미끄러짐을 방지한다.
- UE5의 내장 Foot Placement 노드는 트레이스, 골반 조정, 발 잠금을 올인원으로 처리한다.
도전 과제
배운 내용을 직접 실습해보세요
AnimBP에서 각 발(foot_l, foot_r)에 대해 Line Trace(발 위치에서 아래 방향)를 수행하세요. 히트 결과의 Z 오프셋을 계산하고, Two Bone IK로 발을 지면에 정확히 착지시키세요. Interp To로 보간하여 부드럽게 적용하세요.
양발의 높이 차이에 따라 골반(pelvis)을 아래로 내리는 Pelvis Offset을 계산하세요. 두 발 중 더 낮은 위치에 맞춰 골반을 조정하고, 나머지 발은 IK로 지면에 맞추는 전체 Foot Placement 시스템을 완성하세요.
경사면에서 발바닥이 지면 노멀에 맞게 회전하는 Foot Rotation 시스템을 추가하세요. 계단에서의 발 배치, 이동 중 Foot IK 활성화/비활성화 전환, Control Rig 기반 Foot IK로의 마이그레이션까지 프로덕션 레벨 시스템을 구축하세요.