Unreal5 Enhanced Input 캐릭터 이동 및 점프 C++
- 프로그래밍/언리얼
- 2023. 4. 29.
Unreal5 Enhanced input 캐릭터 이동 및 점프 C++
오늘은 언리얼5에서 EnHanced input을 사용해서 캐릭터 이동과 점프를 구현해 보겠습니다.
그냥 공부한 내용 대충 작성하는거라 효율이랑은 거리가 멀겁니다.
- 캐릭터 만들기.
- Input Action & Mapping 생성
- C++ SlayerCharacter.h 코드 작성.
- Enhanced Input Module추가
- C++ SlayerCharacter.cpp 코드 작성.
- 마지막 설정.
캐릭터 만들기.
캐릭터 C++코드를 생성하고 이름을 SlayerCharacter로 설정했습니다.
이후 Blueprint파일을 하나 만들어 SlayerCharacter를 상속한 BP_SlayerCharacter를 만들었습니다.
BP_SlayerCharacter에서 Skeletal Mesh Asset을 적당한 것을 찾아 선택하였습니다.
InputAction & Mappping 생성
Enhanced input을 사용하기 위해 InputAction과 InputMappingContext를 생성했습니다.
Input Action은 IA_라는 이름을 사용했고, InputMappingContext는 IMC_라는 이름을 사용했습니다.
IA_Jump=bool, IA_Movement=Axis2D(Vector2D).
아래 사진은 공식 문서에 나온 내용입니다.
위의 내용을 참고해 InputMappingContext를 구성하였습니다.
C++ SlayerCharacter.h 코드 작성.
SlayerCharacter.h의 protected부분에 코드를 추가하고 설정한 input을 눌렀을 때 작동할 함수를 선언하였습니다.
FInputActionValue는 UnrealEngine에서 제공하는 클래스 중 하나로, 사용자 입력 이벤트를 나타냅니다.
https://docs.unrealengine.com/4.26/en-US/API/Plugins/EnhancedInput/FInputActionValue/
사용하기 위해서는 inputActionValue.h를 import해줘야 하고, EnhancedInput모듈이 필요합니다.
/*Enhanced input*/
//#include "InputActionValue.h" 를 추가해줘야함.
UPROPERTY(EditAnywhere, Category=Input)
UInputMappingContext* SlayerContext;
UPROPERTY(EditAnywhere, Category = Input)
UInputAction* MovementAction;
UPROPERTY(EditAnywhere, Category = Input)
UInputAction* JumpAction;
void Move(const FInputActionValue& value);
void Jump() override;
이후 UCLASS()윗부분에 class UInputMappingContext, class UInputAction을 추가하였습니다.
class UInputMappingContext;
class UInputAction;
.h파일의 전체 코드는 다음과 같습니다.
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "InputActionValue.h"
#include "SlayerCharacter.generated.h"
class UInputMappingContext;
class UInputAction;
UCLASS()
class SLAYER_API ASlayerCharacter : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
ASlayerCharacter();
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
/*Enhanced input*/
//#include "InputActionValue.h"
UPROPERTY(EditAnywhere, Category=Input)
UInputMappingContext* SlayerContext;
UPROPERTY(EditAnywhere, Category = Input)
UInputAction* MovementAction;
UPROPERTY(EditAnywhere, Category = Input)
UInputAction* JumpAction;
void Move(const FInputActionValue& value);
void Jump() override;
};
Enhanced Input Module 추가.
헤더파일의 코드는 작성했는데 아직 빨간 줄이 보이네요.
모듈추가를 아직 안 해서 그런 것 같습니다.
언리얼 5.1이면 자동으로 추가되는 줄 알았는데 제 컴퓨터는 해당되지 않나봅니다...ㅎㅎ
Slayer.Build.cs로 이동해서 PublicDependencyModuleNames.AddRange에 "EnhancedInput"을 추가하겠습니다.
이제 프로젝트 경로로 이동해 줍니다.
저는 E:\UReal\Slayer위치에 있습니다.
해당 위치에서 Binaries, Intermediate, saved폴더를 삭제합니다.
이후 Slayer.uproject를 우클릭해서 "Generate Visual Studio project files"를 눌러줍니다.
C++ SlayerCharacter cpp 코드 작성.
먼저 헤더파일에서 작성한 함수 정의를 해줍니다.
이제 이걸 C++로 구현해 주면 됩니다.
Begin play()에 이렇게 작성했습니다.
//#include "EnhancedInputSubsystems.h" 추가 필요.
if (APlayerController* PlayerController = Cast<APlayerController>(GetController())) {
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer())) {
Subsystem->AddMappingContext(SlayerContext, 0);
}
}
점프는 그냥 구현된 것을 사용하겠습니다.
void ASlayerCharacter::Jump()
{
Super::Jump(); //Character.h에 있는 Jump사용.
}
https://docs.unrealengine.com/4.27/en-US/API/Runtime/Engine/GameFramework/ACharacter/Jump/
Move함수(움직임) 구현.
const FVector2D MovementVector = value.Get<FVector2D>();
const FRotator Rotation = Controller->GetControlRotation();
const FRotator YawRotation(0.f, Rotation.Yaw, 0.f);
const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
AddMovementInput(ForwardDirection, MovementVector.Y);
const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
AddMovementInput(RightDirection, MovementVector.X);
기능은 다 만들었으니까 이제 bind 해주겠습니다.
SetupPlayerInputComponent에서 아래 코드들을 입력해서 bind 해줍니다.
//#include "EnhancedInputComponent.h"추가.
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent)) {
EnhancedInputComponent->BindAction(MovementAction, ETriggerEvent::Triggered, this, &ASlayerCharacter::Move);
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ASlayerCharacter::Jump);
}
https://docs.unrealengine.com/4.26/en-US/API/Plugins/EnhancedInput/UEnhancedInputComponent/
마지막 설정.
visual studio작업이 다 끝나면 빌드하고 실행해 줍니다.
Blueprint에서 캐릭터가 옆을 보고 있길래 Rotation좀 수정해 주고, IA_어쩌고랑, IMC_어쩌고로 저장했던 것을 추가해 주었습니다.
앞, 뒤, 양옆 모두 잘 움직이고 점프도 잘 되지만 고개가 돌아가지 않고 카메라도 캐릭터에 파묻혀있네요.
이건 카메라 추가해서 하고, 코드 좀 추가하면 되는 건데.. 생각보다 글이 길어져서 여기까지 하겠습니다.
전체 코드.
SlayerCharacter.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "InputActionValue.h"
#include "SlayerCharacter.generated.h"
class UInputMappingContext;
class UInputAction;
UCLASS()
class SLAYER_API ASlayerCharacter : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
ASlayerCharacter();
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
/*Enhanced input*/
//#include "InputActionValue.h"
UPROPERTY(EditAnywhere, Category=Input)
UInputMappingContext* SlayerContext;
UPROPERTY(EditAnywhere, Category = Input)
UInputAction* MovementAction;
UPROPERTY(EditAnywhere, Category = Input)
UInputAction* JumpAction;
void Move(const FInputActionValue& value);
void Jump() override;
};
SlayerCharacter.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "Character/SlayerCharacter.h"
#include "EnhancedInputSubsystems.h"
#include "EnhancedInputComponent.h"
// Sets default values
ASlayerCharacter::ASlayerCharacter()
{
// 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;
}
// Called when the game starts or when spawned
void ASlayerCharacter::BeginPlay()
{
Super::BeginPlay();
//#include "EnhancedInputSubsystems.h" 추가 필요.
if (APlayerController* PlayerController = Cast<APlayerController>(GetController())) {
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer())) {
Subsystem->AddMappingContext(SlayerContext, 0);
}
}
}
void ASlayerCharacter::Move(const FInputActionValue& value)
{
const FVector2D MovementVector = value.Get<FVector2D>();
const FRotator Rotation = Controller->GetControlRotation();
const FRotator YawRotation(0.f, Rotation.Yaw, 0.f);
const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
AddMovementInput(ForwardDirection, MovementVector.Y);//이동
const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
AddMovementInput(RightDirection, MovementVector.X);//이동
}
void ASlayerCharacter::Jump()
{
Super::Jump(); //Character.h에 있는 Jump사용.
}
// Called every frame
void ASlayerCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void ASlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
//#include "EnhancedInputComponent.h"추가.
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent)) {
EnhancedInputComponent->BindAction(MovementAction, ETriggerEvent::Triggered, this, &ASlayerCharacter::Move);
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ASlayerCharacter::Jump);
}
}