Enhanced Input 시스템
UE5 기본 입력 시스템과 GAS 연동
Enhanced Input 개요
UE 5.1부터 기본 입력 시스템
Enhanced Input System은 UE 5.1부터 기본 입력 시스템으로 채택되었습니다. 기존 Input System 대비 더 유연하고 모듈화된 입력 처리가 가능합니다.
Input Action
입력 정의
Modifiers
값 변환
Triggers
발동 조건
Mapping Context
키 바인딩
- Context 기반 — 상황에 따라 입력 매핑을 동적으로 변경 가능
- Modifier 체인 — 입력 값을 파이프라인으로 가공
- 데이터 주도 — 입력 액션과 매핑을 에셋으로 관리
- 멀티플랫폼 — 키보드, 게임패드, 터치 동시 지원
Input Action 정의
다양한 입력 타입과 트리거
Trigger 유형
| Trigger | 설명 | 사용 예시 |
|---|---|---|
Started |
버튼 누른 순간 | 점프, 공격 |
Triggered |
누르는 동안 매 프레임 | 이동, 카메라 |
Completed |
버튼 뗀 순간 | 점프 중지, 차징 해제 |
Canceled |
액션 취소됨 | 차징 취소 |
Ongoing |
조건 만족 중 | 홀드 진행 중 |
Modifier 유형
Negate
값을 반전합니다. 예: S키를 W와 같은 액션에 바인딩하면서 후진으로 사용
Swizzle Input Axis Values
축을 교환합니다. YXZ → XYZ 등
Dead Zone
임계값 이하 입력을 무시합니다. 게임패드 스틱의 드리프트 방지
Scalar
값을 배수로 조정합니다. 감도 조절에 활용
PlayerController 구현
입력 바인딩 및 처리
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "InputActionValue.h"
#include "MyPlayerController.generated.h"
class UInputMappingContext;
class UInputAction;
UCLASS()
class MYGAME_API AMyPlayerController : public APlayerController
{
GENERATED_BODY()
public:
AMyPlayerController();
protected:
virtual void BeginPlay() override;
virtual void SetupInputComponent() override;
// Input Mapping Context
UPROPERTY(EditDefaultsOnly, Category = "Input")
UInputMappingContext* DefaultMappingContext;
// Input Actions
UPROPERTY(EditDefaultsOnly, Category = "Input")
UInputAction* MoveAction;
UPROPERTY(EditDefaultsOnly, Category = "Input")
UInputAction* LookAction;
UPROPERTY(EditDefaultsOnly, Category = "Input")
UInputAction* JumpAction;
UPROPERTY(EditDefaultsOnly, Category = "Input")
UInputAction* AttackAction;
UPROPERTY(EditDefaultsOnly, Category = "Input")
UInputAction* InteractAction;
UPROPERTY(EditDefaultsOnly, Category = "Input")
UInputAction* InventoryAction;
// Input Handlers
void HandleMove(const FInputActionValue& Value);
void HandleLook(const FInputActionValue& Value);
void HandleJump();
void HandleStopJump();
void HandleAttack();
void HandleInteract();
void HandleInventory();
};
#include "MyPlayerController.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InputMappingContext.h"
#include "MyCharacter.h"
AMyPlayerController::AMyPlayerController()
{
}
void AMyPlayerController::BeginPlay()
{
Super::BeginPlay();
// Input Mapping Context 추가
if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(
GetLocalPlayer()))
{
if (DefaultMappingContext)
{
// Priority 0: 기본 매핑
Subsystem->AddMappingContext(DefaultMappingContext, 0);
}
}
}
void AMyPlayerController::SetupInputComponent()
{
Super::SetupInputComponent();
if (UEnhancedInputComponent* EnhancedInput =
Cast<UEnhancedInputComponent>(InputComponent))
{
// 이동 (Triggered: 누르는 동안 계속)
if (MoveAction)
{
EnhancedInput->BindAction(
MoveAction, ETriggerEvent::Triggered,
this, &AMyPlayerController::HandleMove);
}
// 카메라 (Triggered)
if (LookAction)
{
EnhancedInput->BindAction(
LookAction, ETriggerEvent::Triggered,
this, &AMyPlayerController::HandleLook);
}
// 점프 (Started: 누를 때, Completed: 뗄 때)
if (JumpAction)
{
EnhancedInput->BindAction(
JumpAction, ETriggerEvent::Started,
this, &AMyPlayerController::HandleJump);
EnhancedInput->BindAction(
JumpAction, ETriggerEvent::Completed,
this, &AMyPlayerController::HandleStopJump);
}
// 공격 (Started: 한 번만)
if (AttackAction)
{
EnhancedInput->BindAction(
AttackAction, ETriggerEvent::Started,
this, &AMyPlayerController::HandleAttack);
}
// 상호작용
if (InteractAction)
{
EnhancedInput->BindAction(
InteractAction, ETriggerEvent::Started,
this, &AMyPlayerController::HandleInteract);
}
// 인벤토리
if (InventoryAction)
{
EnhancedInput->BindAction(
InventoryAction, ETriggerEvent::Started,
this, &AMyPlayerController::HandleInventory);
}
}
}
입력 핸들러 구현
GAS 및 캐릭터 연동
void AMyPlayerController::HandleMove(const FInputActionValue& Value)
{
// Vector2D: X=Right, Y=Forward
const FVector2D MovementVector = Value.Get<FVector2D>();
if (AMyCharacter* MyCharacter = Cast<AMyCharacter>(GetPawn()))
{
// 카메라 방향 기준 이동
const FRotator Rotation = GetControlRotation();
const FRotator YawRotation(0, Rotation.Yaw, 0);
const FVector ForwardDirection =
FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
const FVector RightDirection =
FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
MyCharacter->AddMovementInput(ForwardDirection, MovementVector.Y);
MyCharacter->AddMovementInput(RightDirection, MovementVector.X);
}
}
void AMyPlayerController::HandleLook(const FInputActionValue& Value)
{
const FVector2D LookVector = Value.Get<FVector2D>();
AddYawInput(LookVector.X);
AddPitchInput(LookVector.Y);
}
void AMyPlayerController::HandleJump()
{
if (ACharacter* MyCharacter = GetCharacter())
{
MyCharacter->Jump();
}
}
void AMyPlayerController::HandleStopJump()
{
if (ACharacter* MyCharacter = GetCharacter())
{
MyCharacter->StopJumping();
}
}
void AMyPlayerController::HandleAttack()
{
if (AMyCharacter* MyCharacter = Cast<AMyCharacter>(GetPawn()))
{
if (UAbilitySystemComponent* ASC =
MyCharacter->GetAbilitySystemComponent())
{
// GameplayTag로 어빌리티 활성화
FGameplayTagContainer TagContainer;
TagContainer.AddTag(
FGameplayTag::RequestGameplayTag(
FName("Ability.Attack.Melee")));
ASC->TryActivateAbilitiesByTag(TagContainer);
}
}
}
void AMyPlayerController::HandleInteract()
{
if (AMyCharacter* MyCharacter = Cast<AMyCharacter>(GetPawn()))
{
MyCharacter->TryInteract();
}
}
void AMyPlayerController::HandleInventory()
{
// UI 토글
if (AMyHUD* HUD = Cast<AMyHUD>(GetHUD()))
{
HUD->ToggleInventory();
}
}
UI가 열리면 UIMappingContext를 추가하고 DefaultMappingContext의 우선순위를 낮추어 입력 처리를 전환할 수 있습니다.
핵심 요약
- Input Action — 입력의 논리적 의미를 정의하는 에셋 (이동, 점프, 공격 등)
- Input Mapping Context — 실제 키와 Input Action을 연결하는 매핑
- Trigger Event — Started, Triggered, Completed 등 입력 상태에 따른 이벤트
- Modifier — 입력 값을 가공하는 파이프라인 (Dead Zone, Negate, Scalar 등)
- GAS 연동 — 공격 등의 입력을 GameplayTag로 어빌리티와 연결
도전 과제
배운 내용을 직접 실습해보세요
UInputAction과 UInputMappingContext를 에디터에서 생성하세요. IA_Move, IA_Look, IA_Attack, IA_Interact, IA_Inventory를 정의하고, DefaultMappingContext에 키 바인딩하세요.
SetupPlayerInputComponent()에서 UEnhancedInputComponent::BindAction()으로 각 액션을 바인딩하세요. ETriggerEvent::Started, Triggered, Completed를 구분하여 한 번 누르기, 누르고 있기 패턴을 구현하세요.
전투, 인벤토리 UI, 대화, 탈것 탑승 등 상황에 따라 UEnhancedInputLocalPlayerSubsystem::AddMappingContext()/RemoveMappingContext()로 입력 매핑을 동적으로 전환하는 시스템을 구현하세요.