๐ก C++๋ก ์ ์ ๋ง๋ค์ด๋ณด์. ๋ํ ์ ํ์ํ๊ธฐ๊ณ๋ฅผ ํฌํจํ์ฌ ๋ง๋ค์ด ๋ณด๊ฒ ๋ค.
์ด๋ฒ์๋ ๋ง๋ค์ด์ง ์ ๋ค์ ํ๋์ฉ ๋ฐฐ์นํ๋๊ฒ ์๋, ์๋์์ฑ์ด ๋๋ Enemy Manager๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
Enemy Manger๋ฅผ ์ํ C++ ํด๋์ค๋ฅผ ์์ฑํ๊ฒ ์ต๋๋ค.
C++ํด๋์ค ์ถ๊ฐํด์ฃผ์๊ณ ,
์กํฐ๋ก ๋ง๋ค์ด ์ฃผ์ธ์.
์ด๋ฆ์ EnemyManager๋ก ํ๊ฒ ์ต๋๋ค.
์ ์์ฑ์ ํ์ํ ๋ณ์๋ค์ ์ถ๊ฐํ๊ฒ ์ต๋๋ค.
public:
UPROPERTY(EditAnywhere,Category=SpawnSettings)
float minTime = 1;
UPROPERTY(EditAnywhere, Category = SpawnSettings)
float maxTime = 5;
UPROPERTY(EditAnywhere, Category = SpawnSettings)
TArray<class AActor*> spawnPoints;
UPROPERTY(EditAnywhere, Category = SpawnSettings)
TSubclassOf<class AEnemy> enemyFactory;
์ง๊ธ๊น์ง currentTime์ด๋ ๋ณ์๋ฅผ ๋ง๋ค์ด์ DeltaTime์ ๋์ ํฉํ์ฌ ์๊ฐ์ ์ฒดํฌํ์์ต๋๋ค.
์ด๋ฒ์๋ ์ธ๋ฆฌ์ผ์์ ์ ๊ณตํ๋ ํ์ด๋จธ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ฒ ์ต๋๋ค.
์๋์ ํ๋ ์๋ ๊ธ๋ก๋ฒ ํ์ด๋จธ ๋งค๋์ ๋ฅผ ์ด์ฉํ ๊ฒ์
๋๋ค.
๊ธ๋ก๋ฒ ํ์ด๋จธ ๋งค๋์ ์๊ฒ ์๋์๊ณ(FTimerHandle)์ ๋๊ฒจ ์ค ํ,
์๊ฐ์ด ์ง๋๋ฉด ํจ์๋ ๋ธ๋ฆฌ๊ฒ์ดํธ๋ฅผ ํตํด ์๋ฆผ์ ๋ฐ์ ์ ์์ต๋๋ค.
์ ํฌ๋ CreateEnemy()๋ผ๋ ํจ์๋ฅผ ์ฌ์ฉํ๊ฒ ์ต๋๋ค.
public:
// ์๋ต
FTimerHandle spawnTimerHandle;
void CreateAlarm();
void CreateEnemy();
Tick()์ผ๋ก ์๊ฐ์ ๋ฐ์ง ์๊ณ , ์ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ์ ๋ฃ์ง ์์ ๊ฒ์
๋๋ค.
์๋ฌด ๋์์ ํ์ง ์๋๋ฐ Tick()์ด ๊ณ์ํด์ ํธ์ถ๋๋๊ฑด ์์ ๋ญ๋น์
๋๋ค.
Tick()์ด ํธ์ถ๋์ง ์๋๋ก ํด์ฃผ๊ฒ ์ต๋๋ค.
AEnemyManager::AEnemyManager()
{
// false๋ก ๋ณ๊ฒฝ
PrimaryActorTick.bCanEverTick = false;
}
minTime๊ณผ maxTime ์ฌ์ด์ ๋๋ค ๊ฐ์ ์์ฑ ์๊ฐ์ผ๋ก ์ ํ๋ ํจ์๋ฅผ ์์ฑํ๊ฒ ์ต๋๋ค.
void AEnemyManager::CreateAlarm()
{
float createTime = FMath::RandRange(minTime, maxTime);
GetWorld()->GetTimerManager().SetTimer(spawnTimerHandle, this, &AEnemyManager::CreateEnemy, createTime);
}
์ต์ด๋ก ๊ฒ์์ด ์์ํ ๋ ํธ์ถ๋๋๋ก ํ๊ธฐ ์ํด์ BeginPlay()์์ CreateAlarm()์ ํ๋ฒ ํธ์ถํ๊ฒ ์ต๋๋ค.
void AEnemyManager::BeginPlay()
{
Super::BeginPlay();
CreateAlarm();
}
Enemy.h ํค๋๋ฅผ ์ถ๊ฐํด์ฃผ์ธ์.
๊ทธ๋ฆฌ๊ณ ์์ฑ ์ง์ ์ ๋๋ค์ผ๋ก ์ ํํ ํ,
ํด๋น ์์น์ ์์ฑํด์ฃผ๊ฒ ์ต๋๋ค.
Enemy๋ฅผ ๋ชป์ฐพ์ ๊ฒฝ์ฐ๋ฅผ ์ํด ์์ธ์ฒ๋ฆฌ๋ ํด์ฃผ๊ฒ ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์์ฑ๋ Enemy์๊ฒ Controller๋ฅผ ์ฃผ๊ฒ ์ต๋๋ค.
void AEnemyManager::CreateEnemy()
{
int index = FMath::RandRange(0, spawnPoints.Num() - 1);
AEnemy* newEnemy = GetWorld()->SpawnActor<AEnemy>(enemyFactory, spawnPoints[index]->GetActorLocation(), FRotator(0));
if (newEnemy != nullptr)
{
newEnemy->SpawnDefaultController();
CreateAlarm();
}
}
์คํฐ ์ง์ ์กํฐ๋ฅผ ๋ง๋ค๊ฒ ์ต๋๋ค.
์กํฐ๋ก BP๋ฅผ ํ๋ ๋ง๋ค์ด ์ฃผ์ธ์.
๋ ๋ฒจ์์ ๋ฐฐ์นํ ๋ ๊ฐ๋จํ๊ฒ ์๋ณํ ์ ์๋๋ก Sphere๋ง ์ถ๊ฐํด์ฃผ๊ฒ ์ต๋๋ค.
ํ์ง๋ง ์ธ๊ฒ์ ํ๋ ์ด ์์๋ ๋ณด์ด์ง ์๋๋ก Hidden in Game์ True๋ก ํด์ฃผ์ธ์.
๋ํ Collision์ NoCollision์ผ๋ก ์ถฉ๋์ ๊บผ์ฃผ๊ฒ ์ต๋๋ค.
๋จ์ํ ์์น๋ฅผ ๋๊ฒจ์ฃผ๋ ์ญํ ๋ง ์ํํ๋๊น์.
๋ ๋ฒจ์ ์ ๋นํ ๋ฐฐ์น๋ฅผ ํด์ฃผ๊ฒ ์ต๋๋ค.
๋ ๋ฒจ์ EnemyManager Class๋ฅผ ๋์ด์ ๋ฐฐ์นํด์ฃผ์ธ์.
์์๋ผ์ด๋์์ ๋ฐฐ์น๋ ๊ฒ์ ํ์ธํด์ฃผ์ธ์.
๊ทธ๋ฆฌ๊ณ Details ์ฐฝ์์ Spawn Points๋ฅผ ์ถ๊ฐํด์ค์๋ค.
โ๊ธฐ์กด ์ง์ ๋ฐฐ์นํ BP_Enemy๋ ์ญ์ ํด์ฃผ์ธ์โ
โ์ปดํ์ผ ์ ์ฅโํ ํ๋ ์ดํด๋ณด๋ฉด
์คํฐ์ง์ ์์ ๋ฟ ๋ฟ ํ๋์ฉ ๋ํ๋ฉ๋๋ค.
๊ทธ๋ฐ๋ฐ ์คํฐ ์ง์ ์ ํ๋์ฉ ์ง์ ํด์ฃผ๋๊ฑด ์ฌ๊ฐ ๊ท์ฐฎ์ ์์ ์ด ์๋๋๋ค.
๋ค์ ํฌ์คํ ์๋ EnemyManager๊ฐ ์ง์ ๋ ๋ฒจ์์ Spawn Point๋ค์ ์ฐพ์์ ํ ๋นํ๋ ์๋ํ ์์ ์ ํด๋ณด๊ฒ ์ต๋๋ค.