[내일배움캠프/UE] Enhanced Input System

김세희·2025년 7월 1일
post-thumbnail

✍️Today I Learned

  1. PlayerController
  2. Enhanced Input System
  3. Input Mapping Context
  4. PlayerController에서 IMC 활성화

PlayerController

플레이어의 입력은 플레이어 컨트롤러에서 처리한다. 유저가 키보드나 패드 등 입력 장치를 조작할 때 조작에 대한 판단을 담당한다. 그것에 대한 결과적인 동작은 캐릭터 클래스에서 담당한다.
👉 입력을 캐릭터에 전달하는 역할을 한다.

주요 기능

  1. 입력 처리 - Enhanced Input System(UE5~)
  2. 카메라 제어 로직
  3. UI와의 상호작용
  4. Possess - 캐릭터나 폰에 빙의 / Unpossess

Enhanced Input System

Input Mapping system (IMC)

IA들을 총괄해서 관리. 스위치 역할
ex) Space bar -> IA_Jump
이렇게 관리하면 입력키가 바껴도 동작 로직은 바꾸지 않아도 된다.
상황에 따라 다른 IMC를 활성화할 수 있어 입력을 관리하기 편리하다.

Input Action (IA)

특정 동작을 추상화. 전선 역할
ex) Jump → IA_Jump → Jump 함수

InputMappingContext

언리얼에서 IA, IMC 블루프린트를 생성한다.

IA

  • Value Type
    입력을 받았을 때 게임에서 어떤 유형의 값을 변환 시킬지
    Digital (bool): on / off. 점프, 마우스, 스프린트 등
    Axis1D (float): 단일 축. 전진 후진, 가속 페달
    Axis2D (Vector2D): x, y축 동시 처리. 이동, 마우스 시점 회전
    Axis3D (Vector): x, y, z축 동시 처리. 비행

  • Triggers
    입력이 어떻게 활성화 되게 할 것인지에 대한 조건. 특이한 조작이 필요한 경우 설정

  • Modifiers
    입력 값 변환
    Dead Zone: 민감도 조정. 미세한 입력 무시
    Negate: 입력 값 반전
    Scalar: 배율
    Swizzle Input Axis Values: 입력값 축 재구성

IMC

IA에 키 매핑

  • IA_Move
    WASD 키를 매핑하고 Swizzle Input Axis Values 로 각 입력마다 축을 변경한다. 양수 값은 앞, 오른쪽으로 이동하므로 A, S에는 Negate를 사용해 반전 시킨다.
  • IA_Look
    Mouse XY 2D-Axis로 입력 매핑. Y축만 Negate로 입력을 반전시킨다.
    마우스를 올리면 Y축 양수 값이 들어오는데 Pitch에서는 양수 값이면 아래로 회전한다.
    마우스를 올렸을 때 시점을 위로 올리기 위해 값을 반전시킨다.

  • IA_Jump
    스페이스 바를 매핑한다.

  • IA_Sprint
    Left Shift를 매핑한다.


PlayerController에서 IMC 활성화

// 헤더
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "CH3_PlayerController.generated.h"

// 전방 선언
class UInputMappingContext;
class UInputAction;

UCLASS()
class CH3_PROJECT_API ACH3_PlayerController : public APlayerController
{
	GENERATED_BODY()

public:
	ACH3_PlayerController();	

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
	UInputMappingContext* InputMappingContext;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
	UInputAction* MoveAction;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
	UInputAction* LookAction;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
	UInputAction* JumpAction;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
	UInputAction* SprintAction;

protected:
	virtual void BeginPlay() override;
};
// cpp
#include "CH3_PlayerController.h"
#include "EnhancedInputSubsystems.h"

ACH3_PlayerController::ACH3_PlayerController() 
	: InputMappingContext(nullptr), 
		MoveAction(nullptr),
		LookAction(nullptr),
		JumpAction(nullptr),
		SprintAction(nullptr)
	// 블루프린트에서 할당할 거라서 안전하게 nullptr 넣어 줌
{
	
}

void ACH3_PlayerController::BeginPlay() 
{
	Super::BeginPlay();

	// 로컬 플레이어: 플레이어의 입력이나 화면들을 관리하는 객체
	// 현재 플레이어의 로컬 플레이어 객체 가져오기
	if (ULocalPlayer* LocalPlayer = GetLocalPlayer()) 
	{
		//UEnhancedInputLocalPlayerSubsystem: IMC를 추가/삭제하는 역할
		if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
			LocalPlayer->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>()) 
		{
			if (InputMappingContext) 
			{
				// IMC 활성화
				// 0: 우선순위. 여러 IMC가 겹치는 상황이 되면 우선순위 높은걸로 할당한다.
				Subsystem->AddMappingContext(InputMappingContext, 0);
			}
		}
	}
}

빌드 후 언리얼 에디터에서 해당 플레리어 컨트롤러 클래스를 상속받은 블루프린트를 열어 멤버 변수들에 맞는 클래스를 할당한다.

출처: 스파르타코딩 내일배움캠프

0개의 댓글