Enhanced Input System 입력 매핑 구현하기
PlayerController, IMC, IA
PlayerController 이해하기
1️⃣ PlayerController란?
- PlayerController는 사용자가 키보드, 마우스, 게임패드 등에서 입력을 받으면, 그 입력을 해석하여 캐릭터나 다른 오브젝트에게 동작을 명령하는 핵심 클래스입니다.
- 언리얼 엔진의 중요한 철학 중 하나는 “플레이어 입력은 PlayerController에서 처리한다”는 것입니다. 이를 통해 입력 처리 로직과 실제 캐릭터의 동작 로직을 분리할 수 있어, 코드를 구조적으로 관리하기가 훨씬 수월해집니다.
- 입력이 처리되는 기본 흐름
- 키보드, 마우스, 게임패드 등 입력 장치로부터 사용자 조작 신호가 들어옵니다.
- 이 신호는 PlayerController가 받아서 해석합니다.
- PlayerController가 현재 소유 (Possess)하고 있는 Pawn에게 이동, 회전, 공격 등의 구체적인 명령을 내립니다.
- 특히 멀티플레이 환경에서는, 각 플레이어마다 개별 PlayerController가 생성되므로, 여러 사용자의 입력을 충돌 없이 분리하고 관리할 수 있습니다.

2️⃣ PlayerController의 주요 기능
- 입력 처리
- 키보드, 마우스, 게임패드, 터치 등 다양한 입력 장치의 이벤트를 처리합니다.
- 언리얼 엔진 5에서 제공하는 Enhanced Input 시스템을 사용하면, 액션/축 매핑을 보다 체계적으로 설정할 수 있습니다.
- C++에서는 SetupInputComponent() 함수를 오버라이드하여, 블루프린트에서는 이벤트 그래프를 통해 입력 로직을 구현합니다.
- 카메라 제어 로직
- 마우스나 게임패드의 축 입력을 받아 캐릭터의 시점 회전이나 줌 인/아웃 같은 카메라 동작을 수행할 수 있습니다.
- HUD 및 UI와의 상호작용
- 언리얼의 UMG (언리얼 모션 그래픽) 기반 UI를 통해 버튼 클릭, 드래그, 터치 등의 이벤트를 PlayerController에서 받을 수 있습니다.
- 예를 들어 인벤토리 열기, 스킬 사용 등의 명령을 UI에서 트리거하면 PlayerController가 이를 해석해 Pawn 또는 GameMode 등 다른 시스템으로 전달할 수 있습니다.
- Possess / UnPossess
- PlayerController는 특정 Pawn에 “빙의 (Possess)”하여 해당 Pawn을 제어합니다.
- 필요할 때 UnPossess() 함수를 호출하여 Pawn과의 연결을 해제한 뒤, 다른 Pawn으로 바꿔 탈 수도 있습니다.
- 멀티플레이 시 각 플레이어마다 고유의 PlayerController가 있고, 이 컨트롤러가 특정 Pawn을 소유함으로써 서로 다른 캐릭터 조작이 가능합니다.
PlayerController C++ 클래스 생성하기
1️⃣ C++ 클래스 APlayerController 생성
- 언리얼 엔진에서 커스텀 PlayerController를 만들기 위해서는, 보통 PlayerController 클래스를 상속받은 후 필요한 기능을 추가·확장합니다.
- 에디터 상단 메뉴에서 Tools → New C++ Class를 선택합니다.
- Common Classes 목록에서 Player Controller를 선택하거나, 검색 창에 PlayerController를 입력해 해당 클래스를 선택합니다.
- 클래스 이름을 MainPlayerController로 지정하고, Class Type은 Public으로 설정한 뒤 Create Class 버튼을 누릅니다.

2️⃣ PlayerController를 GameMode에 적용
- 새로 만든 MainPlayerController가 게임에서 실제로 사용되려면, GameMode에 등록해야 합니다.
- GameMode는 “어떤 PlayerController, 어떤 Pawn을 사용할 것인가?”를 결정하는 역할을 담당하므로, 아래처럼 코드를 추가·수정합니다.
#include "MainGameMode.h"
#include "MainCharacter.h"
#include "MainPlayerController.h"
AMainGameMode::AMainGameMode()
{
// StaticClass(): 클래스 이름을 통해서 호출해주는것
DefaultPawnClass = AMainCharacter::StaticClass();
//
PlayerControllerClass = AMainPlayerController::StaticClass();
}
- PlayerControllerClass는 GameMode가 제공하는 속성으로, 게임 시작 시 사용할 PlayerController 타입을 지정합니다.
- AMainPlayerController::StaticClass()는 언리얼 엔진이 AMainPlayerController 클래스의 정보를 런타임에 참조할 수 있도록 제공하는 정적 함수입니다.
- 위 코드를 저장 후 프로젝트 빌드를 완료하면, 언리얼 에디터에서 GameMode가 MainPlayerController 를 기본 PlayerController로 인식하게 됩니다.
- PlayerController Blueprint 생성
- C++로 만든 SpartaPlayerController를 더 손쉽게 편집할 수 있도록, 블루프린트로 래핑(wrap)하는 과정을 거칩니다.
- Content Browser에서 SpartaPlayerController 클래스를 우클릭 → Create Blueprint Class를 선택하고, BP_SpartaPlayerController 이름으로 생성합니다.
- C++로 만든 SpartaPlayerController를 더 손쉽게 편집할 수 있도록, 블루프린트로 래핑(wrap)하는 과정을 거칩니다.

- 이후 BP_SpartaGameMode를 열어 Player Controller Class 항목을 확인해 보면, C++에서 지정해 둔 SpartaPlayerController가 기본값으로 설정되어 있습니다. 필요하다면 여기서 BP_SpartaPlayerController를 직접 지정하여 사용할 수도 있습니다.

3️⃣ PlayerController 동작 확인
- GameMode에서 PlayerController 클래스를 적용한 뒤, 플레이 (Play) 버튼을 눌러 게임을 실행합니다.
- World Outliner을 보면, 현재 실행 중인 PlayerController 인스턴스가 BP_MainPlayerController로 표시될 것입니다.
- 이렇게 GameMode에 PlayerController 클래스를 지정하면, 게임 시작 시 맞춤형 PlayerController가 자동으로 스폰되어 플레이어 입력을 처리합니다.
Enhanced Input System의 이해 및 Input Action 설정하기
1️⃣ Enhanced Input System란?
- 언리얼 엔진 5에는 이전 버전(UE4 등)에서 사용하던 전역 Project Settings → Input 시스템을 대체하거나 확장하기 위해 Enhanced Input 시스템이 제공됩니다.
- Enhanced Input은 입력 설정을 “입력 맵(Input Mapping Context, IMC)”과 “입력 액션(Input Action, IA)”이라는 개념으로 나누어 관리합니다.
- IMC:IA_Jump, IA_Look, IA_Move, IA_Sprint 등등
- 장점: 추후 다른 플랫좀의 컨트롤러나, 다른 키들의 Binding이 쉬워짐
- IMC의 경우, 사람 컨트롤러 혹은 자동차 컨트롤러 같이 그때그때 IMC 만 변경하려 쉽게 관리할 수 있습니다.
- (사실상 이제는 그냥 이걸로 대체된 것이라 보면될꺼같다 UE6에서는 아예 이전 input 이 사라지지 않을까?)
2️⃣ Input Action (IA) 생성
- Input Action (IA)
- Input Action은 캐릭터의 이동, 점프, 발사, 줌 등과 같이 특정 동작을 추상화한 단위입니다.
- 예를 들어 WASD 이동을 담당하는 IA_Move, 스페이스바 점프를 담당하는 IA_Jump, 마우스 회전을 담당하는 IA_Look 등을 만들 수 있습니다.
- IA 생성 방법
- Content Browser에서 Inputs라는 폴더를 만든 뒤, 우클릭 → Input → Input Action을 선택합니다.
- 예시로 IA_Move라는 이름의 IA 파일을 생성하여, WASD 키 입력을 처리하는 액션으로 만들 수 있습니다.

- 이때, IA 파일을 더블 클릭해 열면 아래와 같은 주요 속성을 설정할 수 있습니다:
- Value Type은 Input Action (IA)이 입력 동작을 발생시킬 때, 어떤 유형의 값을 제공할지 결정하는 옵션입니다.
- Bool (참/거짓)
- 단순 On/Off 토글 입력에 사용됩니다.
- 예) 점프(스페이스바), 공격(마우스 왼쪽 버튼), 달리기 (Sprint)
- Axis1D (1차원 축 값)
- 단일 축 (-1~1 범위)의 입력에 사용됩니다.
- 예) 게임패드 트리거(가속 페달), 전진/후진(W/S)
- Axis2D (2차원 축 값)
- X, Y 두 축을 동시에 처리할 때 사용됩니다.
- 예) 캐릭터 이동(WASD), 마우스 이동(가로+세로)
- Axis3D (3차원 축 값)
- X, Y, Z 세 축을 동시에 처리합니다.
- 예) 비행 시뮬레이션에서 3축 제어
- Bool (참/거짓)

- 트리거 (Trigger)는 입력이 활성화되는 특정 조건을 말합니다.
- Pressed Trigger: 키를 누르는 순간에만 작동.
- Hold Trigger: 키를 일정 시간 눌렀을 때 작동.
- Released Trigger: 키를 뗄 때 작동.
- Combo: 여러 번 두드렸을 때

- 모디파이어 (Modifier)는 입력 값을 수정하거나 변환하기 위한 설정입니다.
- Negate: Axis 반전 (상하 혹은 좌우 반전 시)
- Scalar : 입력 값에 일정 배율을 곱해줌 (마우스 이동 속도 2배)
- Deadzone : 일정 임계값보다 작은 입력은 무시 (게임패드 조이스틱 미세 떨림 방지)
- Swizzle Input Axis Values: 입력 값에 축을 확실하게 재구성 (언리얼에서 정해둔 축 (X, Y, Z) 이아닌

3️⃣ Input Action (IA) 설정
- 우리는 이동, 점프, 카메라 회전, 스프린트 (빨리 달리기) 기능을 구현할 것입니다.
- 그러면 IA_Move에서 어떤 설정을 해야 할지 짐작할 수 있습니다.
- 이동은 일반적으로 "앞/뒤"와 "왼/오른쪽" 두 방향을 동시에 처리하므로, Value Type은 Axis2D로 설정합니다.
- IA_Move는 항상 활성화된 상태에서 WASD 입력만으로 동작해야 하므로 트리거나 모디파이어가 필요하지 않습니다. 예를 들어, "Shift 키를 눌러야만 이동 가능" 같은 조건이 없다면 생략해도 됩니다.
- 다음으로 점프를 담당하는 IA_Jump 를 생성하여 설정해 줍니다.
- 스페이스바를 누르면 점프하는 간단한 방식이므로, Value Type을 Bool로 설정합니다. 점프 동작은 단순히 "On/Off"로 동작하기 때문에 키가 눌렸는지 여부만 중요하며, 추가적인 수치나 축 값이 필요하지 않습니다.
- 시점 회전을 담당하는 IA_Look 을 생성하여 설정해 줍니다
- 마우스 입력은 항상 가로 (X축, 좌/우)와 세로 (Y축, 위/아래) 움직임을 동시에 포함합니다. 따라서 Value Type을 Axis2D로 설정해 줍니다.
- 스프린트 (빠르게 달리기)를 담당하는 IA_Sprint 를 생성하여 설정해 줍니다
- 스프린트 또한 단순히 Shift 키 값으로 속도를 늘리거나 줄이 고를 설정해 주므로, Value Type을 Bool로 (On/Off) 로 설정하고 저장해 줍니다.

Input Mapping Context 설정하기
1️⃣ Input Mapping Context (IMC) 생성
- Input Mapping Context (IMC)
- IMC는 여러 개의 IA들을 한데 모아놓은 매핑 설정 파일입니다.
- 예를 들어, “플레이어 기본 이동, 점프, 시점 전환”을 하나의 IMC에 넣고, “UI 전용 입력”을 다른 IMC로 분리하는 식으로 관리할 수 있습니다.
- 게임 진행 중 특정 상황에서 IMC를 활성 (Enable)하거나 비활성 (Disable)하여 입력을 제어할 수도 있습니다.
- IMC 생성 방법
- Content Browser의 Inputs 폴더에서 우클릭 → Input → Input Mapping Context를 선택합니다. 생성된 파일의 이름을 IMC_Character로 지정합니다.

- 생성된 IMC_Character 에셋을 더블 클릭하여 열고, Mappings 목록에 앞서 만든 IA_Move, IA_Jump, IA_Look 등을 각각 추가합니다.


2️⃣ Input Mapping Context (IMC) 매핑
- IA_Move 는 아래와 같이 키를 매핑해 줍니다.
- 이동 액션(IA_Move)은 W, A, S, D 키를 각각 축 값으로 매핑합니다.
- Swizzle Input Axis Values란?
- Swizzle Input Axis Values는 입력 축 (Axis)을 변환하거나 재구성하는 기능입니다. 언리얼 엔진의 입력 시스템에서는 입력 데이터를 X, Y, Z 축 중 하나로 매핑합니다. Swizzle은 이 입력 값이 올바른 축에 맞지 않을 경우, 특정 축으로 재배치하거나 변환할 수 있게 도와줍니다.
- W 키 (전진)
- W 키를 누르면 입력 값이 X축 (앞뒤 방향)에 맞춰 정렬됩니다.
- 전진은 X축 +1 방향이므로 추가적인 변환은 필요 없습니다.
- S 키 (후진)
- S 키의 입력 값도 Swizzle을 통해 X축으로 정렬됩니다.
- 후진은 전진 (W)의 반대 방향이므로 Negate를 사용해 입력 값을 뒤집습니다. (X축 +1 → X축 -1)
- A 키 (왼쪽 이동)
- A 키를 누르면 입력 값이 Y축 (좌우 방향)에 맞춰 정렬됩니다.
- A키는 오른쪽 D 이동의 반대 방향이므로 Negate를 사용해 Y축의 값을 반전합니다. (Y축 +1 → Y축 -1)
- D 키 (오른쪽 이동)
- D 키의 입력값도 Swizzle을 통해 Y축으로 정렬됩니다.
- D 키는 Y축 (좌우 방향)의 +1 방향에 매핑되므로 추가 변환이 필요 없습니다.
- Swizzle Input Axis Values란?
- 이동 액션(IA_Move)은 W, A, S, D 키를 각각 축 값으로 매핑합니다.

- IA_Jump 는 아래와 같이 키 설정을 지정해 줍니다.
- 점프는 스페이스바를 눌렀을 때 On/Off 형태로 동작합니다.
- 별도의 트리거나 모디파이어가 필요 없으므로, 기본 상태로 둡니다.

- IA_Look 은 아래와 같이 마우스 설정을 지정해 줍니다.
- 마우스 움직임을 통해 Yaw (좌우 회전)과 Pitch (상하 회전) 값을 동시에 전달받습니다.
- Axis2D로 지정한 X축, Y축 값을 게임 내 좌표계에 맞춰 회전에 반영합니다.
- 기본적으로 마우스 Y축의 움직임은 "위로 움직임 = 양수, 아래로 움직임 = 음수"로 전달됩니다.
- 하지만, 카메라의 상하 회전 (Pitch)은 엔진의 좌표계에서 "위로 = 음수, 아래로 = 양수"로 작동하는 경우가 많습니다. 따라서, Y축 값을 Negate Modifier를 통해 반전하여야 합니다.
- 위로 움직임 → 음수(-) (카메라 위로).
- 아래로 움직임 → 양수(+) (카메라 아래로).
- X축 (좌우 회전, Yaw)의 경우, 기본적인 엔진 좌표계와 마우스 움직임의 방향이 일치합니다.
- 오른쪽 이동 → 양수(+).
- 왼쪽 이동 → 음수(-).


(하지만 꼭 이렇게 해야 하는 것이 아닌, 저 설정으로 원하면 저렇게 할 것)
- IA_Sprint 는 아래와 같이 키 설정을 지정해 줍니다.
- 스프린트는 왼쪽 Shift 키를 눌렀을 때 On/Off 형태로 동작합니다.
- Key를 “Left Shift”로 지정하고 트리거나 모디파이어는 기본 상태로 두고 다시 저장을 합니다.

PlayerController에서 IMC 활성화하기
1️⃣ PlayerController 클래스 준비
- 이전 단계에서 ASpartaPlayerController라는 클래스를 만들었고, 플레이어 입력 (IA)과 매핑 컨텍스트 (IMC)를 연결하기 위해 다음과 같이 코드를 수정해 보겠습니다. 우리가 만든 IA와 IMC를 C++ 멤버 변수로 선언하고, 언리얼 에디터에서 이를 지정할 수 있도록 리플렉션 처리합니다.
- UPROPERTY() 이렇게 선언해 두면, 언리얼 에디터나 Blueprint에서 해당 멤버 변수에. uasset 파일 (우리가 만든 IMC, IA 등)을 할당해 줄 수 있습니다.
.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "MainPlayerController.generated.h"
// Declaration
class UInputMappingContext; // IMC 관련 전방 선언
class UInputAction;// IA 관련 전방 선언
UCLASS()
class BC_CH3_ASSIGNMENT_4_API AMainPlayerController : public APlayerController
{
GENERATED_BODY()
public:
AMainPlayerController();
// 에디터에서 세팅할 IMC
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Input")
UInputMappingContext* InputMappingContext;
// IA
// IA_Move를 지정할 변수
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Input")
UInputAction* MoveAction;
// IA_Jump를 지정할 변수
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Input")
UInputAction* JumpAction;
// IA_Look를 지정할 변수
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Input")
UInputAction* LookAction;
// IA_Sprint를 지정할 변수
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
UInputAction* SprintAction;
};
.cpp // 어차피 블루프린트 상에서 전부 다 초기화를 하기 때문에 여기서는 전부 다 nullptr 처리
#include "MainPlayerController.h"
// Enhanced Input System의 Local Player Subsystem을 사용하기 위해 포함
#include "EnhancedInputSubsystems.h"
// 어차피 블루프린트 상에서 전부 다 초기화를 하기 때문에 여기서는 전부 다 nullptr 처리
AMainPlayerController::AMainPlayerController()
: InputMappingContext(nullptr),
MoveAction(nullptr),
JumpAction(nullptr),
LookAction(nullptr),
SprintAction(nullptr)
{
}
- 빌드한 뒤, 언리얼 에디터를 재시작하고, ASpartaPlayerController를 상속받는 BP_SpartaPlayerController를 열어 Details 패널을 확인해 봅니다. 위에서 선언한 변수가 노출되어 있는 것을 볼 수 있습니다.
- 여기서 SpartaInputMappingContext에는 우리가 만든 IMC_Character에셋을 할당합니다.
- SpartaMoveAction, SpartaJumpAction, SpartaLookAction, SpartaSprintAction에는 각각 IA_Move, IA_Jump, IA_Look, IA_Sprint 에셋을 할당합니다.


2️⃣ IMC 활성화 코드 작성
- 이번에는 C++에서 실제로 IMC를 활성화하는 코드를 작성해 보겠습니다. 언리얼 5의 Enhanced Input System은 Local Player Subsystem을 통해 Input Mapping Context를 활성화하거나 비활성화합니다.
- Local Player Subsystem이란?
- 게임이 실행되면 언리얼은 각 플레이어를 표현하기 위해 Local Player 객체를 생성합니다.
- 싱글플레이어 상황에서는 하나의 Local Player
- 로컬 멀티플레이 (하나의 화면에서 여러 명이 플레이)라면 플레이어 수만큼 Local Player가 생성됩니다.
- UEnhancedInputLocalPlayerSubsystem 은 Local Player에 부착되어, 해당 플레이어가 사용할 입력 매핑 (IMC)을 관리합니다.
- 이를 통해, 플레이 중에 동적으로 다른 IMC를 추가·제거하여 입력 모드를 전환할 수 있습니다.
- 예) 전투 중 (IMC_Character) → UI창 열림 (IMC_UI) → 전투 종료 후 다시 (IMC_Character)
- 게임이 실행되면 언리얼은 각 플레이어를 표현하기 위해 Local Player 객체를 생성합니다.
- AMainPlayerController 클래스에서 BeginPlay() 함수를 오버라이드하여, Blueprint에서 지정해 둔 IMC를 활성화하는 코드를 추가하겠습니다.
#include "MainPlayerController.h"
// Enhanced Input System의 Local Player Subsystem을 사용하기 위해 포함
#include "EnhancedInputSubsystems.h"
// 어차피 블루프린트 상에서 전부 다 초기화를 하기 때문에 여기서는 전부 다 nullptr 처리
AMainPlayerController::AMainPlayerController()
: InputMappingContext(nullptr),
MoveAction(nullptr),
JumpAction(nullptr),
LookAction(nullptr),
SprintAction(nullptr)
{
}
void AMainPlayerController::BeginPlay()
{
Super::BeginPlay();
// GetLocalPlayer():현재 PlayerController에 연결된 Local Player 객체를 가져옴
// Local Player 는 그 플레이어의 입력이나 화면 뷰 같은 것을 관리하는 어떤 객체
if (ULocalPlayer* LocalPlayer = GetLocalPlayer())
{
// Local Player에서 EnhancedInputLocalPlayerSubsystem을 획득
// UEnhancedInputLocalPlayerSubsystem: 입력 시스템을 관리 (IMC 추가 혹은 삭제하는 역할)
if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
LocalPlayer->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>())
{
if (InputMappingContext)
{
// Subsystem을 통해 우리가 할당한 IMC를 활성화
// 우선순위(Priority)는 0이 가장 높은 우선순위
Subsystem->AddMappingContext(InputMappingContext, 0);
}
}
}
}
- GetLocalPlayer()
- 현재 PlayerController가 관리하는 Local Player를 반환합니다.
- GetSubsystem<UEnhancedInputLocalPlayerSubsystem>()
- 해당 Local Player에 부착된 Enhanced Input Subsystem을 반환합니다.
- 이를 통해 AddMappingContext나 RemoveMappingContext 등을 호출하여 입력 매핑을 동적으로 제어할 수 있습니다.
- AddMappingContext()
- 주어진 IMC를 Subsystem에 추가하여 입력 매핑을 활성화합니다.
- SpartaInputMappingContext: 활성화할 IMC.
- 0: 우선순위. 낮을수록 높은 우선순위를 가집니다.
- 이 함수를 여러 번 호출해 여러 IMC를 활성화할 수도 있습니다.
- 우선순위를 달리 부여해, 특정 IMC가 다른 IMC보다 우선순위가 높도록 설정할 수도 있습니다.
- 이 로직이 실행되면, IMC에 정의된 모든 IA와 키 매핑이 이 PlayerController에 적용됩니다. 빌드 후 언리얼 에디터를 실행해 보세요.
3️⃣ IMC 적용 확인 및 테스트
- 잘 연결되었는지 확인하기 위해, 언리얼 에디터에서 BP_MainPlayerController 의 Blueprint를 다시 열어 이벤트 그래프를 살펴봅시다.
- 그래프에서 오른쪽 클릭 → “enhanced action events”라고 입력해 검색합니다.
- 우리가 만든 IA_Move, IA_Jump, IA_Look이 검색되는 것을 확인할 수 있습니다.

추천
[페이지] Unreal Engine | 언리얼 엔진