본문으로 바로가기

[Unreal Engine 5] 향상된 입력 (Enhanced Input)

category UnrealEngine/기능 2023. 6. 4. 14:47

Enhanced Input은 이전의 'Action And Axis' 매핑과 완전히 역호환 됩니다.

Unreal Engine5에서 기존의 Input은 Deprecated 조치되었으며, Enhanced Input을 사용하기를 권장합니다.

 

입력시스템의 동작 방식

플레이어의 입력은 컨트롤러를 통해 폰으로 전달됨

입력을 컨트롤러가 처리할 수도, 폰이 처리할 수도 있는데, 일반적으로는 폰이 처리하도록 설정

다양한 사물에 빙의하는 게임의 경우 폰이 유리

 

 

 

입력 매핑 컨텍스트 : 입력 매핑 컨텍스트를 이용하여, 런타임에 각 설정에 맞는 입력장치를 설정할 수 있습니다.

(예 : 게임패드용 입력 매핑 컨텍스트, 키보드용 입력 매핑 컨텍스트)

 

입력값 변조(Modifier) : 우리가 AD / WS 입력값을 받아낼 때 이 값을 Y축과 X축으로 변경, 값 반전등을 설정하는데

입력값 변조 (액션) 이 이 행위를 설정한다.

 

이벤트 활성화(Trigger) : 들어온 입력이 일반 버튼인지, 축 이동인지, 일정 이상 눌러야 하는지 등을 확인하여 이벤트를 활성화 시키고, 게임 로직의 Input 함수로 호출합니다.

 

과거에는 이러한 행위들을 게임 로직에서 처리했는데 별도의 액션을 통해서 관리할 수 있게 함으로써 게임 로직의 부담을 줄이고, 런타임에 원하는 설정들을 자유롭게 변경할 수 있도록 입력 시스템을 향상 시켰다고 생각하면 된다.

 

 

설치 및 기본 세팅

플러그인 세팅에서 Enhanced Input을 찾아 설치하고 언리얼 엔진을 재시작한다.

UE5.2 에서는 이 Enhanced Input이 기본으로 설치되어있고 기본 입력 시스템으로 설정되어 있으므로 할 필요는 없다.

(5.1에서는 해야한다)

 

프로젝트 설정의 Input에서 Default Classes가 Enhanced* 인지 확인하고 설정한다.

 

시작

기본적으로 WASD를 이용한 이동을 작성해보겠다.

기본적인 InputActionInputMappingContext를 생성해준다.

UE5 Documents 에서는 InputAction의 접두사를 IA로, InputMappingContext의 접두사를 IMC로 하기를 권장한다.

 

InputAction을 설정한다. 이 곳에서는 TriggerModifier (위에서 설명했던 입력값 변조와 이벤트 활성화) 를 설정할 수 있으며, 넘어오는 값이 무엇인지를 Value Type으로 설정할 수 있다.

 

InputMappingContext이다. 해당 InputAction에서 어떠한 입력들이 매핑될 것인지를 설정한다.

해당 입력을 받았을 때 이 것이 Action 으로 어떻게 넘어갈 것인지를 설정해야 하는데 

본인은 다음과 같이 설정했다.

W를 눌렀을 때는 IA_Player_Quater에서 설정한 Axis2D (Vector2D)(1, 0) 으로 넘어갈 것이다.

언리얼 엔진에서는 양의 x축이 forward 이므로 (1, 0)이 넘어온다면 그대로 이동시켜 주면 된다.

S를 눌렀을 때는 음의 x축으로 이동해야 하므로 (-1, 0)으로 넘어오게 하기 위해 Modifiers에 Negate를 추가했다.

A와 D는 유심히 확인해야 하는데, Swizzle Input Axis Value라는 Modifiers가 붙었다.

 

이는 X 와 Y의 위치를 변환시키는 작업을 한다.

예를 들어 (1, 0) 이라는 값이 들어온다면 Modifiers가 실제로 게임 로직에 값을 넘길때는 (0, 1) 이라는 값으로 변환시켜 넘긴다.

즉, D를 누르게 된다면 (1, 0) 이라는 기본 값이 넘어가게 되겠지만 Swizzle Input Axis Value 라는 Modifier 때문에 로직에서는 (0, 1)로 넘어가게 될 것이고 언리얼 엔진에서 양의 y축은 right 이므로 우측으로 이동하게 될 것이다.

A를 눌렀을때는 음의 y축으로 이동해야 하므로 (1, 0) -> (0, -1)로 변환되게 될 것이다 (Modifier에 의해)

 

이제 게임 로직에서의 처리만 남았다.

자신이 움직임을 처리할 폰(캐릭터) 클래스의 헤더에서 다음과 같이 작성하자.

그리고 생성자에서 다음과 같이 InputAction을 불러온다.

 

 

SetupPlayerInputComponent재정의(Override)한다.

현재 기본으로 설정되어있는 입력 컴포넌트를 UEnhancedInputComponent로 캐스팅 한 후, 생성자에서 불러온 Action을 바인딩한다.

 

그리고 실제로 값이 넘어왔을 때 이를 움직이게 처리하면 된다.

 

SquaredLength 함수는 제곱하여 얻어낸 길이(?) 정도라고 생각하면 된다.

우리가 어떠한 벡터의 길이를 구할때는 sqrt(x * x + y * y) = z 라고 하는데, 이때 z 의 제곱을 구해보면

x * x + y * y = z * z 이다. 이 때 벡터가 단위벡터라고 생각해보면 x * x + y * y = 1.0 인 것이다.

그러므로 sqrt 를 사용하지 않고 단위 벡터인지를 확인할 수 있으므로 SquaredLength만으로도 판별할 수 있다.

 

우리의 FInputActionValeu& Value 매개변수는 (1, 0), (-1, 0), (0, 1), (0, -1) 의 형태로만 넘어온다. (위의 Modifier)

그러므로 이 방향대로 AddMovementInput을 넣어 이동을 시켜주면 된다.

 

만약 회전이 필요하다면 컨트롤러에 접근하여 회전하자

FRotationMatrix::MakeFromX를 통해서 MoveDirection을 x축으로 설정하여 Up, Right 벡터를 구하고 이를 축으로 삼는 새로운 회전 행렬을 만들어 낸다.

컨트롤러는 현재 사용자의 회전양 같은걸 관리하는거지, 폰이나 카메라에 적용시키지 않는다.
그런데 적용되는 이유는, 카메라나 SpringArm에 bUseControllerRotation이 true로 설정되어 있기 때문이다.
그러므로 컨트롤러가 회전할 때 카메라나 SpringArm도 동시에 회전되어지는 것이다.
즉, 폰도 bUseControllerRotation 같은 것을 true로 설정하는 것이 아니라면 MovementComponent로 회전, 움직임을 처리해야함

 

FMatrix FRotationMatrix::MakeFromX(FVector const& XAxis)
{
	FVector const NewX = XAxis.GetSafeNormal();

	FVector const UpVector = ( FMath::Abs(NewX.Z) < (1.f - KINDA_SMALL_NUMBER) ) ? FVector(0,0,1.f) : FVector(1.f,0,0);

	const FVector NewY = (UpVector ^ NewX).GetSafeNormal();
	const FVector NewZ = NewX ^ NewY;

	return FMatrix(NewX, NewY, NewZ, FVector::ZeroVector);
}

향상된 입력에 대한 코드는 https://github.com/kimduuukbae/UE5_Example 에서 확인할 수 있다.