컨텐츠 검색
[UE5 C++] C++로 캐릭터 움직임 구현과 트러블슈팅: Input Action부터 Foot IK, 그리고 '거대화 버그' 해결까지

2026. 1. 14. 21:39Unreal Engine/개념

1. 오늘의 학습 목표

오늘은 언리얼 엔진 5의 향상된 입력 시스템을 C++ 코드로 제어하여 캐릭터의 기본 움직임(이동, 점프, 전력 질주)을 구현해보았습니다.

그 과정 속에서 발생한 문제 해결 내용을 담았습니다.

  • 외부 에셋을 활용해 BlendSpace와 State Machine을 구성하고, 루트 모션(Root Motion) 문제를 해결했습니다.
  • Control Rig가 없는 외부 에셋 캐릭터에 직접 Control Rig를 제작하여, 경사면에서도 발이 지면에 자연스럽게 닿도록 만들었습니다.
  • 애니메이션 재생 시 캐릭터의 크기가 비정상적으로 변하는 문제를 분석하고 해결했습니다.

2. C++ 기반 Enhanced Input 시스템 구축

가장 먼저 캐릭터의 입력을 처리하기 위해 Input Action(IA)과 Input Mapping Context(IMC)를 설정했습니다.

  • 에셋 구성:
    • IA_Move, IA_Look: Axis2D 타입 (방향 제어)
    • IA_Jump, IA_Sprint: bool 타입 (상태 제어)
    • IMC_Character: 위의 액션들을 키보드/마우스 입력과 매핑
  • C++ 구현:
    • PlayerController 클래스에서 리플렉션 시스템을 통해 IA와 IMC를 등록했습니다.
    • Character 클래스의 SetupPlayerInputComponent 함수를 오버라이드하여, 각 IA와 실제 동작 함수를 바인딩했습니다.
    • 달리기(Sprint) 로직: 걷기 속도(NormalSpeed, 600.0f)에 달리기 계수(SprintSpeedMultiplier, 1.7f)를 곱하여 SprintSpeed를 계산하는 방식으로 구현했습니다.

이 과정을 통해 WASD 이동과 Shift 달리기, Space 점프가 정상적으로 로그를 출력하며 작동하는 것을 확인했습니다.

 


3. 애니메이션 블루프린트와 루트 모션 제어

외부에서 가져온 애니메이션 시퀀스를 활용해 Walk/Run BlendSpace를 제작했습니다. 속도가 0일 때는 Idle, 600일 때는 Walk, 그 이상일 때는 Run으로 전환되도록 설정했습니다.

  • 문제 발생: 외부 에셋의 걷기/달리기 애니메이션에 루트 모션(Root Motion) 값이 포함되어 있어, 캐릭터 캡슐은 제자리에 있는데 메쉬만 앞으로 나가는 현상이 발생했습니다.
  • 해결: 애니메이션 시퀀스의 Asset Details 패널에서 Enable Root Motion을 끄고 Force Root Lock을 활성화했습니다. 이를 통해 애니메이션이 제자리에서 재생되도록 고정하고, 실제 이동은 코드의 속도 값으로 제어하게 만들었습니다.

 

설정 전 설정 후

 


4. Control Rig를 활용한 Foot IK 구현

외부 에셋이라 Control Rig가 없어, 학습용 강의와 다르게 직접 Control Rig를 생성하여 발 위치 보정(Foot IK) 기능을 구현했습니다.

[구현한 5단계 로직]

Step 1 (Trace): FootTrace라는 커스텀 함수를 만들어 발 위치에서 지면으로 Sphere Trace를 발사해 바닥 위치(Hit Location)를 찾아냅니다.


 

Step 2 (Interpolate): 계산된 목표 위치로 발이 순간 이동하지 않도록 보간(Interpolate)하여 부드럽게 움직이게 합니다.


 

Step 3 (Pelvis Adjustment):양발 중 더 낮은 위치의 값을 골반(Pelvis) 높이에 적용합니다. 이를 통해 한쪽 발이 구덩이에 빠져도 다리가 찢어지지 않고 골반이 함께 내려가도록 처리했습니다.


 

Step 4 (Offset Application): 계산된 Z축 보정값을 실제 발과 골반 뼈에 Additive Local 모드로 적용합니다.


 

Step 5 (Full Body IK): 최종적으로 Full Body IK 노드를 사용하여, 이동된 가상의 발 위치(Effector)에 맞춰 실제 다리 관절이 자연스럽게 굽혀지도록 설정했습니다.

 


5. 트러블 슈팅: 착지 시 캐릭터 거대화 버그 해결

Foot IK까지 적용한 후, 점프하고 착지(Land)할 때마다 캐릭터가 거인처럼 커졌다가 줄어드는 치명적인 버그가 발생했습니다.

  • 원인 분석:
    • 처음에는 Control Rig의 문제로 의심했으나, 연결을 해제해도 동일한 현상이 발생했습니다.
    • 로그를 확인한 결과 Trying to play a non-additive animation 'AS_Land' into a pose that is expected to be additive라는 경고를 발견했습니다.
    • 애니메이션 블루프린트에서는 Apply Additive 노드를 사용해 착지 모션을 더하고 있었으나, 정작 AS_Land 애니메이션 파일은 No Additive로 설정되어 있었습니다.
    • 이로 인해 기본 크기(1) + 애니메이션 크기(1) = 2배(Scale 2)가 되는 연산 오류가 발생한 것이었습니다.
  • 해결:
    • AS_Land 애니메이션의 Additive Anim Type을 Local Space로 변경했습니다.
    • Base Pose Type을 Selected animation frame으로 설정하고, 기준이 되는 Idle 애니메이션을 지정하여 문제를 완벽하게 해결했습니다.

 


6. 오늘 배운 점 요약

  • C++와 Enhanced Input: 단순히 입력을 받는 것을 넘어, SetupPlayerInputComponent를 통해 액션과 함수를 바인딩하는 전체적인 파이프라인을 이해했습니다.
  • 루트 모션의 제어: 애니메이션 자체에 이동 값이 포함된 경우 Force Root Lock을 통해 제자리 애니메이션으로 변환할 수 있음을 배웠습니다.
  • Foot IK의 원리: Control Rig 없이 시작했지만, 직접 Trace와 Offset 로직을 짜보며 IK가 단순히 발을 땅에 붙이는 것이 아니라 골반의 높이 조절이 동반되어야 함을 깊이 이해했습니다.
  • Additive Animation의 중요성: 애니메이션 합성 시 '더하기(Additive)' 속성이 맞지 않으면 스케일이나 회전값이 중첩되어 의도치 않은 버그가 발생할 수 있음을 깨달았습니다. 로그(Log) 확인의 중요성을 다시 한번 느꼈습니다.