2026. 4. 20. 19:23ㆍUnreal
필수 구현 기능
C++ Pawn 클래스 및 컴포넌트 구성
- [ ] Pawn 클래스 생성: Pawn을 상속받는 새로운 C++ 클래스를 생성합니다.
- [ ] 컴포넌트 추가: 아래 컴포넌트들을 Pawn 클래스에 추가합니다.
- CapsuleComponent (또는 Box/Sphere 중 택 1)
- SkeletalMeshComponent
- SpringArmComponent
- CameraComponent
- [ ] 계층 구조 설정: 충돌 컴포넌트를 RootComponent로 설정하고, 나머지 컴포넌트들을 부착합니다.
- [ ] DefaultPawn 설정: GameMode 클래스에서 DefaultPawnClass를 본인이 만든 Pawn으로 지정합니다.
- [ ] Physics 설정: 루트 충돌체 및 Mesh의 Simulate Physics를 false로 설정합니다. (물리 대신 코드로 직접 제어)
Enhanced Input 매핑 & 바인딩
- [ ] 입력 액션(IA) 생성: 아래 두 가지 액션을 생성합니다. (타입: Vector2D)
- IA_Move (WASD 이동용)
- IA_Look (마우스 회전용)
- [ ] IMC 매핑: 생성한 액션들을 Input Mapping Context에 등록하고 키를 할당합니다.
- [ ] 액션 바인딩: SetupPlayerInputComponent()에서 입력 처리 함수와 액션들을 바인딩합니다.
이동 및 회전 로직 구현
- [ ] 프레임 독립성: DeltaTime을 사용하여 프레임 속도와 관계없이 일정한 속도로 움직이도록 구현합니다.
- [ ] 이동 구현: AddActorLocalOffset() 등을 활용해 WASD 입력에 따라 Pawn이 움직이도록 작성합니다.
- 이동 방향은 Pawn의 Forward/Right 벡터를 기준으로 결정됩니다.
- [ ] 회전 구현: AddActorLocalRotation() 등을 활용해 마우스 입력에 따라 회전하도록 작성합니다.
- 마우스 입력값으로 Yaw와 Pitch를 직접 계산하여 구현합니다.
- ⚠️ 주의: AddControllerYawInput(), AddControllerPitchInput() 등 엔진 기본 제공 함수는 사용하지 않습니다.
- [ ] 제한 사항: 평면 상에서의 이동과 회전만 처리하며, 중력이나 낙하 효과는 고려하지 않습니다.
C++ Pawn 클래스 생성 및 컴포넌트 구현
컴포넌트 추가
Pawn 클래스를 생성하고 컴포넌트를 구현했다.
우선 MyPawn.h 파일에 클래스 전방선언과 필수 기능 컴포넌트를 선언했다.


cpp 파일 - 생성자 부분에 구현

여기서 포인트는
카메라 컴포넌트는 캡슐 컴포넌트가 아니라 "스프링 암"컴포넌트에 붙이는 것이다.
계층 구조 설정 : 충돌 컴포넌트를 Root Component로 설정하고, 나머지 컴포넌트들을 부착
위에서 cpp 파일에서 구현 완료함.
DefaultPawn 설정 : GameMode 클래스에서 DefaultPawnClass를 본인이 만든 Pawn으로 지정

GameMode 클래스를 생성 후 생성자에
DefaultPawnClass = AMyPawn::StaticClass() 를 입력하면 자동으로 Player Start 부분에 스폰된다.
그 후 게임모드에 다음과 같이 설정한다.

Physics 설정
루트 충돌체 및 Mesh의 Simulate Physics를 false로 설정한다.
이때 사용할 함수는 다음과 같다.
SetSimulatePhysics()
이 함수를 생성자 부분에 호출해주면 된다.

여기까지 1번 기능을 구현했을 때 실행 결과는 다음과 같다.

Enhanced Input 매핑 & 바인딩
입력 액션(IA) 생성
두 가지의 액션을 생성해야 한다.
IA_Move (WASD 이동용)
IA_Look (마우스 회전용)
IA_Move

IA_Look
Move와 같이 설정하면 된다.
IMC 매핑
생성한 액션들을 Input Mapping Context에 등록한다.


위에서부터 Move, Look을 순서대로 매핑했다.
Look에서 Y축을 반전시키는 것도 잊지 않는다.
액션 바인딩
SetupPlayerInputComponent()에서 입력 처리 함수와 액션들을 바인딩한다.

Move 함수와 Look 함수를 생성해준다.

SetupPlayerInputComponent에 바인딩 로직을 구현한다.
이동 구현
DeltaTime을 곱해 프레임률과 무관하게 동일한 속도를 보장하고,
GetActorForwardVector()와 GetActorRightVector()를 기준 방향으로 삼아서 Pawn이 바라보는 방향을 기준으로 이동하게 한다.

GetSafeNormal()은 W와 D를 동시에 입력 시(대각선 이동) 벡터의 크기가 √2 ≈ 1.41이 된다. 정규화 없이는 대각선 이동이 40%정도 더 빠르기 때문에 안전하게 GetSafeNormal을 이용해서 처리해준다.
회전 구현
회전은 Yaw(좌우)와 Pitch(상하)를 분리해서 구현한다.
좌우는 Pawn 전체를 회전시키고, Pitch는 SpringArm에만 적용해 캐릭터가 앞으로 쓰러지는 것 처럼 보이는 것을 방지한다.
Pawn 전체 회전 -> AddActorLocalRotation()
SpringArm만 회전 -> SetRelativeRotation()
AMyPawn::Tick()

CurrentPitch를 이용해서 관리한 이유는 매 프레임을 AddActorLocalRotation으로 누적하면 clamp적용이 어렵고 짐벌락 문제가 생길 수 있다.
멤버 변수 CurrentPitch에 누적값을 보관하고 SetRelativeRotation으로 절대값을 세팅하는 방식이 훨씬 안전해서 이렇게 작성했다.
트러블 슈팅 / 핵심 정리
1. 카메라 회전이 전혀 안 됨
원인 : SpringArm->bUsePawnControlRotation = true 상태에서 Controller회전이 매 프레임 덮어씌워짐
해결 : true -> false로 변경
2. 키를 떼도 계속 이동
원인 : ETriggerEvent::Completed 바인딩을 누락해 계속 입력되어 있는 상태
해결 : Move함수를 Completed에도 바인딩해서 누르지 않을 때는 종료되도록 함
3. 대각선이 직선보다 빠름
원인 : 벡터 합산 시 크기가 √2배가 됨
해결 : GetSafeNormal() 함수로 정규화
4. 회전 감도가 너무 낮음(아예 안 움직이는 것 처럼 보임)
원인 : LookSensitivity = 1.f에 DeltaTime까지 곱하면 실제값이 매우 작아짐
해결 : 에디터에서 1 -> 50으로 값을 조정
'Unreal' 카테고리의 다른 글
| < UE5 > 레벨 진행 시스템 - GameStateClass (1) | 2026.04.28 |
|---|---|
| < 언리얼 C++ > 6자유도 비행체 + 중력 / 낙하 + 에어 컨트롤 구현 (0) | 2026.04.22 |
| 언리얼 엔진 애니메이션 블루프린트 정리 (0) | 2026.04.16 |
| 리플렉션 / UBT / UHT / CDO 정리 (0) | 2026.04.15 |
| < 언리얼 C++ > 캐릭터 이동 구현 (0) | 2026.04.14 |