[UE5] ๐Ÿš€ Project Galaga (10)

Singery00ยท2024๋…„ 5์›” 21์ผ
0

Project Galaga

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

๊ฐœ์š”

๐Ÿš€ Project Galaga ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

Unreal C++๊ณผ ๊ฒŒ์ž„์ˆ˜ํ•™์„ ์ ‘๋ชฉํ•ด์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

2024.05.04 ~ 2024.05.21์˜ ๊ฐœ๋ฐœ ๊ธฐ๊ฐ„์œผ๋กœ, ์ด 17์ผ ๋™์•ˆ ๊ฐœ๋ฐœ์„ ์™„๋ฃŒํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๊ฑฐ์ฐฝํ•˜๊ฒŒ ์‹œ์ž‘ํ•œ ํ”„๋กœ์ ํŠธ๋ณด๋‹จ ์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด ๊ฒƒ๋“ค์„ ์ข…ํ•ฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์„œ ๊ฒฐ๊ณผ๋ฌผ์„ ๋งŒ๋“ค์–ด ๋‚ด๋ณด๊ฒ ๋‹ค๋Š” ๋งˆ์Œ์œผ๋กœ ์™„์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น ์‹œ๋ฆฌ์ฆˆ์—๋Š” ๊ฐœ๋ฐœ ์ผ์ง€๋ฅผ ์ •๋ฆฌํ•˜๋ฉฐ, ๊ฐœ๋ฐœ ๋‚ด์šฉ์— ๋Œ€ํ•œ ์„ค๋ช…๊ณผ ์ด์Šˆ๋ฅผ ์ •๋ฆฌํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

๐Ÿš€ Project Galaga Github Repository


๋ณธ๋ก 

๋‹ค์‹œ ํ”Œ๋ ˆ์ด์–ด์˜ ๊ตฌํ˜„ ๋‚ด์šฉ์œผ๋กœ ๋Œ์•„ ์™”์Šต๋‹ˆ๋‹ค.

์˜ค๋ธŒ์ ํŠธ ํ’€๋ง ๊ตฌํ˜„ ๋‚ด์šฉ์„ ๋จผ์ € ํ•˜๊ณ  ๋‚˜์•ผ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด์„œ ์„ค๋ช…์ด ๊ฐ€๋Šฅํ•  ๊ฒƒ ๊ฐ™์•„ ํ›„์ˆœ์œ„๋กœ ๋ฐ€๋ ธ์Šต๋‹ˆ๋‹ค.

ํญํƒ„ ์•„์ดํ…œ ์‚ฌ์šฉ

ํ”Œ๋ ˆ์ด์–ด๋Š” Rํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ํญํƒ„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋•Œ ํญํƒ„์„ ์‚ฌ์šฉ ์‹œ ๋ ˆ๋ฒจ์— ํ™œ์„ฑํ™” ๋˜์–ด ์žˆ๋Š” ๋ชจ๋“  ์ ์˜ ์ด์•Œ์„ ๋ฌดํšจํ™”ํ•ฉ๋‹ˆ๋‹ค.

๋น„์ƒํƒˆ์ถœ์ด ๊ฐ€๋Šฅํ•œ ๊ฒƒ์ด์ฃ .

์ด๋Š” Enemy Bullet Pool์˜ Pooled Object ๋ฐฐ์—ด์„ ์ˆœํšŒํ•˜๋ฉฐ ๋ชจ๋“  ์ด์•Œ์„ Deactiveํ•ด์ฃผ์–ด ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ํƒ€์ด๋จธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํญํƒ„์— 5์ดˆ์˜ ์ฟจํƒ€์ž„์„ ๋งŒ๋“ค์–ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

void AMyPlayer::Boom()
{
	if (PlayerBoomCount > 0 && !isBoomCool)
	{
		PlayerBoomEffect();

		isBoomCool = true;

		PlayerBoomCount -= 1;

		auto pool = UGameplayStatics::GetActorOfClass(GetWorld(), AEnemyBulletPool::StaticClass());

		if (pool)
		{
			AEnemyBulletPool* enemyBulletPool = Cast<AEnemyBulletPool>(pool);

			if (enemyBulletPool != nullptr)
			{
				enemyBulletPool->DeactiveAllBullets();
			}
		}

		FTimerHandle CanUseBoom;
		GetWorldTimerManager().SetTimer(CanUseBoom, this, &AMyPlayer::setCanUseBoom, 5.0f, false);
	}

}

ํ•„์‚ด๊ธฐ ์‚ฌ์šฉ

ํƒ€์ด๋จธ๋กœ ๊ณต๊ฒฉ ์‹คํ–‰ ๋ฐ ์ข…๋ฃŒ

Space๋ฅผ ๋ˆŒ๋Ÿฌ ํ•„์‚ด๊ธฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•„์‚ด๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ•๋ ฅํ•œ ๊ด‘์„ ์ด ์•ž์œผ๋กœ ๋‚˜๊ฐ€ 3์ดˆ๋™์•ˆ ์ ์—๊ฒŒ ํ”ผํ•ด๋ฅผ ์ž…ํž ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Š” FireUltTimer๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ 0.1์ดˆ๋งˆ๋‹ค ํ”ผํ•ด๋ฅผ ์ค„ ์ˆ˜ ์žˆ๋Š” Trace๋ฅผ ๋ฐ˜๋ณตํ•˜์—ฌ ๋ฐœ์‚ฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์ถ”๊ฐ€๋กœ 3์ดˆ ํ›„์— ์‹คํ–‰๋˜๋Š” UltTimer ํƒ€์ด๋จธ๋ฅผ ๋™์‹œ์— ์‹คํ–‰ํ•˜์—ฌ FireUltTimer๋ฅผ Clearํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

void UPlayerAttack::Ultimate()
{
	if (!GetIsUlt())
	{
		me->PlayerUltEffect();
		SetIsUlt(true);

		if (me != nullptr)
		{

			GetWorld()->GetTimerManager().SetTimer(FireUltTimer, this, &UPlayerAttack::FireUlt, 0.1f, true);

			FTimerHandle UltTimer;
			GetWorld()->GetTimerManager().SetTimer(UltTimer, this, &UPlayerAttack::StopUlt, 3.0f, false);
		}
	}
}

Trace ๋ฐœ์‚ฌ

์ฝ”๋“œ๊ฐ€ ๊ธธ์ง€๋งŒ ๊ตฌํ˜„ ๋‚ด์šฉ์€ ๋งค์šฐ ๋‹จ์ˆœํ•ฉ๋‹ˆ๋‹ค.
Trace๋Š” ํ•„์‚ด๊ธฐ๊ฐ€ ํ™œ์„ฑํ™”๋œ 3์ดˆ๋™์•ˆ 0.1์ดˆ ๊ฐ„๊ฒฉ์œผ๋กœ ๋„“์€ ๋ฒ”์œ„์˜ Multi Trace๋ฅผ ๋ฐœ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์ด๋Š” ๊ด‘์„ ์ด ์ง€๋‚˜๊ฐ€๋Š” ๊ฒฝ๋กœ์ƒ์˜ ๋ชจ๋“  ์ ์—๊ฒŒ ํ”ผํ•ด๋ฅผ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ถฉ๋Œ์ด ๊ฐ์ง€๋œ ๋Œ€์ƒ์˜ ํƒœ๊ทธ๊ฐ€ 'Enemy'๋ผ๋ฉด ApplyDamage()๋ฅผ, 'EnemyBullet'์ด๋ผ๋ฉด ๋น„ํ™œ์„ฑํ™” ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

void UPlayerAttack::FireUlt()
{
	FVector StartPos = me->GetActorLocation() + FVector(200.0f, 0, 0);
	FVector EndPos = StartPos + me->GetActorForwardVector() * 4500.f;

	TArray<FHitResult> HitResults;

	FCollisionQueryParams CollisionParams;
	CollisionParams.AddIgnoredActor(me);

	bool Result = GetWorld()->SweepMultiByChannel
	(
		HitResults,
		StartPos,
		EndPos,
		FQuat::Identity,
		ECollisionChannel::ECC_GameTraceChannel2,
		FCollisionShape::MakeBox(FVector(180, 180, 180)),
		CollisionParams
	);

	// Draw the trace path
	//DrawDebugBox(GetWorld(), StartPos, FVector(180, 180, 180), FQuat::Identity, FColor::Green, false, 2.0f);
	//DrawDebugBox(GetWorld(), EndPos, FVector(180, 180, 180), FQuat::Identity, FColor::Red, false, 2.0f);
	//DrawDebugLine(GetWorld(), StartPos, EndPos, FColor::Blue, false, 2.0f, 0, 5.0f);


	if (Result)
	{
		for (FHitResult HitResult : HitResults)
		{
			if (HitResult.GetActor())
			{
				if (HitResult.GetActor()->ActorHasTag("Enemy"))
				{

					UGameplayStatics::ApplyDamage(HitResult.GetActor(), 1, NULL, NULL, NULL);

					//DrawDebugBox(GetWorld(), HitResult.ImpactPoint, FVector(60, 60, 60), FQuat::Identity, FColor::Yellow, false, 2.0f);
				}
				else if (HitResult.GetActor()->ActorHasTag("EnemyBullet"))
				{
					AEnemyBullet* bullet = Cast<AEnemyBullet>(HitResult.GetActor());
					bullet->Deactivate();
				}
			}
		}
	}
}

Trace ์ข…๋ฃŒ

3์ดˆ ํ›„ ์‹คํ–‰๋˜๋Š” StopUlt()์ž…๋‹ˆ๋‹ค.
๋‹จ์ˆœํ•˜๊ฒŒ FireUltTimer๋ฅผ Clearํ•ด์ค๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ๋” ์ด์ƒ Trace๊ฐ€ ๋ฐœ์‚ฌ๋˜์ง€ ์•Š๊ฒ ์ฃ .

void UPlayerAttack::StopUlt()
{
	GetWorld()->GetTimerManager().ClearTimer(FireUltTimer);
}

๊ทธ๋ ‡๊ฒŒ ๊ตฌํ˜„๋œ ํ•„์‚ด๊ธฐ์ž…๋‹ˆ๋‹ค.


๋งˆ๋ฌด๋ฆฌ

์—ฌ๊ธฐ๊นŒ์ง€ ํ”Œ๋ ˆ์ด์–ด์˜ ์ถ”๊ฐ€ ์กฐ์ž‘์— ๋Œ€ํ•œ ๊ตฌํ˜„๋‚ด์šฉ ์ •๋ฆฌ์˜€์Šต๋‹ˆ๋‹ค.

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

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