Unreal Engine/기능 구현 / / 2025. 8. 23. 17:55

[Unreal Engine 5] 프로젝트 설정(2) - Enhanced Input System

반응형

에디터에서 Input Action과 InputMappingContext를 먼저 만들든, C++ 코드로 먼저 멤버로 만들든 순서는 중요하지 않다.

 

 

# 점프

 

1. Input Action을 생성한다. 

점프를 구현할 것이므로 InputActionValue는 점프 "한다"와 "안 한다"로 나뉘면 되므로 bool값으로 설정한다.

 

값 타입 외에 다른 것은 손대지 않는다. 

 

 

2. Input Mapping Context를 생성한다.

3. Input Mapping Context에서 Input Action을 매핑한다.

키보드의 스페이스바와 점프를 매핑한다.

이제 스페이스바가 눌리면 점프가 true가 된다.

 

이제 true가 되면 호출될 함수를 지정해야 한다.

 

4. UInputAction과 UInputMappingContext 멤버를 만든다.

단일 책임 원칙에 따라 PlayerController에 생성하는게 적절하지만 빠르게 테스트하기 위해서 일단 캐릭터에서 생성한다.

 

향상된 입력 시스템(Enhanced Input System)을 사용하기 위해서는 반드시 프로젝트명.Build.cs 파일에 "Enhanced Input" 모듈이 추가되어 있어야 한다. 

 

헤더

#include "EnhanctedInputSubsystems.h"

#include "EnhancedInputComponent.h"

 

폰이 재시작 될 때 호출되는 함수에서 입력을 처리한다.

코드는 다음과 같다. 

1). 플레이어 컨트롤러를 가져오고

2). 플레이어 컨트롤러의 LocalPlayer에서 Subsystem을 가져와서 EnhancedInputLocalPlayerSubsystem으로 형변환한다.

3). 여기서 에디터에서 생성한 InputMappingContext를 0번 플레이어(로컬 플레이어 / 클라이언트 자신)에 연결한다.

 

 

 

5. InputAction을 바인딩한다.

1). UInputComponent를 UEnhancedInputComponent로 형변환한다.

2). BindAction 함수를 사용해 UInputAction을 바인딩한다.

 

이렇게 하면, 키보드 스페이스 바와 매핑된 IA_Jump가 true가 되면 AAOS_Character::Jump 함수가 호출되는 형태가 된다.

 

점프 기능은 언리얼 엔진에서 기본으로 제공하는 함수를 사용한다.

 

 

6. 에디터에서 UInputAction과 UInputMappingContext를 연결한다.

 

이제 IA_Jump가 bool값이고, 

스페이스 바를 누르면 bool이 true가 됨을 C++에서도 알 수 있게 되었다.

 

 

 

 

그 다음으로는 마우스 움직임을 통한 카메라 회전을 구현한다.

 

# 카메라 회전

1. UInputAction과  바인딩할 함수를 생성한다.

여기서 매개변수는 const FInputActionValue&는 항상 고정이다.

 

2. UEnhancedInputComponent에 바인딩한다. 

 

3. 바인딩할 함수를 정의한다.

해당 코드의 오타가 있다. AddContollerPitchInput의 값이 반전되어야 한다. 따라서 InputValue.Y가 아니라 -InputValue.Y여야 한다.

FInputActionValue는 총 4가지 타입 중 하나다.

1). bool

2). FVector1D

3). FVector2D

4). FVector

이 값은 에디터에서 InputAction의 값 타입을 무엇으로 지정했느냐에 따라 달라지는데, 

코드를 작성할 때부터 여기서 어떤 타입의 값을 받아서 처리할지를 생각하고 구현한다.

 

지금은 마우스를 통한 회전을 생각하는 것이므로 bool 값은 의미가 없다.

"회전 한다", "안 한다"가 아니다. "얼마만큼 회전할 것인가?"가 핵심이다.

그러므로 XY값이 필요하다. 따라서 FVector2D를 써야 한다.

 

여기서 또 중요한 점은 값을 바꾸는 대상이 캐릭터가 아니다. 컨트롤러다.

언리얼 엔진에서 이 사실을 잊으면 안된다. 플레이어가 바라보는 캐릭터/Pawn는 껍데기다. 본체는 Controller이다.

나의 입력을 받고 전달하는 전기 신호(뇌/Controller)가 본체이고, 몸통(Pawn)는 그저 명령에 따라 움직이는 대상일 뿐이다.

 

 

4. 에디터에서 InputAction(IA_Look)을 생성한다.

 

값 타입은 FVector2D

 

 

5. InputMappingContext에서 InputAction과 마우스를 매핑한다.

 

6. 캐릭터에서 C++에서 생성한 UInputAction과 에디터에서 생성한 InputAction을 연결한다.

 

이렇게 하면 마우스의 X,Y 값이 바뀌면 C++에 바인딩된 HandleLookInput 함수가 호출되며 X,Y 값이 전달된다.

 

 

그런데 몇 가지 문제가 보인다.

1. 카메라가 회전하면 캐릭터도 같이 회전한다.

2. 카메라의 상하 회전이 안되고 있다.

 

먼저 치명적인 문제인 카메라의 상하 회전부터 적용케 해야 한다.

 

이 문제는 SpringArm 때문이다.

Spring Arm도 컨트롤러의 회전에 영향을 받게 하면 카메라 회전 문제가 해결된다.

 

 

 

다음 문제로는 카메라가 회전하면 캐릭터도 같이 회전하는 문제인데, 이 문제는 Pawn의 컨트롤러 회전을 사용할 것인지 여부로 해결할 수 있다.

 

에디터에서 보면 폰이 컨트롤러의 회전을 따라갈 것이냐 하는 bool 값 설정이 있는데 지금 카메라를 따라 회전하는 이유가 Yaw가 true이기 때문이다. 

 

이를 해결하기 전에 Pitch도 true로 설정하면 어떻게 되는지 보면 해당 기능이 뭔지 바로 감이 잡힌다.

문제가 보이는가? 

카메라가 상하로 회전하면 캐릭터도 같이 상하로 회전하면서 캐릭터가 땅바닥에 엎어지는 모습을 볼 수 있다.

 

즉, 저 값들을 true/false로 설정 여부에 따라 컨트롤러의 회전 값에 캐릭터가 영향을 받을 것인지 설정할 수 있다.

저 값들을 모두 false로 설정하면

1. 마우스 입력(IA_Look) & Input apping Context으로 HandleLookInput이 호출되고

2. 여기서 Controller의 회전 값이 변경되며

3. SpringArm은 Controller의 회전 값에 영향을 받아 카메라는 같이 회전하지만

4. Pawn은 Controller의 회전을 무시하므로 캐릭터는 카메라가 움직이는 방향으로 같이 움직이지 않는다.

 

이걸 명확히 하기 위해서 이동을 구현해서 테스트한다.

 

 

 

# 이동

1. UInputAction을 생성한다.

 

2. 이동과 관련된 함수 4종을 생성한다.

 

3. UEnhancedInputComponent에 바인딩한다.

 

 

4. HandleMoveInput 함수를 구현한다.

이동을 제대로 구현하기 위해서 

1). 대각선 이동 값이 커지지 않도록 정규화하고

2). 카메라의 기울기를 무시한 전방과 오른쪽 값을 계산한다.

 

카메라의 기울기를 무시하고 항상 전방을 구하기 위해서 벡터의 외적을 사용한다.

카메라의 오른쪽 방향 벡터는 (0, 1, 0), UpVector는 (0, 0, 1)이므로, 결과 값은 (1, 0, 0) 즉 전방이 나온다.

카메라의 회전에 따라 오른쪽 방향 벡터는 (-1, 0, 0)이 될 수도 있다. 이 때 전방 값은 (0, 1, 0)이 되므로 카메라가 어떤 방향을 바라보든 그 방향에 맞는 수평 전방 벡터를 정확하게 계산해준다.

 

 

5. 에디터에서 InputAction을 생성한다.

 

6. 캐릭터에서 UInputAction과 에디터에서 생성한 InputAction을 연결한다. 

 

 

7. InputMappingContext에 키보드와 매핑한다.

키는 WASD로 할 것인데, XY값에 따른 결과를 수정해줄 필요가 있다. 

일단은 키 매핑만 하고 수정은 하지 않은 채 플레이를 시작해 입력을 받아본다.

 

결과는 오른쪽으로, 양의 값(+1)으로 움직인다.

 

어떤 키를 입력해도 Y * (+1)이니 이제 이 값을 X로도 바꿥고 -1로도 바꿔보면 된다.

 

W와 D는 앞/뒤이므로 X축으로 움직여야 하고 W는 양수, D는 음수여야 한다.

 

A는 Y축으로 움직이는 것은 동일하나 지금 값에서 반전되어 음수여야 한다.

 

이 모든걸 반영하면 다음과 같다.

D키만 수정사항이 없다.

 

결과 확인

 

이동까지 키 입력을 받아서 잘 동작한다.

 

 

 

이제 아까 발생했던, 카메라 회전과 관계 없이 WASD키를 입력하면 캐릭터가 그 방향으로 회전하길 바란다면 두 가지 작업을 해줘야 한다.

 

 

1). 캐릭터가 움직임에 맞춰서 회전하는 기능을 활성화한다.

GetCharacterMovement()->bOrientRotationToMovement = true : 캐릭터의 움직임에 맞춰서 자동으로 회전해라

GetCharacterMovement()->RotationRate : 회전 속도 조절(얼마나 빠르게 회전할거냐)

Yaw(좌우) 값을 720도로 설정했는데, 이는 1초에 두 바퀴를 돌 정도로 매우 빠르게 회전하라는 뜻이다.

 

 

2). Pawn의 컨트롤러 회전을 비활성화 한다.

이렇게 하면, 마우스 이동 -> 컨트롤러 회전 -> 카메라 회전 -> Pawn 회전 무시

이므로, 마우스를 암만 회전시켜도 Pawn은 회전하지 않는다. 이제 키보드 입력으로 앞뒤좌우로 움직일 때만 회전한다.

 

 

 

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유