시작하기 전에
이전 섹션인 입력 액션으로 플레이어 캐릭터 생성하기에서 다음 목표를 완료했는지 확인합니다.
캐릭터 C++ 클래스를 생성했습니다.
입력 액션(Input Actions) 및 입력 매핑 컨텍스트(Input Mapping Contexts) 작동 방식을 학습했습니다.
입력과 무브먼트 링크 방법 배우기
캐릭터 블루프린트 샘플을 살펴보고 입력 액션, 입력 매핑 컨텍스트, 코드가 어떻게 결합하여 무브먼트를 생성하는지 알아봅니다. 그런 다음, 코드에서 그 함수 기능을 리플리케이트하는 방법을 배웁니다.
블루프린트에서 입력 시각화하기
1인칭 템플릿과 함께 제공되는 BP_FirstPersonCharacter 클래스는 블루프린트와 입력 액션이 어떻게 상호작용하는지 보여주는 좋은 예입니다.
콘텐츠 브라우저 에셋 트리에서 Content > FirstPerson > Blueprints로 이동합니다. BP_FirstPersonCharacter 클래스를 더블클릭하여 블루프린트 에디터에서 엽니다.
블루프린트의 이벤트 그래프(Event Graph)는 블루프린트 에디터 중앙에 있습니다. 이벤트 그래프는 게임플레이에 반응하여 이벤트와 함수 호출로 정렬된 일련의 액션을 순서대로 수행하는 노드 그래프입니다. 이 그래프에는 카메라 입력(Camera Input), 무브먼트 입력(Movement Input) 및 점프 입력(Jump Input)에 대한 노드 그룹이 있습니다.
점프 입력 로직 이해
점프 입력 그룹을 확대합니다. EnhancedInputAction IA_Jump 노드는 지난 단계에서 살펴본 IA_Jump 입력 액션 에셋을 나타냅니다.
입력 액션이 트리거되면 시작됨(Started) 및 트리거됨(Triggered) 이벤트를 발동합니다. 이 노드의 시작됨 이벤트는 Jump라는 함수 노드로 이어집니다. 이 블루프린트의 부모 캐릭터 클래스에는 점프 함수 기능이 내장되어 있으며, 이 함수는 버튼을 눌러 IA_Jump가 발동될 때마다 호출됩니다.
점프가 완료되면 이 노드는 완료됨(Completed) 이벤트를 트리거합니다. 이 이벤트는 또 다른 함수 노드인 Stop Jumping으로 이어지며, 이 노드 역시 캐릭터 클래스에서 상속됩니다.
점프 입력 로직은 터치 컨트롤도 추가하지만, 이 튜토리얼에서는 다루지 않습니다.
무브먼트 입력 로직 이해
다음으로 움직임 입력(Movement Input) 그룹을 살펴봅니다. 이 그룹 또한 입력 액션에 해당하는 IA_Move 노드로 시작합니다.
IA_Move 노드에는 IA_Move에 바인딩된 버튼이 눌리면 트리거되는 이벤트가 있습니다.
IA_Move에는 플레이어 입력에 의해 생성되는 X 및 Y 무브먼트 값인 액션 값 X(Action Value X)와 액션 값 Y(Action Value Y)도 포함되어 있습니다. X와 Y 값은 분리되어 있으므로 각 값을 캐릭터에 개별적으로 적용해야 합니다.
Move 노드는 캐릭터에 무브먼트를 적용하는 커스텀 함수 노드입니다. 노드와 디테일 패널에서 왼쪽/오른쪽(Left/Right) 및 전방/후방(Forward/Backward)이라는 두 개의 입력을 받고, IA_Move의 X 및 Y 무브먼트 값이 이러한 입력에 전달되는 것을 확인할 수 있습니다.
Move 노드를 더블클릭하거나 그래프 위의 이동(Move) 탭을 클릭하면 함수 내부의 로직을 확인할 수 있습니다.
이 함수는 입력 값이 있는 함수 엔트리 노드로 시작됩니다.
Left/Right 노드 그룹에는 World Direction 및 Scale Value, 이렇게 두 가지 값에 따라 캐릭터에 움직임을 추가하는 Add Movement Input 함수 노드가 포함되어 있습니다.
월드 방향은 캐릭터가 월드에서 향하고 있는 방향이며, 스케일 값은 적용할 무브먼트 양입니다. 이 노드는 왼쪽/오른쪽 무브먼트를 처리하므로, Get Actor Right Vector 함수 노드를 사용하여 먼저 월드 내 캐릭터 위치의 오른쪽 벡터를 구한 다음, Left / Right 입력(입력 액션의 X 값)을 스케일 값(Scale Value)으로 사용하여 그 벡터를 따라 무브먼트를 적용합니다.
Left / Right가 양수이면 캐릭터가 X축 위쪽, 즉 오른쪽으로 이동합니다. Left / Right가 음수이면 캐릭터가 X축 아래쪽, 즉 왼쪽으로 이동합니다.
Forward/Backward 그룹의 구성은 Left/Right 그룹과 같지만, 대신 Forward / Backward 입력(입력 액션의 Y 값)을 사용하여 액터의 전방 벡터(Forward Vector)를 따라 스케일 값을 결정합니다.
코드에서 이러한 노드를 복제하려면 노력을 조금 더 기울여야 하지만, 캐릭터가 움직이는 방식과 위치를 정밀하게 제어할 수 있습니다.
플레이어 컨트롤러로 플레이어에게 입력 할당하기
입력 매핑 컨텍스트(Input Mapping Context)가 플레이어 입력을 입력 액션에 매핑하지만, 해당 입력 컨텍스트도 플레이어에 연결해야 합니다. 디폴트 플레이어는 플레이어 컨트롤러(PlayerController) 클래스와 입력 서브시스템으로 이 작업을 수행합니다.
플레이어 컨트롤러 에셋은 사람 플레이어와 플레이어가 제어하는 게임 내 폰을 잇는 다리 역할을 합니다. 해당 에셋이 플레이어의 입력을 받아 처리하고 이를 명령으로 변환하면, 폰이 그 명령을 받고 게임 월드에서 그 무브먼트를 수행하는 방법을 알게 됩니다. 동일한 플레이어 컨트롤러를 사용하여 다른 폰을 제어할 수 있습니다.
플레이어 컨트롤러로는 다음과 같은 작업도 수행할 수 있습니다.
컷신 또는 메뉴 사용 중에 입력을 비활성화합니다.
점수 또는 기타 플레이어 데이터를 트래킹합니다.
UI 엘리먼트를 스폰하거나 숨깁니다.
플레이어 컨트롤러와 캐릭터를 분리하면 유연성과 데이터 지속성을 확보할 수 있습니다. 예를 들어, 플레이어가 사망했을 때처럼 플레이어 데이터나 입력 처리 로직을 잃지 않고 캐릭터를 전환할 수 있는 것은 해당 데이터와 정보가 플레이어 컨트롤러 내에 있기 때문입니다.
블루프린트에서 이를 구성하는 방법을 살펴보려면, 콘텐츠 브라우저의 Blueprints 폴더로 돌아가 BP_FirstPersonPlayerController 블루프린트를 엽니다.
플레이어 컨트롤러 클래스에는 향상된 입력 로컬 플레이어(Enhanced Input Local Player) 서브시스템이 있습니다. 이는 특정 로컬 플레이어에 붙어서 런타임에 해당 플레이어의 입력 컨텍스트와 매핑을 관리하는 서브시스템입니다. 이 서브시스템을 활용하면 어떤 입력이 활성화되는지 관리하고 런타임 시 입력 컨텍스트 간에 교체할 수 있습니다. UE 서브시스템에 대한 자세한 내용은 프로그래밍 서브시스템을 참조하세요.
게임이 시작되었을 때 향상된 입력 로컬 플레이어 서브시스템이 유효하면 매핑 컨텍스트 추가(Add Mapping Context)를 호출하여 IMC_Default 입력 매핑 컨텍스트를 플레이어의 입력 서브시스템에 바인딩합니다. 즉, 이 노드 그룹은 플레이어를 위해 이 입력 세트를 활성화합니다.
이 플레이어 컨트롤러 로직은 다른 무브먼트 로직과 별도의 블루프린트에 있지만, C++에서는 이 모든 것을 캐릭터 클래스 안에서 구현하므로 별도의 C++ 클래스가 필요하지 않습니다.
BP_FirstPersonCharacter의 이벤트 그래프는 폰이 빙의될 때까지 기다린 후 입력 매핑 컨텍스트를 적용하는 또 다른 방법을 보여줍니다. 이 접근 방식은 이 튜토리얼에서는 다루지 않지만, 직접 살펴볼 수는 있습니다.
캐릭터 클래스 구성하기
블루프린트에서 무브먼트가 작동하는 방식을 알아봤으니, 이제 코드로 빌드한 다음 레벨에서 캐릭터의 움직임을 테스트해 볼 차례입니다! 먼저 필요한 모든 모듈과 #include 구문을 추가한 다음, 캐릭터 무브먼트를 구현하는 데 필요한 클래스와 함수 및 프로퍼티를 선언합니다.
이 튜토리얼의 코드 예시에서는 AdventureGame이라는 프로젝트와 AdventureCharacter라는 캐릭터 클래스를 사용합니다.
향상된 입력 시스템 추가하기
언리얼 에디터에서 이미 향상된 입력 시스템(Enhanced Input System)이 활성화되었는지 확인했지만, 프로젝트의 Build.cs에서도 수동으로 선언하고 캐릭터 클래스에 특정 컴포넌트를 추가해야 합니다.
C++ 프로젝트에서 향상된 입력 시스템을 사용하려면 다음 단계를 따릅니다.
Visual Studio에서 프로젝트를 열고
[프로젝트명].Build.cs를 엽니다. 이 .cs 파일은 프로젝트의 다른 클래스 파일과 함께Source폴더에 있습니다.이 파일은 언리얼 엔진에 프로젝트 빌드에 필요한 모듈을 알려줍니다.
PublicDependencyModuleNames함수 호출에서 모듈 목록에"EnhancedInput"을 추가합니다.C++PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput" });Build.cs파일을 저장하고 닫습니다.
캐릭터 클래스에 향상된 입력 시스템 컴포넌트를 추가하려면 다음 단계를 따릅니다.
캐릭터의
.h파일을 엽니다. 파일 상단에 다음 include 구문을 추가합니다.#include "EnhancedInputComponent.h"구문은 향상된 입력 컴포넌트 모듈을 추가합니다.#include "InputActionValue.h"구문은 입력 액션에 의해 생성된 입력 액션 값에 액세스할 수 있게 합니다.#include "EnhancedInputSubsystems.h"구문은 로컬 플레이어 서브시스템에 액세스할 수 있게 합니다.
C++// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "EnhancedInputComponent.h" #include "EnhancedInputSubsystems.h" #include "InputActionValue.h" #include "AdventureCharacter.generated.h"추가하는 모든
#include구문은AdventureCharacter.generated.h구문 앞에 와야 합니다. 코드가 제대로 작동하려면, 이 구문이 입력 목록 끝에 있어야 합니다.#include구문 뒤에 다음의 새로운 클래스 세 개를 선언합니다.UInputMappingContextUInputActionUInputComponent
이 클래스는 이미 향상된 입력 모듈 내부에 존재합니다. 이렇게 기존 오브젝트를 선언하는 것을 포워드 선언이라고 하며, 컴파일러에 해당 클래스가 존재하고 이를 사용할 것임을 알려줍니다.
C++// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "EnhancedInputComponent.h" #include "EnhancedInputSubsystems.h" #include "InputActionValue.h" #include "AdventureCharacter.generated.h"
입력 매핑 컨텍스트 포인터 선언하기
캐릭터의 .h 파일의 protected 섹션에서 TObjectPtr을 사용하여 FirstPersonContext라는 이름의 새로운 UInputMappingContext 포인터를 추가합니다. 이는 입력 동작을 버튼 누르기에 링크하는 입력 매핑 컨텍스트(Input Mapping Context)에 대한 포인터입니다.
TObjectPtr은 언리얼 엔진의 스마트 포인터 래퍼로, UObject 파생 타입을 더 안전하게 참조할 수단입니다. 이는 에디터를 인지하며, 프리미티브 UObject 포인터의 대체제로서 가비지 컬렉션으로부터 안전합니다. TObjectPtr은 하드 레퍼런스이므로 런타임에 오브젝트를 계속 로드된 상태로 유지합니다. 언리얼 엔진으로 프로그래밍할 때는 이런 방식으로 포인터를 선언하는 것이 좋습니다.
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input)
TObjectPtr<UInputMappingContext> FirstPersonContext;U 접두사는 이 입력 매핑 컨텍스트가 UObject라는 의미입니다.
변수 선언 앞에 오는 UPROPERTY() 매크로는 언리얼 엔진에 해당 변수에 대해 알려줍니다. 언리얼 헤더 툴은 이 매크로를 사용하여 코드 관련 정보를 처리하며 변수에 액세스할 수 있는 위치, 에디터에서 변수가 표시되는 방식 등을 제어합니다.
이 포인터에는 다음 UPROPERTY 값이 있습니다.
EditAnywhere: 클래스의 디테일(Details) 패널에서 언리얼 에디터에 프로퍼티를 노출합니다.BlueprintReadOnly: 블루프린트가 이 프로퍼티에 액세스할 수는 있지만, 편집할 수는 없습니다.Category = Input: 프로퍼티가 클래스의 디테일 패널에서 입력(Input)이라는 섹션 아래에 표시됩니다. 카테고리는 코드를 정리하는 데 유용하며, 카테고리를 활용하면 에디터 탐색이 훨씬 쉬워집니다.
점프 및 이동 입력 액션 포인터 선언하기
또한, protected 섹션에 MoveAction 및 JumpAction이라고 명명한 두 개의 UInputAction 포인터를 추가합니다. 이는 IA_Jump 및 IA_Move 입력 액션에 대한 포인터입니다.
이 두 포인터에 UInputMappingContext와 동일한 UPROPERTY() 매크로를 지정합니다.
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input)
TObjectPtr<UInputMappingContext> FirstPersonContext;
// Move Input Actions
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input)
TObjectPtr<UInputAction> MoveAction;
Move() 함수 선언하기
입력 액션은 입력 액션 값을 생성하고, 이 값을 사용하여 캐릭터에 무브먼트를 적용하는 새 함수에 이 값을 전달해야 합니다.
파일의 public 섹션에서 Value라 명명된, const FInputActionValue 레퍼런스를 받는 Move()라는 이름으로 새 함수를 선언합니다.
// Handles 2D Movement Input
UFUNCTION()
void Move(const FInputActionValue& Value);함수 선언 앞에 오는 UFUNCTION() 매크로는 언리얼 헤더 툴이 함수를 인식하도록 해줍니다.
파일을 저장합니다. 이제 캐릭터의 헤더 파일이 다음과 같은 모습이어야 합니다.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InputActionValue.h"
#include "AdventureCharacter.generated.h"
class UInputMappingContext;
무브먼트 함수 구현
이제 캐릭터 무브먼트에 필요한 프로퍼티를 캐릭터의 .cpp에 선언했으니, 디폴트 캐릭터의 블루프린트에서 봤던 함수 기능을 모방하도록 함수를 디자인합니다.
Move() 함수 구성하기
캐릭터의 .cpp 클래스를 열고 Move()에 대한 새 함수 정의를 추가하여 .h 파일에서 선언한 함수를 구현합니다.
void AAdventureCharacter::Move(const FInputActionValue& Value)
{
) 디폴트 캐릭터의 입력 액션을 살펴볼 때 IA_Move의 값 타입이 Axis2D (Vector2D)였으므로, 트리거될 때 FVector2D 값을 반환한다는 것을 알 수 있습니다.
Move() 안에서 FInputActionValue의 값을 가져와 MovementValue라는 새 FVector2D 안에 저장합니다.
void AAdventureCharacter::Move(const FInputActionValue& Value)
{
// 2D Vector of movement values returned from the input action
const FVector2D MovementValue = Value.Get<FVector2D>();
}그런 다음, if 문을 추가하여 컨트롤러가 유효한지 확인합니다. Controller는 이 액터를 소유한 컨트롤러에 대한 포인터이며, 이 포인터가 유효해야 무브먼트가 작동합니다.
void AAdventureCharacter::Move(const FInputActionValue& Value)
{
// 2D Vector of movement values returned from the input action
const FVector2D MovementValue = Value.Get<FVector2D>();
// Check if the controller possessing this Actor is valid
if (Controller)
{
}
Move()로 2D 무브먼트 입력 추가하기
캐릭터 블루프린트에서 왼쪽, 오른쪽, 전방, 후방 무브먼트를 생성하기 위해 이벤트 그래프에 IA_Move의 액션 값 X와 액션 값 Y를 액터의 오른쪽 벡터 및 전방 벡터와 결합하여 무브먼트 입력을 추가했습니다. 이를 Move() 함수 내의 코드에서 구현할 것입니다.
if 문 내에서 GetActorRightVector()를 호출하여 액터의 오른쪽 벡터를 Right라는 새 FVector에 저장합니다.
const FVector Right = GetActorRightVector();그런 다음, AddMovementInput()을 호출하여 캐릭터에 무브먼트를 추가하고 Right와 MovementValue.X를 전달합니다.
AddMovementInput(Right, MovementValue.X);GetActorForwardVector()를 사용하여 전방 및 후방 무브먼트에 대해 이 프로세스를 반복하되, 이번에는 MovementValue.Y를 전달합니다.
완성된 Move() 함수는 다음과 같은 모습이어야 합니다.
void AAdventureCharacter::Move(const FInputActionValue& Value)
{
// 2D Vector of movement values returned from the input action
const FVector2D MovementValue = Value.Get<FVector2D>();
// Check if the controller posessing this Actor is valid
if (Controller)
{
// Add left and right movement
const FVector Right = GetActorRightVector();
SetupPlayerInputComponent로 무브먼트를 입력에 바인딩하기
다음으로, Move 함수를 앞서 선언한 FirstPersonContext 입력 매핑 컨텍스트에 링크합니다.
이를 위한 함수인 SetupPlayerInputComponent()는 이미 ACharacter에서 상속되었으므로 캐릭터의 .cpp 파일에 이미 정의되어 있습니다. 이 함수는 UInputComponent를 받아 플레이어 입력을 구성하는 데 사용합니다.
향상된 입력 컴포넌트 확인하기
기본적으로 이 함수는 캐릭터에 입력 컴포넌트가 있는지 확인하는 ACharacter의 SetupPlayerInputComponent() 함수를 호출하는 것으로 시작됩니다.
// Called to bind functionality to input
void AAdventure::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
}이 함수는 캐릭터에 일반 입력 컴포넌트가 있는지만 확인합니다. 그리고 여기서는 향상된 입력 컴포넌트가 있는지 확인해야 하므로 부모 클래스의 SetupPlayerInputComponent() 함수에 대한 이 호출을 삭제해야 합니다.
대신, if 구문에서 EnhancedInputComponent라는 이름으로 새 UEnhancedInputComponent 포인터를 선언합니다. 이를 이 함수에 전달된 PlayerInputComponent를 UEnhancedInputComponent로 캐스팅하면서 CastChecked()를 호출한 결과와 같게 설정합니다.
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
{
}무브먼트 액션 바인딩하기
if 문 내에서 EnhancedInputComponent로부터 BindAction() 함수를 호출합니다.
함수에 다음 실행인자를 전달합니다.
MoveAction: 캐릭터의.h파일에 선언된, 바인딩할 입력 액션입니다.ETriggeredEvent에서트리거된이벤트: 이벤트의 트리거 타입입니다.this: 바인딩할 대상 캐릭터입니다.Move(): 바인딩하려는 함수에 대한 레퍼런스입니다.
if (TObjectPtr<UEnhancedInputComponent> EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
{
// Bind Movement Actions
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AAdventureCharacter::Move);
}이제 IA_Move가 트리거되면 Move() 함수를 호출하여 캐릭터에 무브먼트를 추가합니다!
점프 액션 바인딩하기
다음으로 IA_Jump에 점프 시작과 점프 중지에 사용할 바인딩 두 개를 추가합니다.
다음 실행인자를 사용합니다.
.h파일에서 선언한 IA_Jump에 대한 입력 액션 포인터인JumpAction.Started및Completed트리거 이벤트.ACharacter 부모 클래스에서 상속되고 정의된
Jump및StopJumping함수.
// Bind Jump Actions
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Started, this, &ACharacter::Jump);
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);이제 SetupPlayerInputComponent() 함수는 다음과 같은 모습이어야 합니다.
// Called to bind functionality to input
void AAdventureCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
// Check the UInputComponent passed to this function and cast it to an UEnhancedInputComponent
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
{
// Bind Movement Actions
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AAdventureCharacter::Move);
// Bind Jump Actions
입력 매핑을 캐릭터에 바인딩하기
입력을 함수에 바인딩했지만, 여전히 입력 매핑 컨텍스트를 캐릭터에 바인딩해야 합니다. 게임이 시작될 때 입력이 구성되도록 캐릭터의 BeginPlay() 함수에서 이 작업을 수행합니다.
BeginPlay()는 부모 AActor 클래스의 가상 함수이며, 게임이 시작되거나 월드에서 액터가 스폰되고 완전히 초기화될 때 호출됩니다. 게임플레이 시작 시 해당 액터에 대해 한 번 실행되어야 하는 로직에 사용합니다.
진행하기 전에 BeginPlay()에서 글로벌 엔진 포인터가 null인지 확인합니다.
check(GEngine != nullptr);if 문 내에서 PlayerController라는 이름으로 새 APlayerController 포인터를 생성합니다. 컨트롤러(Controller)를 APlayerController로 캐스팅한 결과로 설정합니다.
// Get the player controller for this character
if (APlayerController* PlayerController = Cast<APlayerController>(Controller))
{
}if 문은 포인터가 null이 아닌 경우에만 실행이 진행되도록 보장합니다.
이제 향상된 입력 로컬 플레이어 서브시스템(Enhanced Input Local Player Subsystem)을 가져오고 .h 파일에서 선언한 FirstPersonContext 입력 매핑 컨텍스트를 서브시스템에 추가해야 합니다.
또 다른 if 문에서는 ULocalPlayer::GetSubsystem()을 호출하여 현재 플레이어를 전달해 Subsystem이라는 이름으로 새 UEnhancedInputLocalPlayerSubsystem 포인터를 생성합니다. 플레이어 컨트롤러(PlayerController)->GetLocalPlayer()를 호출하여 현재 플레이어를 가져올 수 있습니다.
if (APlayerController* PlayerController = Cast<APlayerController>(Controller))
{
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
{
}
}이 매핑 컨텍스트를 가장 높은 우선순위로 설정하려면 AddMappingContext()를 호출하여 서브시스템에 매핑 컨텍스트를 추가하고, 매핑 컨텍스트와 0의 우선순위를 전달합니다.
// Get the enhanced input local player subsystem and add a new input mapping context to it
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
{
Subsystem->AddMappingContext(FirstPersonContext, 0);
}마지막으로 새 디버그 메시지를 추가하여 커스텀 캐릭터(Character) 클래스가 사용되고 있는지 검증합니다.
BeginPlay() 함수는 다음과 같은 모습이어야 합니다.
// Called when the game starts or when spawned
void AAdventureCharacter::BeginPlay()
{
Super::BeginPlay();
check(GEngine != nullptr);
// Get the player controller for this character
if (APlayerController* PlayerController = Cast<APlayerController>(Controller))
{
Visual Studio에서 .h 헤더와 .cpp 구현 파일을 저장한 다음, Build를 클릭하여 프로젝트를 컴파일합니다.
캐릭터 블루프린트에서 변수 설정하기
이러한 무브먼트 컨트롤 설정을 완료하려면 캐릭터의 블루프린트를 사용하여 코드에서 선언한 변수에 에셋을 할당합니다.
캐릭터의 새 프로퍼티를 에셋으로 채우려면 다음 단계를 따릅니다.
아직 열리지 않았을 경우, 언리얼 에디터의 블루프린트 에디터에서 캐릭터 블루프린트를 엽니다.
디테일(Details) 패널의 입력(Input) 아래에서 다음 프로퍼티를 설정합니다.
1인칭 컨텍스트(First Person Context)를
IMC_Adventure로 설정합니다.이동 액션(Move Action)을
IA_Move로 설정합니다.점프 액션(Jump Action)을
IA_Jump로 설정합니다.
블루프린트를 저장하고 컴파일(Compile)을 클릭하여 컴파일합니다.
캐릭터 무브먼트 테스트하기
레벨 에디터 툴바(Level Editor Toolbar)에서 플레이(Play) 버튼을 클릭하여 에디터에서 플레이(Play In Editor) 모드를 시작합니다. 게임이 시작되면 화면에 'Hello World!'와 'We are using AdventureCharacter'라는 문구가 표시되어야 합니다. WASD 또는 화살표 키를 사용하여 이동하고 스페이스 바를 사용하여 점프할 수 있어야 합니다!
다음 순서
움직이는 캐릭터는 있지만, 아직 제대로 된 메시와 카메라가 없습니다. 다음 섹션에서는 카메라 컴포넌트를 만들고, 캐릭터에 바인딩하고, 스켈레탈 메시를 추가하여 실제 1인칭 뷰포인트를 얻는 방법을 알아보겠습니다!
1인칭 카메라, 메시 및 애니메이션 추가
C++를 사용하여 1인칭 캐릭터에 메시와 카메라 컴포넌트를 붙이는 방법을 알아봅니다.
완성된 코드
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InputActionValue.h"
#include "AdventureCharacter.generated.h"
class UInputMappingContext;
#include "AdventureCharacter.h"
// Sets default values
AAdventureCharacter::AAdventureCharacter()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Fill out your copyright notice in the Description page of Project Settings.
using UnrealBuildTool;
public class AdventureGame : ModuleRules
{
public AdventureGame(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;