Skip to content

UE5 Enhanced Input System 가이드

UE5에서 기존 BindAxis / BindAction 기반의 Legacy Input System은 Enhanced Input System으로 대체되었습니다. Enhanced Input은 런타임 컨텍스트 전환, 복합 입력 매핑, 플랫폼별 리맵핑을 지원하는 데이터 기반 입력 시스템입니다.

기능Legacy InputEnhanced Input
런타임 리맵핑불가가능
컨텍스트 전환 (UI/전투)불가IMC로 즉시 전환
복합 입력 (Chord)제한적Trigger로 유연 지원
입력 수정자 (Dead Zone, Swizzle)제한적Modifier로 풍부한 변환
플랫폼별 기본 키수동자동 구성 가능

YourGame.Build.cs에 모듈을 추가합니다.

YourGame.Build.cs
PublicDependencyModuleNames.AddRange(new string[]
{
"Core",
"CoreUObject",
"Engine",
"InputCore",
"EnhancedInput" // 추가
});

프로젝트 세팅에서 Default Player Input ClassDefault Input Component Class를 변경합니다.

Config/DefaultInput.ini:

[/Script/Engine.InputSettings]
DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput
DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent

Enhanced Input은 두 가지 데이터 에셋을 사용합니다.

  • InputAction (IA): 단일 논리적 행동 정의 (예: IA_Jump, IA_Move)
  • Input Mapping Context (IMC): 물리 키와 IA를 연결하는 컨텍스트 그룹

에디터에서 생성: 우클릭 > Input > Input Action / Input Mapping Context


MyCharacter.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "InputActionValue.h"
#include "MyCharacter.generated.h"
class UInputMappingContext;
class UInputAction;
UCLASS()
class MYGAME_API AMyCharacter : public ACharacter
{
GENERATED_BODY()
public:
AMyCharacter();
protected:
virtual void BeginPlay() override;
virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override;
private:
// IMC (에디터에서 할당)
UPROPERTY(EditDefaultsOnly, Category = "Input")
TObjectPtr<UInputMappingContext> DefaultMappingContext;
// InputActions (에디터에서 할당)
UPROPERTY(EditDefaultsOnly, Category = "Input")
TObjectPtr<UInputAction> IA_Move;
UPROPERTY(EditDefaultsOnly, Category = "Input")
TObjectPtr<UInputAction> IA_Look;
UPROPERTY(EditDefaultsOnly, Category = "Input")
TObjectPtr<UInputAction> IA_Jump;
UPROPERTY(EditDefaultsOnly, Category = "Input")
TObjectPtr<UInputAction> IA_Sprint;
// 입력 핸들러
void HandleMove(const FInputActionValue& Value);
void HandleLook(const FInputActionValue& Value);
void HandleJump(const FInputActionValue& Value);
void HandleSprintStarted(const FInputActionValue& Value);
void HandleSprintEnded(const FInputActionValue& Value);
};
MyCharacter.cpp
#include "MyCharacter.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InputMappingContext.h"
#include "GameFramework/CharacterMovementComponent.h"
AMyCharacter::AMyCharacter()
{
PrimaryActorTick.bCanEverTick = false;
}
void AMyCharacter::BeginPlay()
{
Super::BeginPlay();
// LocalPlayer의 EnhancedInputLocalPlayerSubsystem에 IMC 등록
if (APlayerController* PC = Cast<APlayerController>(GetController()))
{
if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
{
// Priority: 숫자가 높을수록 우선순위가 높음
Subsystem->AddMappingContext(DefaultMappingContext, 0);
}
}
}
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
// Enhanced Input Component로 캐스팅
UEnhancedInputComponent* EnhancedInput = Cast<UEnhancedInputComponent>(PlayerInputComponent);
if (!EnhancedInput)
{
return;
}
// Move: Triggered (눌리는 동안 매 프레임)
EnhancedInput->BindAction(IA_Move, ETriggerEvent::Triggered, this, &AMyCharacter::HandleMove);
// Look: Triggered
EnhancedInput->BindAction(IA_Look, ETriggerEvent::Triggered, this, &AMyCharacter::HandleLook);
// Jump: Started (키를 누른 순간 1회)
EnhancedInput->BindAction(IA_Jump, ETriggerEvent::Started, this, &AMyCharacter::HandleJump);
// Sprint: Started / Completed (누름/뗌)
EnhancedInput->BindAction(IA_Sprint, ETriggerEvent::Started, this, &AMyCharacter::HandleSprintStarted);
EnhancedInput->BindAction(IA_Sprint, ETriggerEvent::Completed, this, &AMyCharacter::HandleSprintEnded);
}
void AMyCharacter::HandleMove(const FInputActionValue& Value)
{
// IA_Move의 Value Type이 Axis2D(Vector2D)인 경우
FVector2D MoveInput = Value.Get<FVector2D>();
if (Controller)
{
const FRotator Rotation = Controller->GetControlRotation();
const FRotator YawRotation(0, Rotation.Yaw, 0);
const FVector ForwardDir = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
const FVector RightDir = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
AddMovementInput(ForwardDir, MoveInput.Y);
AddMovementInput(RightDir, MoveInput.X);
}
}
void AMyCharacter::HandleLook(const FInputActionValue& Value)
{
// IA_Look의 Value Type이 Axis2D(Vector2D)인 경우
FVector2D LookInput = Value.Get<FVector2D>();
AddControllerYawInput(LookInput.X);
AddControllerPitchInput(LookInput.Y);
}
void AMyCharacter::HandleJump(const FInputActionValue& Value)
{
Jump();
}
void AMyCharacter::HandleSprintStarted(const FInputActionValue& Value)
{
GetCharacterMovement()->MaxWalkSpeed = 800.f;
}
void AMyCharacter::HandleSprintEnded(const FInputActionValue& Value)
{
GetCharacterMovement()->MaxWalkSpeed = 400.f;
}

BindAction 두 번째 파라미터로 전달하는 트리거 이벤트를 선택합니다.

ETriggerEvent발생 시점
Started입력이 시작된 첫 프레임 (키 누름 순간)
Triggered입력이 활성화된 매 프레임 (키 누르는 동안)
Ongoing조건을 처리 중인 매 프레임 (Tap 등 복합 트리거)
Completed입력이 종료된 프레임 (키 뗌)
Canceled진행 중 조건이 실패한 프레임

5. IMC 런타임 전환 — UI/전투 컨텍스트

Section titled “5. IMC 런타임 전환 — UI/전투 컨텍스트”
// UIComponent.cpp — UI 열릴 때 전투 IMC 제거, UI IMC 추가
void UUIComponent::OpenInventory()
{
APlayerController* PC = Cast<APlayerController>(GetOwner()->GetInstigatorController());
if (!PC) return;
UEnhancedInputLocalPlayerSubsystem* Subsystem =
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer());
if (!Subsystem) return;
// 전투 컨텍스트 제거
Subsystem->RemoveMappingContext(CombatMappingContext);
// UI 컨텍스트 추가 (우선순위 10으로 최상위)
Subsystem->AddMappingContext(UIMappingContext, 10);
PC->SetShowMouseCursor(true);
PC->SetInputMode(FInputModeUIOnly());
}
void UUIComponent::CloseInventory()
{
APlayerController* PC = Cast<APlayerController>(GetOwner()->GetInstigatorController());
if (!PC) return;
UEnhancedInputLocalPlayerSubsystem* Subsystem =
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer());
if (!Subsystem) return;
Subsystem->RemoveMappingContext(UIMappingContext);
Subsystem->AddMappingContext(CombatMappingContext, 0);
PC->SetShowMouseCursor(false);
PC->SetInputMode(FInputModeGameOnly());
}

에디터 에셋 없이 순수 C++로 InputAction을 생성하고 바인딩할 수 있습니다.

void AMyCharacter::SetupDynamicInput()
{
UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(InputComponent);
if (!EIC) return;
// 런타임 InputAction 생성
UInputAction* DynamicAction = NewObject<UInputAction>(this);
DynamicAction->ValueType = EInputActionValueType::Boolean;
// 바인딩
EIC->BindAction(DynamicAction, ETriggerEvent::Started, this, &AMyCharacter::HandleJump);
// IMC에 동적으로 매핑 추가
UInputMappingContext* DynamicIMC = NewObject<UInputMappingContext>(this);
FEnhancedActionKeyMapping& Mapping = DynamicIMC->MapKey(DynamicAction, EKeys::SpaceBar);
if (APlayerController* PC = Cast<APlayerController>(GetController()))
{
if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
{
Subsystem->AddMappingContext(DynamicIMC, 5);
}
}
}

ValueType사용 사례Get<> 타입
Boolean점프, 상호작용 (눌림/뗌)bool
Axis1D가속·감속 (단일 축)float
Axis2D이동·시점 (2D 방향)FVector2D
Axis3D3D 공간 입력 (VR 등)FVector

  • IMC (Input Mapping Context): 물리 키 ↔ 논리 액션 매핑 그룹. AddMappingContext / RemoveMappingContext로 런타임 전환
  • InputAction: 논리적 행동 단위. 에디터에서 생성하거나 C++에서 NewObject<UInputAction>()으로 동적 생성
  • SetupPlayerInputComponent에서 UEnhancedInputComponent로 캐스팅 후 BindAction 호출
  • ETriggerEvent::Started / Triggered / Completed를 상황에 맞게 선택
  • 컨텍스트 우선순위(Priority)가 높은 IMC가 먼저 입력을 처리하므로 UI는 높은 값 사용