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

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

UE5 C++

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

๊ฐœ์š”

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

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

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

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


๋ณธ๋ก 

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

Key ๋“ฑ๋ก

ํˆด๋ฐ” - Edit - Project Settings - Engine - Input์œผ๋กœ ์ด๋™ํ•˜์—ฌ ์•„๋ž˜ ์‚ฌ์ง„๊ณผ ๊ฐ™์ด ์ด๋™, ๋งˆ์šฐ์Šค ํšŒ์ „, ์ ํ”„์— ๋Œ€ํ•œ ํ‚ค๋ฅผ ๋“ฑ๋กํ•ด์ค๋‹ˆ๋‹ค.

๋งˆ์šฐ์Šค ํšŒ์ „ ์ฒ˜๋ฆฌ

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

ํ•จ์ˆ˜ ์ •์˜

๊ฐ๊ฐ ์ž…๋ ฅ์— ๋ฐ”์ธ๋”ฉํ•ด ์ค„ ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

public:
	void LookUp(float value);
	void Turn(float value);

๋ฐ”์ธ๋”ฉ ์ฒ˜๋ฆฌ

SetupPlayerInputComponent ํ•จ์ˆ˜๋Š” ACharacter ํด๋ž˜์Šค๋กœ๋ถ€ํ„ฐ ์ƒ์†๋œ ๋ฉค๋ฒ„ ํ•จ์ˆ˜๋กœ ํ”Œ๋ ˆ์ด์–ด์˜ ์ž…๋ ฅ์„ ๋ฐ›์•„๋“ค์ด๊ณ  ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

SetupPlayerInputComponent ํ•จ์ˆ˜์—์„œ ๋ฐ”์ธ๋”ฉ์— ๋Œ€ํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

๋งˆ์šฐ์Šค ํšŒ์ „์€ Axis Mappings์—์„œ ์ฒ˜๋ฆฌํ–ˆ์œผ๋‹ˆ BindAxis๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๊ฐ๊ฐ์˜ ์ธ์ž๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. Input์—์„œ ๋“ฑ๋กํ•œ ์ด๋ฆ„
  2. ๋Œ€์ƒ Object
  3. ๋ฐ”์ธ๋”ฉํ•ด ์ค„ ํ•จ์ˆ˜๋ช…
// Called to bind functionality to input
void AMyPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	PlayerInputComponent->BindAxis(TEXT("LookUp"), this, &AMyPlayer::LookUp);
	PlayerInputComponent->BindAxis(TEXT("Turn"), this, &AMyPlayer::Turn);

}

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

์ƒํ•˜๋Š” Pitch
์ขŒ์šฐ๋Š” Yaw
๊ฐ๊ฐ ํ•ด๋‹นํ•˜๋Š” AddControllerInputํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์„œ value๋ฅผ ๋„ฃ์–ด ์ค๋‹ˆ๋‹ค.

void AMyPlayer::LookUp(float value)
{
	AddControllerPitchInput(value);
}

void AMyPlayer::Turn(float value)
{
	AddControllerYawInput(value);
}

โ—์ €์žฅ ํ›„ ์‹คํ–‰โ—ํ•ด๋ณด๋ฉด ์ขŒ์šฐํšŒ์ „์€ ๊ฐ€๋Šฅํ•˜๋‚˜ ์ƒํ•˜ํšŒ์ „์ด ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

bUsePawnControlRotation ์„ค์ •

์ด๋Š” SpringArmComp์˜ bUsePawnControlRotation์ด false๋กœ ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ด์ „ ํฌ์ŠคํŒ…์—์„œ ์ถ”๊ฐ€ํ–ˆ๋˜ springArmComp์— ์ถ”๊ฐ€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์ค๋‹ˆ๋‹ค.

springArmComp->bUsePawnControlRotation = true;

๋‹ค์‹œ โ—์ €์žฅ ํ›„ ์‹คํ–‰โ—ํ•ด๋ณด๋ฉด ๋ชจ๋‘ ์ž˜ ๋ฉ๋‹ˆ๋‹ค.
ํ˜น์‹œ ์ƒํ•˜๊ฐ€ ๋ฐ˜๋Œ€๋กœ ์›€์ง์ธ๋‹ค๋ฉด Key Mapping์—์„œ ๊ฐ’์ด ๋ฐ˜๋Œ€๋กœ ๋“ค์–ด๊ฐ€์ง€ ์•Š์•˜๋Š”์ง€ ํ™•์ธํ•ด์ฃผ์„ธ์š”.


์ด๋™ ์ฒ˜๋ฆฌ

์ด๋™๋„ ๋™์ผํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

  1. ๋ฐ”์ธ๋”ฉํ•  ํ•จ์ˆ˜ ์„ ์–ธ
  2. ํ‚ค์™€ ํ•จ์ˆ˜ ๋ฐ”์ธ๋”ฉ
  3. ๋ฐ”์ธ๋”ฉ ํ•จ์ˆ˜ ์ •์˜

3๋‹จ๊ณ„๋ฅผ ๊ฑฐ์น˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

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

ํ”Œ๋ ˆ์ด์–ด์˜ ์ด๋™์†๋„์™€ ์ด๋™๋ฐฉํ–ฅ์„ ์ €์žฅํ•˜๊ณ  ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•ด์„œ walkSpeed์™€ direction ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

	UPROPERTY(EditAnywhere,Category = PlayerSetting)
	float walkSpeed = 600;

	FVector direction;

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

์•ž๋’ค ์ด๋™ W,S์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ InputHorizontal ํ•จ์ˆ˜์™€

์ขŒ์šฐ ์ด๋™ D,A์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ Input Vertical ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

	void InputHorizontal(float vlaue);
	void InputVertical(float vlaue);

๋ฐ”์ธ๋”ฉ ์ฒ˜๋ฆฌ

์—ญ์‹œ ํ”ŒSetupPlayerInputComponent ํ•จ์ˆ˜์—์„œ ๋ฐ”์ธ๋”ฉ์— ๋Œ€ํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

// Called to bind functionality to input
void AMyPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
    
    // ์ƒ๋žต
    
	PlayerInputComponent->BindAxis(TEXT("Horizontal"), this, &AMyPlayer::InputHorizontal);
	PlayerInputComponent->BindAxis(TEXT("Vertical"), this, &AMyPlayer::InputVertical);


}

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

์ด๋™ ๋ฐ”์ธ๋”ฉ ํ•จ์ˆ˜์˜ ์—ญํ• ์€ ํ”Œ๋ ˆ์ด์–ด์˜ ์ด๋™ ๋ฐฉํ–ฅ ๊ฐ’์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

void AMyPlayer::InputHorizontal(float value)
{
	direction.X = value;
}

void AMyPlayer::InputVertical(float value)
{
	direction.Y = value;
}

ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์›ํ•˜๋Š” ์ด๋™๋ฐฉํ–ฅ์„ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
์ด๋ฅผ ํ†ตํ•ด Tick() ํ•จ์ˆ˜์—์„œ ๊ฐ’์„ ๊ณ„์‚ฐํ•˜์—ฌ ์‹ค์ œ๋กœ ์ด๋™์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ์ฒ˜๋ฆฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์‹ค์ œ ์ด๋™ ๊ตฌํ˜„

๋“ฑ์†์šด๋™ ๊ณต์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”Œ๋ ˆ์ด์–ด์˜ ์ด๋™์„ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

P(๊ฒฐ๊ณผ ์œ„์น˜) = P0(ํ˜„์žฌ ์œ„์น˜) + v(์†๋„) * t(์‹œ๊ฐ„)

์œ„ ๊ณต์‹์„ ์‚ฌ์šฉํ•ด์„œ ์ฒ˜๋ฆฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

void AMyPlayer::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	FVector P0 = GetActorLocation();
	FVector vt = direction * walkSpeed * DeltaTime;
	FVector P = P0 + vt;

	SetActorLocation(P);
	direction = FVector::ZeroVector;

}

tick()ํ•จ์ˆ˜๋Š” ๊ณ„์†ํ•ด์„œ ํ˜ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ ์ž…๋ ฅ์ด ์žˆ์„ ๋•Œ๋งŒ ์ด๋™์„ ์œ„ํ•ด์„œ๋Š” direction์„ ๊ณ„์‚ฐ์ด ๋๋‚˜๋ฉด Zero Vector๋กœ ์ดˆ๊ธฐํ™”ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

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

์ด๋Š” direction์ด ๊ฐ€์ง€๋Š” ๋ฒกํ„ฐ๊ฐ€ ์ƒ๋Œ€ ์ขŒํ‘œ๊ฐ€ ์•„๋‹Œ ์ ˆ๋Œ€ ์ขŒํ‘œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

direction ์ˆ˜์ •

์ด๋™ ๋ฐฉํ–ฅ ๋ฒกํ„ฐ๋ฅผ ์ƒํƒœ์ขŒํ‘œ๋กœ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”.

direction = FTransform(GetControlRotation()).TransformVector(direction);

GetControlRotationํ•จ์ˆ˜๋Š” ํ•ด๋‹น ํ”Œ๋ ˆ์ด์–ด ํฐ์„ ์ปจํŠธ๋กคํ•˜๊ณ  ์ž‡๋Š” ์ปจํŠธ๋กค๋Ÿฌ์˜ ๋ฐฉํ–ฅ์„ FRotator ํƒ€์ž…์œผ๋กœ ๋„˜๊ฒจ ์ค๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ํŠน์ • ์ด๋™ ๋ฒกํ„ฐ๋ฅผ ์ž์‹ ์˜ ๊ธฐ์ค€์œผ๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” TransformVector()ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ direction์„ ์ˆ˜์ •ํ•ด์ค๋‹ˆ๋‹ค.

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

์ฝ”๋“œ ์ˆ˜์ •

๊ธฐ์กด ์šฐ๋ฆฌ๋Š” ๋“ฑ์† ์šด๋™ ๊ณต์‹์„ ์‚ฌ์šฉํ•˜ใ…“์—ฌ ์›€์ง์ž„์„ ์ง์ ‘ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์–ธ๋ฆฌ์–ผ ๊ฒŒ์ž„ ํ”„๋ ˆ์ž„์›Œํฌ์—๋Š” ์บ๋ฆญํ„ฐ์˜ ์›€์ง์ž„์„ ์ฒ˜๋ฆฌํ•ด์ค„ Charactor Movement๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ด ์ปดํฌ๋„ŒํŠธ์˜ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜์—ฌ ๋“ฑ์†์šด๋™ ๊ตฌํ˜„ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ธฐ์กด ๊ณ„์‚ฐ ๊ณต์‹์„ ์ฃผ์„์ฒ˜๋ฆฌํ•˜๊ณ , AddMovementInput์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

void AMyPlayer::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	direction = FTransform(GetControlRotation()).TransformVector(direction);

	//FVector P0 = GetActorLocation();
	//FVector vt = direction * walkSpeed * DeltaTime;
	//FVector P = P0 + vt;
	//SetActorLocation(P);

	AddMovementInput(direction);
	direction = FVector::ZeroVector;

}

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

์ ํ”„ ์ฒ˜๋ฆฌ

์ ํ”„๋Š” ์บ๋ฆญํ„ฐํด๋ž˜์Šค์˜ ๊ธฐ๋Šฅ ์ค‘ Jump()๋ฅผ ํ˜ธ์ถœํ•ด์ฃผ๋ฉด ๋์ž…๋‹ˆ๋‹ค.

๋ฐ”์ธ๋”ฉ ํ•จ์ˆ˜๋ฅผ ๋จผ์ € ์„ ์–ธํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

public:
	void LookUp(float value);
	void Turn(float value);
	void InputJump();

์ด๋ฒˆ์—” BindAction์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์ธ์ž๊ฐ€ ํ•˜๋‚˜ ๋” ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.

// Called to bind functionality to input
void AMyPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	//์ƒ๋žต

	PlayerInputComponent->BindAction(TEXT("Jump"), IE_Pressed, this, &AMyPlayer::InputJump);

}

์œ„์™€ ๊ฐ™์ด ํ•จ์ˆ˜๋ฅผ ๋ฐ”์ธ๋”ฉํ–ˆ๋‹ค๋ฉด InputJump()๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ์ •์˜ํ•ด์ค๋‹ˆ๋‹ค.

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

์ด๊ฒŒ ๋์ž…๋‹ˆ๋‹ค.

โ—์ €์žฅ ํ›„ ์‹คํ–‰โ—ํ•ด๋ณด๋ฉด ์บ๋ฆญํ„ฐ๊ฐ€ ์ ํ”„๊นŒ์ง€ ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค.


๋งˆ๋ฌด๋ฆฌ

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

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

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

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

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