언리얼 Character와 시점 구현 정리 (Enhanced Input, Control Rotation, BackView/QuarterView)
언리얼 Character 학습 노트. 강의 5.1~5.6 개념만. Enhanced Input 구조, 회전 옵션 관계, 시점 전환 헷갈릴 때 다시 보기.
Enhanced Input System (왜 쓰는가)
구 입력 시스템은 설정 후 게임 로직에서 입력 값을 처리 → 플레이 중 키 변경 대응 불가. Enhanced Input은 플레이 중에도 입력 설정 변경 가능.
구성 요소(데이터를 함수에 매핑하는 체계):
- InputAction: 입력을 처리하는 주체. Value Type 지정(Vector2D 등)
- Modifier: 들어온 입력을 재가공(AD/WS를 X/Y축으로, 값 반전 등)
- Trigger: 입력 이벤트 활성화 조건(눌렀을 때/일정 이상 눌러야/축 이동 등)
- InputMappingContext(IMC): 어떤 키가 어떤 액션에 매핑되는지. 플랫폼별로 따로 둘 수 있음
- InputConfig: 액션들을 모아둔 DataAsset
플러그인 추가 시 .uproject 수정, 모듈 추가 시 해당 모듈의 .Build.cs 수정. (EnhancedInput 모듈을 ShooterX에 추가하려면 ShooterX.Build.cs)
Enhanced Input 연결 흐름
세 단계로 외워두면 됨:
- BeginPlay에서 PlayerController의 EnhancedInputLocalPlayerSubsystem을 얻어 AddMappingContext(IMC, 우선순위)
- SetupPlayerInputComponent에서 PlayerInputComponent를 UEnhancedInputComponent로 캐스팅
- BindAction(액션, ETriggerEvent::Triggered, this, 함수)로 함수 바인드
함정: 블루프린트에서 Override Input Component Class를 EnhancedInputComponent로 지정해야 캐스팅이 성공. 안 하면 캐스팅 실패로 입력이 안 먹음. 입력 처리 함수는 const FInputActionValue& 인자를 받고 Get
ACharacter vs APawn
ACharacter는 APawn을 상속한, 인간형 폰을 효과적으로 구현하기 위한 클래스. Capsule/SkeletalMesh는 동일하지만 CharacterMovementComponent를 쓰는 게 핵심 차이.
CharacterMovementComponent vs FloatingPawnMovement:
- 점프 등 중력 영향 받는 움직임 제공
- 걷기 외 기어가기/날기/수영 등 MovementMode 제공
- 멀티플레이에서 캐릭터 간 움직임 자동 동기화
MovementMode(EMovementMode): None(이동 끄기), Walking, Falling 등. MaxWalkSpeed(걷기 속도), JumpZVelocity(점프 속도).
설계 패턴: 캐릭터는 이후 PlayerCharacter/NonPlayerCharacter로 갈리므로 공통 부모 SXCharacterBase를 먼저 만들어둠. 캡슐 크기, 메시 위치/회전 보정, 무브먼트 기본값을 여기에.
Control Rotation: 플레이어의 의지 vs 폰의 물리
핵심 개념 구분:
- 컨트롤 로테이션: 플레이어 컨트롤러가 관리. 물리 무시한 "플레이어의 의지"(어디를 보고 싶은가)
- 폰의 속도: 물리 제약이 반영된 "폰의 실제 상황"
확인 방법: 뷰포트 클릭 후 틸드(~) 키로 콘솔 진입, DisplayAll PlayerController ControlRotation 입력.
회전 동기화 속성 관계 (가장 자주 헷갈리는 부분)
Controller ↔ Pawn:
- bUseControllerRotationYaw(Pitch/Roll): true면 컨트롤 로테이션의 해당 축이 폰 회전에 즉시 동기화. Character는 기본 Yaw true
Pawn ↔ SpringArm:
- bUsePawnControlRotation: true면 폰(컨트롤) 회전에 스프링암이 연동. false면 폰이 회전해도 스프링암 고정(컷씬용)
- bInheritPitch/Yaw/Roll: 루트 컴포넌트 회전을 스프링암이 따라갈지
- bDoCollisionTest: 폰과 카메라 사이 벽 있으면 카메라를 폰 쪽으로 당김
Pawn ↔ Camera:
- bUsePawnControlRotation으로 결정되지만, 카메라가 스프링암 자식이면 스프링암을 따름
CharacterMovement 회전 옵션:
- RotationRate: 회전 속도
- bUseControllerDesiredRotation: 컨트롤 로테이션 방향으로 폰을 RotationRate 속도로 부드럽게 회전
- bOrientRotationToMovement: 이동 방향으로 폰을 RotationRate 속도로 회전
가장 중요한 함정: 폰 회전 옵션끼리 충돌하면 움직임이 망가짐. bUseControllerRotationYaw(true)와 bOrientRotationToMovement(true)를 동시에 켜면 안 됨. 차이는, 전자는 시선=캐릭터 회전이 항상 동기화, 후자는 이동 키를 눌러야 동기화.
마우스 감도: UE4의 InputYawScale 등은 UE5에서 deprecated. Look 함수 인자 값에 계수를 곱해서 조절.
BackView 구현 핵심
GTA 같은 백뷰. 카메라가 회전한 뒤 그 방향으로 이동.
설정: bUseControllerRotationYaw true, 스프링암 bUsePawnControlRotation true(컨트롤 로테이션→스프링암 동기화), bInheritPitch/Yaw true, bDoCollisionTest true.
함정: bUsePawnControlRotation이 true라 컨트롤 로테이션이 결국 스프링암(=카메라) 회전이 됨. 그래서 SetRelativeRotation은 무의미해짐.
이동 방향 도출: 컨트롤 로테이션이 카메라 방향이므로, 컨트롤 로테이션의 Yaw만으로(Pitch는 비행기 아니니 무시) FRotationMatrix 생성 → X축이 Forward, Y축이 Right. 그 방향으로 AddMovementInput.
이동만 되고 회전이 안 되면 어색 → bOrientRotationToMovement true + RotationRate 지정으로 이동 방향으로 부드럽게 회전(이때 bUseControllerRotationYaw는 false로).
QuarterView 구현 핵심
설정: 스프링암 bUsePawnControlRotation false(폰 회전과 카메라 분리), TargetArmLength 길게, 위에서 내려보는 회전(-45도), bInherit 전부 false, bDoCollisionTest false.
이동 방향 도출이 BackView와 반대:
- BackView: 컨트롤 로테이션(=카메라)으로 회전 행렬 → 이동 방향
- QuarterView: 입력 X/Y로 방향 벡터 생성 → 이걸 캐릭터의 의지로 간주 → MakeFromX로 회전 행렬 만들어 컨트롤 로테이션에 대입
MakeFromX/Y/Z: 벡터 하나로 회전 행렬 생성. QuarterView는 입력 합산 벡터와 캐릭터 시선(X축)이 같아야 해서 MakeFromX 사용.
45도 단위로 끊겨 회전하면 → bUseControllerDesiredRotation true로 컨트롤 회전 방향으로 부드럽게 회전(이때 bUseControllerRotationYaw, bOrientRotationToMovement는 false).
함수 호출 순서 (중요)
입력 이벤트 함수 → 액터 Tick → 애니메이션 이벤트 함수.
이유: 플레이어 의지(입력)를 먼저 확인 → Tick에서 그에 대응할 최종 행동 결정 → 결과 보고 애니메이션 처리. QuarterView에서 입력은 변수에만 담고 실제 이동/회전은 Tick에서 처리하는 이유가 이 순서 때문.
함정: 입력 이벤트 함수는 그 입력이 있을 때만 매 프레임 호출됨. 입력 없으면 안 불림. 그래서 지속 처리가 필요한 로직을 입력 함수에만 두면 안 됨.
시점 전환 함정
BackView↔QuarterView 전환 시 회전 동기화 주체가 반대라 그냥 바꾸면 카메라가 튐.
- BackView: 컨트롤 로테이션 → 스프링암에 동기화
- QuarterView: 컨트롤 로테이션 ← 폰 회전에서 받아옴
그래서 전환 직전에 컨트롤 로테이션을 미리 맞춰줘야 함:
- BackView→QuarterView: 컨트롤 로테이션에 폰 회전(GetActorRotation) 세팅
- QuarterView→BackView: 컨트롤 로테이션에 스프링암 회전 세팅
부드러운 전환: 스프링암 길이/회전을 즉시 바꾸지 말고 목표값(DestArmLength 등)을 두고 Tick에서 InterpTo로 보간. float은 FInterpTo, FVector는 VInterpTo, FRotator는 RInterpTo. InterpTo는 등속으로 목표까지 가다 도달하면 멈춤.
TPS 시점 설정 정리
최종 프로젝트는 TPS. 생성자에서 한 번에 설정:
- bUseControllerRotationYaw true, bOrientRotationToMovement true(이동 방향으로 캐릭터 회전), RotationRate/MaxWalkSpeed 지정
- 스프링암 bUsePawnControlRotation true, bInheritPitch/Yaw true, bDoCollisionTest true, 약간 우측 상단 오프셋(어깨너머 시점)
- 카메라 bUsePawnControlRotation false(스프링암 자식이라 스프링암 따름)
- 이동은 컨트롤 로테이션 Yaw로 회전 행렬 만들어 Forward/Right 도출(BackView 방식과 동일)
'학습 > Unreal' 카테고리의 다른 글
| 언리얼 충돌 시스템 핵심 정리 (콜리전 프리셋, 트레이싱) (0) | 2026.05.16 |
|---|---|
| 언리얼 애니메이션 시스템 정리 (AnimInstance, State Machine, Montage, Notify) (0) | 2026.05.06 |
| 언리얼 Pawn과 게임플레이 프레임워크 정리 (GameMode, Controller, 입력, 애니메이션) (0) | 2026.05.01 |
| 언리얼 Actor와 컴포넌트 구조 정리 (컴포지션, UPROPERTY, 이벤트 함수, Movement) (0) | 2026.04.30 |
| 언리얼 실무 도구 정리 (Interface, Delegate, FString, 컨테이너) (0) | 2026.04.28 |
