콘텐츠로 이동

UE5 Motion Warping 구현 완전 가이드

Motion Warping은 UE5에서 Root Motion 애니메이션을 런타임 타겟 위치/방향에 맞게 동적으로 변형하는 시스템입니다. 캐릭터가 장애물을 타거나, 정확히 목표물을 공격하거나, 지형에 맞게 착지하는 등의 동작을 정밀하게 제어합니다.

플러그인: MotionWarping 플러그인 활성화 필요


// 캐릭터 클래스에 컴포넌트 추가
UCLASS()
class AMyCharacter : public ACharacter
{
GENERATED_BODY()
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
TObjectPtr<UMotionWarpingComponent> MotionWarpingComponent;
public:
AMyCharacter();
};
AMyCharacter::AMyCharacter()
{
MotionWarpingComponent = CreateDefaultSubobject<UMotionWarpingComponent>(
TEXT("MotionWarpingComponent"));
}

Motion Warping은 애니메이션의 특정 구간에서 작동합니다.

애니메이션 에디터 설정:
1. 애니메이션 시퀀스 열기
2. Notifies 트랙에 AnimNotifyState_MotionWarping 추가
3. 워핑 구간 지정 (시작~종료 프레임)
4. Warp Target Name 설정 (예: "ClimbTarget")
5. Warp Point Anim Provider: Component Space (권장)

#include "MotionWarpingComponent.h"
void AMyCharacter::StartClimbing(const FHitResult& ClimbHit)
{
// 워프 타겟 위치 설정
FMotionWarpingTarget WarpTarget;
WarpTarget.Name = FName("ClimbTarget");
WarpTarget.Location = ClimbHit.Location;
WarpTarget.Rotation = FRotationMatrix::MakeFromX(ClimbHit.Normal * -1.f).Rotator();
MotionWarpingComponent->AddOrUpdateWarpTarget(WarpTarget);
// 클라이밍 몽타주 재생
PlayAnimMontage(ClimbMontage);
}
// 몽타주 종료 시 정리
void AMyCharacter::OnMontageEnded(UAnimMontage* Montage, bool bInterrupted)
{
if (Montage == ClimbMontage)
{
// 워프 타겟 제거
MotionWarpingComponent->RemoveWarpTarget(FName("ClimbTarget"));
}
}

// 근접 공격 시 적 방향으로 워핑
void AMyCharacter::PerformMeleeAttack(AActor* Target)
{
if (!Target) return;
// 공격 타겟 방향 계산
FVector TargetLocation = Target->GetActorLocation();
FVector ToTarget = (TargetLocation - GetActorLocation()).GetSafeNormal();
FRotator FaceTarget = ToTarget.Rotation();
FaceTarget.Pitch = 0.f;
// 워프 타겟: 적 앞 특정 거리
FMotionWarpingTarget AttackTarget;
AttackTarget.Name = FName("AttackTarget");
AttackTarget.Location = TargetLocation - ToTarget * 100.f; // 100cm 앞
AttackTarget.Rotation = FaceTarget;
MotionWarpingComponent->AddOrUpdateWarpTarget(AttackTarget);
// 공격 몽타주 재생
PlayAnimMontage(AttackMontage);
}

// 착지 위치를 동적으로 조정
void AMyCharacter::PredictLandingAndWarp()
{
// 착지 위치 예측
FVector LandingLocation;
FPredictProjectilePathParams PredictParams;
PredictParams.StartLocation = GetActorLocation();
PredictParams.LaunchVelocity = GetVelocity();
PredictParams.DrawDebugType = EDrawDebugTrace::None;
FPredictProjectilePathResult PredictResult;
if (UGameplayStatics::PredictProjectilePath(
this, PredictParams, PredictResult))
{
LandingLocation = PredictResult.HitResult.Location;
FMotionWarpingTarget LandTarget;
LandTarget.Name = FName("LandTarget");
LandTarget.Location = LandingLocation;
LandTarget.Rotation = GetActorRotation();
MotionWarpingComponent->AddOrUpdateWarpTarget(LandTarget);
}
}

// 위치와 회전 모두 워핑
FMotionWarpingTarget Target;
Target.Name = TEXT("MyTarget");
Target.Location = TargetPos;
Target.Rotation = TargetRot;
MotionWarpingComponent->AddOrUpdateWarpTarget(Target);
// Component 기반 워핑 (타겟이 이동할 때 자동 추적)
FMotionWarpingTargetByComponent ComponentTarget;
ComponentTarget.Name = TEXT("TrackingTarget");
ComponentTarget.Component = TargetActor->GetRootComponent();
ComponentTarget.BoneName = TEXT("Pelvis"); // 특정 본 추적
MotionWarpingComponent->AddOrUpdateWarpTargetFromComponent(
TEXT("TrackingTarget"),
TargetActor->GetRootComponent(),
NAME_None, true);

여러 Warp 구간을 하나의 몽타주에서 순차적으로 사용합니다.

AnimNotifyState_MotionWarping 설정:
- Warp Target Name: "GrabPoint1" (구간 1)
- Warp Target Name: "PullPoint" (구간 2)
- Warp Target Name: "LandPoint" (구간 3)
// 각 구간 타겟 미리 설정
void AMyCharacter::SetupVaultTargets(
FVector GrabPos, FVector LandPos)
{
MotionWarpingComponent->AddOrUpdateWarpTarget(
{"GrabPoint1", GrabPos, GrabRot});
MotionWarpingComponent->AddOrUpdateWarpTarget(
{"PullPoint", GrabPos + FVector(0,0,50), GrabRot});
MotionWarpingComponent->AddOrUpdateWarpTarget(
{"LandPoint", LandPos, LandRot});
PlayAnimMontage(VaultMontage);
}

// 에디터에서 워핑 디버그
// 콘솔 명령: MotionWarping.Debug 1
// C++에서 수동 디버그
void AMyCharacter::DrawWarpDebug()
{
#if WITH_EDITOR
for (const FMotionWarpingTarget& Target :
MotionWarpingComponent->GetWarpTargets())
{
DrawDebugSphere(GetWorld(), Target.Location, 30.f, 12,
FColor::Green, false, 2.f);
DrawDebugDirectionalArrow(GetWorld(),
Target.Location,
Target.Location + Target.Rotation.Vector() * 100.f,
20.f, FColor::Blue, false, 2.f);
}
#endif
}

  • Motion Warping = Root Motion 애니메이션을 타겟 위치에 맞게 변형
  • UMotionWarpingComponent를 캐릭터에 추가
  • 애니메이션에 AnimNotifyState_MotionWarping 구간 지정
  • AddOrUpdateWarpTarget()으로 런타임 타겟 설정
  • 벽 타기, 근접 공격, 착지 등 정밀한 위치 맞춤에 활용