[UE5 / C++] ๐Ÿ•น๏ธ C++๋กœ ์บ๋ฆญํ„ฐ ์กฐ์ž‘ ๊ตฌํ˜„ํ•˜๊ธฐ (ๅฎŒ)

Singery00ยท2024๋…„ 4์›” 15์ผ
0

UE5 C++

๋ชฉ๋ก ๋ณด๊ธฐ
5/20
post-thumbnail

๊ฐœ์š”

๐Ÿ’ก C++๋กœ ํ”Œ๋ ˆ์ด์–ด์˜ ์บ๋ฆญํ„ฐ๋ฅผ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด ๋ณด์ž.

C++์„ ์‚ฌ์šฉํ•ด์„œ ํ”Œ๋ ˆ์ด์–ด์˜ ์บ๋ฆญํ„ฐ์—๊ฒŒ W,A,S,D์™€ Space, ๋งˆ์šฐ์Šค๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ•„์ˆ˜์ ์ธ ์กฐ์ž‘์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด๋ฒˆ์—๋Š” Enhanced Input System์„ ์‚ฌ์šฉํ•ด์„œ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

1. Old Input System์œผ๋กœ ์กฐ์ž‘ ๊ตฌํ˜„
2. Enhanced Input System์œผ๋กœ ์กฐ์ž‘ ๊ตฌํ˜„


๋ณธ๋ก 

์บ๋ฆญํ„ฐ๋ฅผ ์กฐ์ž‘ํ•˜๊ธฐ ์œ„ํ•œ Key ์ถ”๊ฐ€๋Š” Blueprint๋กœ ๊ตฌํ˜„ํ•  ๋•Œ์™€ ๋™์ผํ•˜๊ฒŒ Unreal ์—๋””ํ„ฐ์—์„œ ์ง„ํ–‰ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ‚ค ๋งŒ๋“ค๊ธฐ

Input Action ์ƒ์„ฑ

IA_Move, IA_Look,_IA_Jump 3๊ฐœ๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ์„ธ์š”.

Input Mapping Context ์ƒ์„ฑ

์•„๋ž˜ ์‚ฌ์ง„๊ณผ ๊ฐ™์ด ์„ค์ •ํ•ด์ฃผ์„ธ์š”.

ํ—ค๋”ํŒŒ์ผ ์ˆ˜์ •

InputActionValue ์ถ”๊ฐ€

ํ—ค๋”ํŒŒ์ผ์˜ ์ƒ๋‹จ์— InputActionValue.h๋ฅผ includeํ•ด์ฃผ์„ธ์š”

#include "InputActionValue.h"
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "MyPlayer.generated.h"

ํ•จ์ˆ˜ ๋˜ํ•œ ๋ณ€์ˆ˜์™€ ๊ฐ™์ด ํ—ค๋”ํŒŒ์ผ์—์„œ ์„ ์–ธ ํ›„ ์ •์˜ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์นฉ๋‹ˆ๋‹ค.

GENERATED_BODY ์˜ค๋ฅ˜

์œ„์—์„œ ํ—ค๋” ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•˜๋ฉด GENERATED_BODY()๊ฐ€ ๋นจ๊ฐ„์ค„์ด ์ง ๊ทธ์ด๋ฉด์„œ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜ํƒ€๋‚  ๊ฒ๋‹ˆ๋‹ค.

์ƒ์„ธํ•œ ๋‚ด์šฉ์€ ๋”ฐ๋กœ ํฌ์ŠคํŒ…์„ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋นŒ๋“œ ํ›„ ์–ธ๋ฆฌ์–ผ๊ณผ ์—ฐ๋™ํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

IA ๋ณ€์ˆ˜ ์ถ”๊ฐ€

์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•  ํ‚ค์ž…๋ ฅ์— ๋Œ€ํ•œ Input Action์„ ๋ฐ›์•„์˜ฌ ๋ณ€์ˆ˜๋“ค์„ ์ƒ์„ฑํ•ด์ค๋‹ˆ๋‹ค.

๋˜ํ•œ IA๋“ค์„ ๋ฌถ์–ด์„œ ๊ด€๋ฆฌํ•ด์ค„ IMC ๋ณ€์ˆ˜๋„ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

private:
	// IMC
	UPROPERTY(editanywhere,category=input, meta=(allowprivateaccess = true))
	class UInputMappingContext* DefaultMappingContext;
	// IA_Jump
	UPROPERTY(editanywhere,category=input, meta = (allowprivateaccess = true))
	class UInputAction* JumpAction;
	// IA_Look
	UPROPERTY(editanywhere,category=input, meta = (allowprivateaccess = true))
	class UInputAction* LookAction;
	// IA_Move
	UPROPERTY(editanywhere,category=input, meta = (allowprivateaccess = true))
	class UInputAction* MoveAction;

๋ฐ”์ธ๋”ฉ ํ•จ์ˆ˜ ์ถ”๊ฐ€

๊ฐ ํ‚ค์ž…๋ ฅ์— ๋Œ€ํ•ด์„œ ์‹คํ–‰๋  ํ•จ์ˆ˜๋“ค์„ ์„ ์–ธํ•ด์ฃผ์„ธ์š”.

	void Move(const FInputActionValue& value);
	void Look(const FInputActionValue& value);
	void Jump() override;

์†Œ์ŠคํŒŒ์ผ ์ˆ˜์ •

ํ—ค๋” ์ถ”๊ฐ€

์†Œ์Šค ํŒŒ์ผ์— ์•„๋ž˜์˜ ํ—ค๋” 3๊ฐœ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”.

#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InputMappingContext.h"

์•„๋งˆ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜์„œ ์ถ”๊ฐ€๊ฐ€ ์•ˆ๋˜์‹œ๋Š” ๋ถ„๋“ค์ด ๊ณ„์‹ค ์ˆ˜ ์žˆ๋Š”๋ฐ ์ผ๋‹จ ๋‹นํ™ฉํ•˜์ง€ ๋งˆ์‹œ๊ณ  ์ด์–ด์„œ ์ž‘์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ž…๋ ฅ ๋งคํ•‘ ๋กœ๋“œ

์ƒ์„ฑํ•œ IA๋ณ€์ˆ˜๋“ค์— ๋Œ€ํ•ด์„œ ํ”„๋กœ์ ํŠธ ๋‚ด์—์„œ ์ •์˜๋œ ์ž…๋ ฅ ๋งคํ•‘ ์ปจํ…์ŠคํŠธ์™€ ์ž…๋ ฅ ์•ก์…˜๋“ค์„ ๋กœ๋“œํ•ด์„œ ์ฐธ์กฐ๋ฅผ ํ• ๋‹นํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ”Œ๋ ˆ์ด์–ด์˜ ์ƒ์„ฑ์ž ๋ถ€๋ถ„์—์„œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.

AMyPlayer::AMyPlayer()
{
	// ์ƒ๋žต

	static ConstructorHelpers::FObjectFinder<UInputMappingContext>DEFAULT_CONTEXT(TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/IMC_Player.IMC_Player'"));
	
	static ConstructorHelpers::FObjectFinder<UInputAction>IA_MOVE(TEXT("/Script/EnhancedInput.InputAction'/Game/Input/IA_Move.IA_Move'"));
	static ConstructorHelpers::FObjectFinder<UInputAction>IA_JUMP(TEXT("/ Script / EnhancedInput.InputAction'/Game/Input/IA_Jump.IA_Jump'"));
	static ConstructorHelpers::FObjectFinder<UInputAction>IA_LOOK(TEXT("/ Script / EnhancedInput.InputAction'/Game/Input/IA_Look.IA_Look'"));

	if (DEFAULT_CONTEXT.Succeeded())
	{
		DefaultMappingContext = DEFAULT_CONTEXT.Object;
	}

	if (IA_MOVE.Succeeded())
	{
		MoveAction = IA_MOVE.Object;
	}
	
	if (IA_JUMP.Succeeded())
	{
		JumpAction = IA_JUMP.Object;
	}

	if (IA_LOOK.Succeeded())
	{
		LookAction = IA_LOOK.Object;
	}

}

Enhanced Input Local Player Subsystem

์ €ํฌ๊ฐ€ ๋ธ”๋ฃจํ”„๋ฆฐํŠธ๋กœ Enhanced Input์„ ๊ตฌํ˜„ํ•  ๋•Œ ์•„๋ž˜ ์‚ฌ์ง„์ฒ˜๋Ÿผ ๊ตฌํ˜„ํ•œ ๊ฒƒ์„ ๊ธฐ์–ต๋‚˜์‹œ๋‚˜์š”?

์ด๊ฑธ ์ง์ ‘ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
BeginPlay()์—์„œ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.

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

	if (APlayerController* PlayerController = Cast<APlayerController>(GetController()))
	{
		if (UEnhancedInputLocalPlayerSubsystem* SubSystem =
			ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
		{
			SubSystem->AddMappingContext(DefaultMappingContext, 0);
		}
	}
}

์ฝ”๋“œ๋งŒ ๋ณด๊ณ  ๋”ฐ๋ผํ•˜์‹ ๋‹ค๋ฉด ์ด๊ฒŒ ๋ญ์•ผ.. ํ•˜์‹ค ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ ๊ฐ ์ฝ”๋“œ ํ•œ์ค„ ํ•œ์ค„์ด ๋ธ”๋ฃจํ”„๋ฆฐํŠธ ์‚ฌ์ง„๊ณผ ๋น„๊ตํ•ด๋ณด์‹œ๋ฉด ๋”ฑ ๋Š๋‚Œ์ด ์˜ค์‹ค ๊ฒ๋‹ˆ๋‹ค.

ํ•จ์ˆ˜ ๋ฐ”์ธ๋”ฉ

ํ‚ค ์ž…๋ ฅ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•˜์˜€์œผ๋‹ˆ ์ž…๋ ฅ๊ณผ ์‹คํ–‰๋  ํ•จ์ˆ˜๋ฅผ ๋ฐ”์ธ๋”ฉ ํ•ด์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

SetupPlayerInputComponent๋กœ ์ด๋™ํ•ด์„œ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.

void AMyPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);


	if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
	{
		EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyPlayer::Move);
		EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &AMyPlayer::Look);
		EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &AMyPlayer::Jump);
	}

}

Move() ๊ตฌํ˜„

Move ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
์ƒ์„ธํ•œ ์„ค๋ช…์€ ์ฃผ์„์œผ๋กœ ๋Œ€์ฒดํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

void AMyPlayer::Move(const FInputActionValue& Value)
{
	// ์ด๋™์— ์‚ฌ์šฉ๋  ๋ฐฉํ–ฅ๊ณผ ์†๋„๋ฅผ ๋‚˜ํƒ€๋ƒ„
	const FVector2D MovementVector = Value.Get<FVector2D>();
	// ํ”Œ๋ ˆ์ด์–ด์˜ ํ˜„์žฌ ๋ฐฉํ–ฅ
	const FRotator Rotation = Controller->GetControlRotation();
	// Yaw๋งŒ์„ ์‚ฌ์šฉํ•ด ์ƒˆ๋กœ์šด ํšŒ์ „ ์ƒ์„ฑ
	const FRotator YawRotation(0.f, Rotation.Yaw, 0.f);
	// YawํšŒ์ „์„ ๊ธฐ์ค€์œผ๋กœ ์ „๋ฐฉ ๋ฐฉํ–ฅ ๊ณ„์‚ฐ
	const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
	// ์ „๋ฐฉ ๋ฐฉํ–ฅ๊ณผ Y๊ฐ’(์ „๋ฐฉ ์ด๋™์†๋„)์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋™
	AddMovementInput(ForwardDirection, MovementVector.Y);
	// YawํšŒ์ „์„ ๊ธฐ์ค€์œผ๋กœ ์šฐ์ธก ๋ฐฉํ–ฅ ๊ณ„์‚ฐ
	const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
	// ์šฐ์ธก ๋ฐฉํ–ฅ๊ณผ X๊ฐ’(์šฐ์ธก ์ด๋™์†๋„)์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋™
	AddMovementInput(RightDirection, MovementVector.X);
}

Look() ๊ตฌํ˜„

Lookํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

Yaw์™€ Pitch๋ฅผ ์กฐ์ ˆํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

void AMyPlayer::Look(const FInputActionValue& Value)
{
	// ํšŒ์ „๋Ÿ‰
	const FVector2D LookVector = Value.Get<FVector2D>();
	// X๊ฐ’(์ˆ˜ํ‰ ํšŒ์ „๋Ÿ‰)์„ ์‚ฌ์šฉํ•ด yawํšŒ์ „ ์ถ”๊ฐ€ > ์ˆ˜ํ‰ ์‹œ์„  ํšŒ์ „
	AddControllerYawInput(LookVector.X);
	// Y๊ฐ’(์ˆ˜์ง ํšŒ์ „๋Ÿ‰)์„ ์‚ฌ์šฉํ•ด pitchํšŒ์ „ ์ถ”๊ฐ€ > ์ˆ˜์ง ์‹œ์„  ํšŒ์ „
	AddControllerPitchInput(LookVector.Y);
}

Jump() ๊ตฌํ˜„

Jump๋Š” ์บ๋ฆญํ„ฐ์— ์žˆ๋Š” ์ ํ”„๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

void AMyPlayer::Jump()
{
	Super::Jump();
}

์—ฌ๊ธฐ๊นŒ์ง€๋กœ ๊ตฌํ˜„์€ ๋ชจ๋‘ ๋๋‚ฌ์Šต๋‹ˆ๋‹ค.
๊ทผ๋ฐ ๋นจ๊ฐ„์ค„์ด ๊ณณ๊ณณ์— ๊ทธ์—ฌ ๊ณ„์‹  ๋ถ„๋“ค์ด ๊ณ„์‹ค๊ฒ๋‹ˆ๋‹ค.


์˜ค๋ฅ˜ ํ•ด๊ฒฐ

๋ชจ๋“ˆ ์ถ”๊ฐ€

๋ณธ์ธ ํ”„๋กœ์ ํŠธ์˜ Games - Config - Source - <ํ”„๋กœ์ ํŠธ๋ช… ํŒŒ์ผ>๋กœ ์ด๋™ํ•˜๋ฉด ํ”„๋กœ์ ํŠธ๋ช….Build.cs๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
ํ•ด๋‹น ํŒŒ์ผ์„ ์—ด์–ด์ฃผ์„ธ์š”.

๊ทธ๋ฆฌ๊ณ  EnhancedInput์„ ์ถ”๊ฐ€๋กœ ์ ์–ด์ฃผ์„ธ์š”.

ํ•„์š”ํ•œ ๋ชจ๋“ˆ์„ ์ถ”๊ฐ€ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์ถ”ํ›„ ํ™”๋ฉด์— ํ‘œ์‹œ๋  ์œ„์ ฏ์„ ์‚ฌ์šฉํ•  ๋• UMG๋ฅผ ์ถ”๊ฐ€๋กœ ์ ์–ด ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

  1. ๊ป๋‹ค ์ผœ๋ณด์„ธ์š”. ์ด๊ฑฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

  2. ๋‹ค์‹œ ๋นŒ๋“œ๋ฅผ ํ•ด๋ณด์„ธ์š”.

  3. ํ”„๋กœ์ ํŠธ ํŒŒ์ผ๋กœ ์ด๋™ํ•ด์„œ ํ”„๋กœ์ ํŠธ.exe๋ฅผ ์šฐํด๋ฆญํ•ด์„œ Generate Visual Studio project files๋ฅผ ํ•ด์ฃผ์„ธ์š”.

์ปดํ“จํ„ฐ๊ฐ€ ๊ฐ€๋” ๊ฑฐ์ง“๋ง์„ ํ•ฉ๋‹ˆ๋‹ค...

โ—์ €์žฅ ํ›„ ์‹คํ–‰โ—ํ•ด๋ณด๋ฉด ํ”Œ๋ ˆ์ด์–ด๋ฅผ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๋งˆ๋ฌด๋ฆฌ

์บ๋ฆญํ„ฐ์—๊ฒŒ Enhanced Input System์„ ์‚ฌ์šฉํ•ด์„œ ๊ธฐ์ดˆ์ ์ธ ์›€์ง์ž„์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

์›์ธ์„ ์•Œ ์ˆ˜๋„ ์—†๋Š” ์—๋Ÿฌ๊ฐ€ ๋งˆ๊ตฌ๋งˆ๊ตฌ ๋‚˜ํƒ€๋‚˜์„œ ์›์ธ์„ ํŒŒ์•…ํ•˜๊ณ ์ž ๋งŽ์ด ์—ฐ๊ตฌํ•ด ๋ณผ ์ˆ˜ ์žˆ๋Š” ์‹œ๊ฐ„์ด์˜€์Šต๋‹ˆ๋‹ค.

์–ธ๋ฆฌ์–ผ ์—”์ง„์˜ ๋ฒ„์ „์— ๋”ฐ๋ผ, ๋˜ Visual Studio์˜ ๋ฒ„์ „์— ๋”ฐ๋ผ ๋ชจ๋‘ ๋‹ค๋ฅด๊ฒŒ ๋‚˜ํƒ€๋‚˜๋Š” ์—๋Ÿฌ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

1. Old Input System์œผ๋กœ ์กฐ์ž‘ ๊ตฌํ˜„
2. Enhanced Input System์œผ๋กœ ์กฐ์ž‘ ๊ตฌํ˜„

profile
๊ฒŒ์ž„ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜์–ด๋ณด์ž

0๊ฐœ์˜ ๋Œ“๊ธ€