UE5 Enhanced Input 탑다운 카메라 이동
프로퍼티가 null이면 조용히 레거시 입력으로 빠진다
블루프린트에서 아무것도 할당하지 않아도 WASD·Space가 동작하는 입력 구조를 코드로 만들었다. UObject 데이터 에셋에는 초기화 지점이 없다는 것과, 경고만 남기고 넘어가는 deprecated 함정.
VOIDBaseCharacter에 탑다운 카메라를 붙이고, WASD 이동을 카메라 시점 기준으로, Space를 점프로 연결했다. 레거시 입력을 걷어내고 Enhanced Input System(키 입력을 InputAction·InputMappingContext 에셋으로 관리하는 UE5의 입력 시스템)만 쓰는 것이 목표였다. 이 글에서는 그 구현과, 그 뒤에 붙은 트러블슈팅 네 건을 이야기하려 한다 — 구현은 스프링암·카메라 구성과 매핑 컨텍스트를 코드에서 자동 생성하는 구조, 트러블슈팅은 “경고만 뜨고 입력이 조용히 레거시 경로로 빠지는” 문제가 중심이다.
작업 목표
구현 내용
1. 카메라 컴포넌트 추가 (VOIDBaseCharacter)
카메라는 SpringArmComponent(캐릭터와 카메라 사이 거리를 유지해 주는 지지대 컴포넌트)와 CameraComponent 조합으로 구성했다. CameraBoom은 RootComponent에 부착하고 길이 800, Pitch -60도를 줘서 탑다운 각도를 만들었다. FollowCamera는 CameraBoom 소켓에 붙이고 폰 컨트롤 회전을 꺼서, 카메라가 캐릭터를 따라다니되 회전하지는 않는 고정 탑다운 시점이 됐다.
2. Enhanced Input 클래스 구조
| 클래스 | 부모 | 역할 |
|---|---|---|
USC_MoveAction | UInputAction | ValueType = Axis2D (Vector2D), WASD 이동용 |
USC_JumpAction | UInputAction | ValueType = Boolean, Space 점프용 |
USC_InputMappingContext | UInputMappingContext | 두 Action을 내부에 자동 생성, WASD+Space 매핑 자동 구성 |
3. WASD 매핑 구성 (USC_InputMappingContext::BuildDefaultMappings)
Axis2D 하나로 WASD를 전부 받으려면 W/S 입력을 Y축으로 돌려줘야 해서 SwizzleAxis(입력 축 순서를 바꿔주는 모디파이어)를 썼다.
| 키 | 방향 | 모디파이어 |
|---|---|---|
| W | 앞 (Y +1) | SwizzleAxis YXZ |
| S | 뒤 (Y -1) | SwizzleAxis YXZ + Negate |
| D | 오른쪽 (X +1) | 없음 |
| A | 왼쪽 (X -1) | Negate |
| Space | 점프 | 없음 |
4. 카메라 기준 이동 로직
1
2
3
4
5
6
const FRotator CameraYaw(0.0f, CameraBoom->GetComponentRotation().Yaw, 0.0f);
const FVector ForwardDir = FRotationMatrix(CameraYaw).GetUnitAxis(EAxis::X);
const FVector RightDir = FRotationMatrix(CameraYaw).GetUnitAxis(EAxis::Y);
AddMovementInput(ForwardDir, Input.Y);
AddMovementInput(RightDir, Input.X);
카메라 회전에서 Yaw만 뽑아 수평 이동 방향으로 변환했다. 이렇게 하면 나중에 카메라가 회전해도 이동 방향이 자동으로 따라온다.
트러블슈팅
1 — 입력이 아무 반응이 없다
원인: 실제로 스폰되는 클래스는 VOIDBaseCharacter인데, 입력 코드는 VOIDPlayerCharacter에 작성돼 있었다.
증상: 빌드도 되고 에러도 없는데 키를 눌러도 아무 일이 없었다.
해결: 코드를 실제 스폰되는 클래스로 옮겼다. 이후로는 입력 작업 전에 어떤 클래스가 스폰되는지부터 확인하는 순서로 굳혔다.
2 — 매핑이 에디터에도 안 보이고 런타임에도 안 먹는다
원인: USC_InputMappingContext는 UObject 기반 데이터 에셋이라 블루프린트의 Construction Script에 해당하는 자동 초기화 지점이 없다. BuildDefaultMappings()를 아무도 불러 주지 않았다.
증상: 에셋을 열어도 매핑 목록이 비어 있었고, 런타임에도 입력이 등록되지 않았다.
해결: PostLoad()(에셋 로드 시 호출)와 PostEditChangeProperty()(에디터에서 프로퍼티 변경 시 호출)를 오버라이드해 초기화가 자동으로 걸리게 했다.
1
2
3
4
5
6
7
8
9
10
11
12
13
void USC_InputMappingContext::PostLoad()
{
Super::PostLoad();
BuildDefaultMappings();
}
#if WITH_EDITOR
void USC_InputMappingContext::PostEditChangeProperty(FPropertyChangedEvent& e)
{
Super::PostEditChangeProperty(e);
BuildDefaultMappings();
}
#endif
3 — deprecated 경고가 계속 뜬다
원인: DefaultMappingContext와 MoveAction UPROPERTY를 블루프린트에서 수동 할당하지 않아 null이었다. Enhanced Input이 등록되지 않은 채 레거시 입력 경로로 조용히 빠지고 있었다.
증상: Axis and Action mappings are now deprecated, please use Enhanced Input Actions and Input Mapping Contexts instead. 경고가 반복 출력됐다.
해결: 생성자에서 CreateDefaultSubobject로 직접 생성해, 할당을 잊어도 null이 될 수 없게 만들었다.
1
2
// VOIDBaseCharacter 생성자
InputMappingContext = CreateDefaultSubobject<USC_InputMappingContext>(TEXT("InputMappingContext"));
4 — 설정 문제인지 확인
프로젝트 설정 쪽 원인을 배제하려고 입력 설정도 확인했다.
DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInputDefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent
설정은 이미 Enhanced Input으로 잡혀 있었다. 결국 문제는 설정이 아니라 코드 레벨의 null 참조였다.
최종 구조 요약
1
2
3
4
5
6
AVOIDBaseCharacter
├── USpringArmComponent (CameraBoom)
├── UCameraComponent (FollowCamera)
└── USC_InputMappingContext (InputMappingContext)
├── USC_MoveAction (MoveAction) — Axis2D, WASD 자동 매핑
└── USC_JumpAction (JumpAction) — Boolean, Space 자동 매핑
- 블루프린트에서 아무것도 할당하지 않아도 WASD 이동 + Space 점프 자동 동작
Build.cs에EnhancedInput모듈 추가 필요
핵심 요약 — UObject 기반 데이터 에셋에는 Construction Script가 없어서 초기화 코드를
PostLoad()·PostEditChangeProperty()에서 직접 호출해야 한다는 것, 그리고 Enhanced Input 관련 프로퍼티가 null이면 경고만 남기고 조용히 레거시 입력 경로로 빠진다는 것을 배웠다.