[UE5 / C++] ๐Ÿ‘ฟ ์  ๋งŒ๋“ค๊ธฐ (Feat. FSM) (ๅฎŒ)

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

UE5 C++

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

๊ฐœ์š”

๐Ÿ’ก C++๋กœ ์ ์„ ๋งŒ๋“ค์–ด๋ณด์ž. ๋˜ํ•œ ์œ ํ•œ์ƒํƒœ๊ธฐ๊ณ„๋ฅผ ํฌํ•จํ•˜์—ฌ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ๋‹ค.

์ด๋ฒˆ์—๋Š” ์ ์ด ๊ณต๊ฒฉํ•  ๋•Œ ์•„๊ตฐ์ด ํ”ผ๊ฒฉ๋˜๋„๋ก ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


๋ณธ๋ก 


Line Trace Channel ์ถ”๊ฐ€

Edit - Project Settings - Engine - Collision์œผ๋กœ ์ด๋™ํ•ด์ฃผ์„ธ์š”.

๊ทธ๋ฆฌ๊ณ  Trace Channels์—์„œ EnemyMeleeAttack ์ฑ„๋„์„ ์ถ”๊ฐ€ ํ•ด์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

AttackState() ์ˆ˜์ •

Attack ์ขŒํ‘œ๋ฅผ ์œ„ํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ด์ค„ ์ˆ˜ ์žˆ์œผ๋‚˜,
๊ทธ๋ƒฅ GetMesh()์—์„œ Z๋ฅผ ๋”ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

me->GetMesh()๋กœ ์  ๋ฉ”์‹œ๋ฅผ ๋ฐ›์•„์™€ Start, End์œ„์น˜๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค.

์ด๋•Œ Mesh์˜ ์ขŒํ‘œ๊ณ„๋Š” Forward๊ฐ€ ์•„๋‹Œ RightVector๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ์„ธ์š”.

๊ทธ๋ฆฌ๊ณ  ๋ณธ์ธ ๋ฌด์‹œ Params๊นŒ์ง€ ์ผ๋‹จ ์ž‘์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

void UEnemyFSM::AttackState()
{
	FVector Direction = target->GetActorLocation() - me->GetActorLocation();

	if (Direction.Size() <= attackRange)
	{
		if (currentTime > attackDelayTime)
		{
			UAnimInstance* AnimInstance = me->GetMesh()->GetAnimInstance();
			if (AnimInstance != nullptr)
			{
            	// ์ƒ๋žต
				FVector startPos = me->GetMesh()->GetComponentLocation() + FVector(0, 0, 100);
				FVector endPos = startPos + (me->GetMesh()->GetRightVector() * 150);

				FHitResult hitInfo;

				FCollisionQueryParams params;
				params.AddIgnoredActor(me);


			}
		}
	}


}

์œ„ ์ธ์ž๋ฅผ ์‚ฌ์šฉํ•ด์„œ LineTrace๋ฅผ ์˜๊ฒ ์Šต๋‹ˆ๋‹ค.
bHit์—์„œ LineTraceSingeByChannel์„ ์ด์ฃผ์„ธ์š”.

์ด๋•Œ ์ฑ„๋„์€ ECollisionChannel::ECC_GameTraceChannel1 ๋„ฃ์–ด ์ฃผ์„ธ์š”.

์šฐ๋ฆฌ๊ฐ€ ๋„ฃ์€ ์ฑ„๋„์˜ 1๋ฒˆ์„ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

void UEnemyFSM::AttackState()
{
	FVector Direction = target->GetActorLocation() - me->GetActorLocation();

	if (Direction.Size() <= attackRange)
	{
		if (currentTime > attackDelayTime)
		{
			UAnimInstance* AnimInstance = me->GetMesh()->GetAnimInstance();
			if (AnimInstance != nullptr)
			{
            	// ์ƒ๋žต
				bool bHit = GetWorld()->LineTraceSingleByChannel(hitInfo, startPos, endPos, ECollisionChannel::ECC_GameTraceChannel1, params);

			}
		}
	}


}

์ด์–ด์„œ LineTrace์— ๋งž์€ ๋Œ€์ƒ์ด ์žˆ๋‹ค๋ฉด bHit์— ์ •๋ณด๊ฐ€ ๋“ค์–ด ๊ฐˆ ๊ฒ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  Player๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ์œ ๋‹ˆํฌ ๋„ค์ž„์„ ํ•˜๋‚˜ ๊ฐ€์ ธ์˜ค๊ฒ ์Šต๋‹ˆ๋‹ค.

์ €๋Š” GunMeshComp๋ฅผ ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  Player๋•Œ์™€ ๋™์ผํ•˜๊ฒŒ ApplyDamage๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ์„ธ์š”.

void UEnemyFSM::AttackState()
{
	FVector Direction = target->GetActorLocation() - me->GetActorLocation();

	if (Direction.Size() <= attackRange)
	{
		if (currentTime > attackDelayTime)
		{
			UAnimInstance* AnimInstance = me->GetMesh()->GetAnimInstance();
			if (AnimInstance != nullptr)
			{
            	// ์ƒ๋žต

				if (bHit)
				{
					auto enemy = hitInfo.GetActor()->GetDefaultSubobjectByName(TEXT("GunMeshComp"));

					if (enemy)
					{
						UGameplayStatics::ApplyDamage(hitInfo.GetActor(), 1, NULL, NULL, NULL);
					}
				}


			}
		}
	}


}

Player์˜ Take Damage()

MyPlayer Class๋กœ ์ด๋™ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ถ”๊ฐ€ ์š”์†Œ ์„ ์–ธ

์ฒด๋ ฅ ์ถ”๊ฐ€

ํ”Œ๋ ˆ์ด์–ด์—๊ฒŒ๋„ ์ฒด๋ ฅ์„ ๋„ฃ์–ด ์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = FSMComponent)
	float Hp = 3;

TakeDamage() ์„ ์–ธ

MyPlayer.h๋กœ ๊ฐ€์„œ TakeDamage()๋ฅผ ์„ ์–ธํ•ด์ฃผ์„ธ์š”.

	virtual float TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override;

AM_Hit ์ถ”๊ฐ€

ํ”Œ๋ ˆ์ด์–ด๋„ ํ”ผ๊ฒฉ์‹œ AM_Hit๋ฅผ ์žฌ์ƒํ•˜๋„๋ก ํ•ด์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

	UPROPERTY(EditAnywhere, Category = Montage)
	UAnimMontage* AM_Hit;

TakeDamage() ์ •์˜

์šฐ์„  ํ—ค๋”๋ฅผ ํ•˜๋‚˜ ์ถ”๊ฐ€ํ•ด์ค์‹œ๋‹ค.

#include "Components/CapsuleComponent.h"

๊ทธ๋ฆฌ๊ณ  Enemy๋•Œ์™€ ๊ฐ™์ด ๋™์ผํ•˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์ค๋‹ˆ๋‹ค.
์ƒํƒœ์ „ํ™˜ ๋Œ€์‹  ์ƒํƒœํ•จ์ˆ˜์˜ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ๋„ฃ์œผ๋ฉด ๋˜๊ฒ ์ฃ ?

float AMyPlayer::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
	float damage = Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
	Hp -= damage;

	if (Hp <= 0)
	{
		GetMesh()->SetSimulatePhysics(true);
		GetMesh()->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
		GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	}
	else 
	{
		UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
		if (AnimInstance != nullptr)
		{
			AnimInstance->Montage_Play(AM_Hit);
		}
	}


	return damage;
}

โ—์ปดํŒŒ์ผ ์ €์žฅโ—ํ•˜๊ณ  ์–ธ๋ฆฌ์–ผ ์—๋””ํ„ฐ๋กœ ์ด๋™ํ•ด์ฃผ์„ธ์š”.

BP_Player์˜ AM_Hit ์ถ”๊ฐ€

BP_Player๋ฅผ ์—ด์–ด์„œ AM_Hit์„ ๋„ฃ์–ด ์ฃผ์„ธ์š”.

โ—์ปดํŒŒ์ผ ์ €์žฅโ—ํ•˜๊ณ  ์‹คํ–‰ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋งฅ ์—†์ด ์“ฐ๋Ÿฌ์ง€๋„ค์š”.

๋งˆ๋ฌด๋ฆฌ

์  ๊ณต๊ฒฉ๊ณผ ํ”Œ๋ ˆ์ด์–ด์˜ ํ”ผ๊ฒฉ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์•ฝ๊ฐ„ ํƒ€์ด๋ฐ์ด ๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ณธ๋ž˜ Notify๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์• ๋‹ˆ๋ฉ”์ด์…˜์˜ ํŠน์ • ์‹œ์ ์— Line Trace๋ฅผ ์˜๊ณ  ์ƒํ˜ธ์ž‘์šฉ์ด ๋˜๋„๋ก ํ•ด์•ผ๊ฒ ์ฃ .

๋˜ํ•œ ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์ฃฝ์—ˆ์Œ์—๋„ ๊ณ„์†ํ•ด์„œ ์ ๋“ค์ด target์— ๋Œ€ํ•œ ์ƒํƒœ ๋™์ž‘์ด ๊ณ„์†๋ฉ๋‹ˆ๋‹ค.

๋‘ ๋ถ€๋ถ„์€ ๋‚˜์ค‘์— ์‹œ๊ฐ„์ด ๋œ๋‹ค๋ฉด ์—…๋ฐ์ดํŠธ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

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

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