[언리얼] Cpp - pool

gest·2026년 2월 10일

unreal

목록 보기
9/11

이번 시간에는 몬스터를 스폰하는 기능을 구현할 것이다. 이때 메모리 최적화를 위해 유니티에 있는 개념인 pool을 쓸 계획이다.


pool이란?

메모리를 제거하고 생성하는 과정이 메모리소모와 시간이 많이 걸려 그거를 보완하고자 만든 개념이다. 미리 오브젝트를 max로 만들고 일부로 안보이게 해서 spawn을 하면 그 pool에 있는 오브젝트 중 하나를 보이게 하는 것이다. 만약 몬스터가 죽는다면 destory하는 게 아닌 시각적으로 안보이게 한다. 이런 방식으로 시간과 메모리 소모를 막는 방법이라고 보면 된다.


코드

나는 pool을 놓을 위치를 gamemode로 정했다. 이후 pool에 쓸 배열 자료구조는 TArray로 선택했다. 원래 C++이라면 vector가 적합하지만 언리얼에서는 따로 TArray 자료클래스가 존재하는 거 같았다.

Spawn

SpawnActor를 쓰면 된다.
GetWorld()->SpawnActor<생성할클래스>(BP_생성할클래스?,위치,회전, param)

참고로 초반에 액터를 생성할때 같은 위치에 스폰하면 생성이 안되는 경우가 있다.
그래서 나는 파라미터를 수정할 것이다.

FVector SpawnLocation = FVector(100, 0, 50);
FRotator SpawnRotation = FRotator::ZeroRotator;

// SpawnParameters 설정 => 같은 position이 있어도 충돌되지않고 스폰됨
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;

// Enemy 스폰
AEnemy* newEnemy = GetWorld()->SpawnActor<AEnemy>(
	EnemyClass,
	FVector(100, 0, 50),
	SpawnRotation,
	SpawnParams
);

근데 SpawnActor를 쓰면 AIController가 없다.
그래서 따로 AIController를 넣어줘야 한다.

SpawnDefaultController(); //강제 호출

숨기기

유니티에서는 SetActive() 함수인걸로 아는데
언리얼에서는 무슨 함수일까?
NewEnemy->SetActorHiddenInGame(true); 이거 쓰면 된다.

//.h

TArray<AEnemy*> enemyPool;
TArray<AActor*> coinPool;
public:

UPROPERTY(EditDefaultsOnly, Category = "Coin")
TSubclassOf<AActor> CoinClass;

스포너 코드

기본적으로 GetRandomReachablePointInRadius함수를 써서 주변에 적이나 코인같은 오브젝트의 위치를 만들어준다.

주의 원 둘레로 nav가 가능한 지형에만 스폰한다.


void AZombieSlayerGameMode::initEnemy()
{
    FVector SpawnLocation = FVector(100, 0, 50);
    FRotator SpawnRotation = FRotator::ZeroRotator;

    // SpawnParameters 설정
    FActorSpawnParameters spawnParams;
    spawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;

    // Enemy 스폰
    AEnemy* newEnemy = GetWorld()->SpawnActor<AEnemy>(
        EnemyClass,
        FVector(100, 0, 50),
        SpawnRotation,
        spawnParams
    );

    if (newEnemy)
    {
        enemyPool.Add(newEnemy);  // 풀에 추가
        newEnemy->SetActorHiddenInGame(true);  // 비활성화
    }
    else {
    }
}

void AZombieSlayerGameMode::SpawnEnemy()
{
    if (MAX_ENEMY_SIZE <= enemy_size)
        return;

    AEnemy *enemy = enemyPool[enemy_size];
    UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(GetWorld());
 
    float radius = 500;

    AMyPlayer* myPlayer =
        Cast<AMyPlayer>(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));

    FVector playerLocation = myPlayer->GetActorLocation();
    FNavLocation resultLocation;



    // 플레이어 주변 Radius 내 랜덤 도달가능 위치 찾기
    bool bSuccess = NavSys->GetRandomReachablePointInRadius(playerLocation, radius, resultLocation);
    

    if (bSuccess)
    {
        enemy->SetActorLocation(resultLocation.Location);
        enemy->SetActorHiddenInGame(false);
    }

    enemy_size++;
}

0개의 댓글