프로젝트 회고 / / 2025. 12. 2. 23:03

[UE5 액션] 루트 모션 기반 자연스러운 대시 구현 Motion Warping

반응형

🎮 구현 목표

액션 게임의 핵심인 빠르고 역동적인 이동을 구현하되, 애니메이션과 자연스럽게 어우러지는 대시 시스템을 만들고자 했습니다. 특히 적에게 빠르게 접근하는 "돌진형 스킬"의 자연스러운 연출이 목표였습니다.

 

🚨 문제 상황

대시를 구현하기 위해 세 가지 방법을 테스트했습니다.

  • AddMovementInput()의 Scale을 높이는 방법
  • LaunchCharater()를 사용하는 방법
  • Tick()에서 MaxWalkSpeed를 조작하는 방법

세 가지 방법 모두 결과적으로:

  • ❌ 캐릭터가 순간이동하는 듯한 부자연스러운 느낌
  • 캐릭터가 미끄러지는 현상
  • ❌ 이동 거리와 애니메이션 거리의 불일치로 인한 이질감

'이동'과 '애니메이션'이 완전히 분리된 것이 문제의 핵심이었습니다.

 

 

💭 해결 방법

Youtube로 다른 사람들이 어떻게 대시를 구현했는지 보기 위해 자료조사를 하다가 우연히 언리얼 서밋을 보게 되었는데, 여기서 모션 워핑의 존재를 알게되었습니다.

 

Youtube

영상을 보다 대시 시연 과정이 나오는 것을 보고 "아! 이거다!" 싶었습니다.

Motion Warping의 핵심 개념:

애니메이션을 런타임에 동적으로 변형하여 목표 지점까지 도달하게 만드는 기술입니다.

  • 애니메이션이 원래 100cm 이동한다면 → 목표가 200cm 떨어져 있으면 애니메이션을 2배 늘림
  • Root Motion을 유지하면서 거리를 조정하므로 발이 땅에서 미끄러지지 않음
  • 이동 거리와 애니메이션이 완벽하게 일치

즉, 제가 찾던 애니메이션과 이동을 하나로 묶는 방법이었습니다.

 

 

🔧 구현

1차 시도: Blueprint로 프로토타입 검증

본격적인 C++ 작업 전에 Motion Warping 플러그인을 활성화하고, 블루프린트로 빠르게 프로토타입을 만들어 개념을 검증했습니다.
영상을 참고하여 저에게 필요한 부분만 자료조사를 하며 블루프린트로 로직을 먼저 완성시켜나갔습니다.

 

검증 항목:

  • ✅ Motion Warping Component 동작 확인
  • ✅ Warp Target 설정 방식 이해
  • ✅ 애니메이션 에디터에서 Warp Point 설정 방법 습득

결과: "실제로 작동한다!"는 확신을 얻고 C++ 구현으로 전환

 

2차 시도: C++ 구현

void ASoulPlayerCharacter::MotionWarpingDashSlash()
{
    Super::MotionWarpingDashSlash();

    check(MotionWarpingComponent);
    LOG(">>> Motion Warping Dash Slash <<<")
    GetCharacterMovement()->SetMovementMode(EMovementMode::MOVE_Flying);
    FVector Start = MotionWarpArrowComponent->GetComponentLocation();
    FVector Forward = MotionWarpArrowComponent->GetForwardVector();
    FVector End = Start + (Forward * 2000.0f);

    FHitResult OutHit;
    TArray<AActor*> ActorToIgnore;
    ActorToIgnore.Add(this);

    EDrawDebugTrace::Type TraceType = EDrawDebugTrace::None;

    const bool bHit = UKismetSystemLibrary::LineTraceSingle(
        GetWorld(),
        Start,
        End,
        UEngineTypes::ConvertToTraceType(ECC_Visibility),
        false,
        ActorToIgnore,
        TraceType,
        OutHit,
        true
    );

    if (bHit)
    {
        MotionWarpingComponent->AddOrUpdateWarpTargetFromLocation(TEXT("DashSlash"), OutHit.Location);
    }
}

구현 핵심:

  1. Flying Mode: 대시 중 지형의 영향을 받지 않도록 설정
  2. 동적 목표 설정: 레이캐스트로 탐지한 지점을 실시간으로 Warp Target에 적용
  3. Warp Point 이름 매칭: 애니메이션 에디터에서 설정한 "DashSlash"와 코드의 이름 일치

 

대시 애니메이션의 특정 구간에 Motion Warping NotifyState를 추가:

  • Warp Target Name: "DashSlash"
  • Warp Translation: Forward 축 활성화
  • Warp Rotation: 목표 방향으로 캐릭터 회전

이렇게 하면 애니메이션 재생 중 실시간으로 Root Motion이 목표 지점까지 늘어납니다.

 

✅ 결과

애니메이션과 완벽하게 동기화된 역동적인 대시 완성

Launch Character(Before)

이미지

미끄러짐이 있음

Motion Warping(After)

이미지

이동이 깔끔하게 떨어짐

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유