๐ Project Galaga ์์ํฉ๋๋ค.
Unreal C++๊ณผ ๊ฒ์์ํ์ ์ ๋ชฉํด์ ํ๋ก์ ํธ๋ฅผ ์งํํ์ต๋๋ค.
2024.05.04 ~ 2024.05.21์ ๊ฐ๋ฐ ๊ธฐ๊ฐ์ผ๋ก, ์ด 17์ผ ๋์ ๊ฐ๋ฐ์ ์๋ฃํ์์ต๋๋ค.
๊ฑฐ์ฐฝํ๊ฒ ์์ํ ํ๋ก์ ํธ๋ณด๋จ ์ง๊ธ๊น์ง ๋ฐฐ์ด ๊ฒ๋ค์ ์ข ํฉ์ ์ผ๋ก ์ฌ์ฉํด์ ๊ฒฐ๊ณผ๋ฌผ์ ๋ง๋ค์ด ๋ด๋ณด๊ฒ ๋ค๋ ๋ง์์ผ๋ก ์์ฑํ์์ต๋๋ค.
ํด๋น ์๋ฆฌ์ฆ์๋ ๊ฐ๋ฐ ์ผ์ง๋ฅผ ์ ๋ฆฌํ๋ฉฐ, ๊ฐ๋ฐ ๋ด์ฉ์ ๋ํ ์ค๋ช ๊ณผ ์ด์๋ฅผ ์ ๋ฆฌํ ์์ ์ ๋๋ค.
๋ค์ ํ๋ ์ด์ด์ ๊ตฌํ ๋ด์ฉ์ผ๋ก ๋์ ์์ต๋๋ค.
์ค๋ธ์ ํธ ํ๋ง ๊ตฌํ ๋ด์ฉ์ ๋จผ์ ํ๊ณ ๋์ผ ์ถ๊ฐ ๊ธฐ๋ฅ์ ๋ํด์ ์ค๋ช ์ด ๊ฐ๋ฅํ ๊ฒ ๊ฐ์ ํ์์๋ก ๋ฐ๋ ธ์ต๋๋ค.
ํ๋ ์ด์ด๋ 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๋ ํ์ด๊ธฐ๊ฐ ํ์ฑํ๋ 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();
}
}
}
}
}
3์ด ํ ์คํ๋๋ StopUlt()์
๋๋ค.
๋จ์ํ๊ฒ FireUltTimer๋ฅผ Clearํด์ค๋๋ค.
๊ทธ๋ผ ๋ ์ด์ Trace๊ฐ ๋ฐ์ฌ๋์ง ์๊ฒ ์ฃ .
void UPlayerAttack::StopUlt()
{
GetWorld()->GetTimerManager().ClearTimer(FireUltTimer);
}
๊ทธ๋ ๊ฒ ๊ตฌํ๋ ํ์ด๊ธฐ์
๋๋ค.
์ฌ๊ธฐ๊น์ง ํ๋ ์ด์ด์ ์ถ๊ฐ ์กฐ์์ ๋ํ ๊ตฌํ๋ด์ฉ ์ ๋ฆฌ์์ต๋๋ค.