2024/02/06 TIL

양우창·2025년 2월 6일

내일배움캠프 TIL

목록 보기
21/22

개요

오늘은 언리얼 엔진에서 아이템을 랜덤한 위치에 스폰하는 방법을 공부했다. 특히, 단순 랜덤 스폰이 아니라, 스폰 확률을 적용하는 방법까지 배우면서, 한층 더 게임 개발자다운 로직을 짜볼 수 있었다.

랜덤 위치에 아이템 스폰하기

  1. 레벨 셋팅하기
  • 기존 레벨 구조 정리
    • Resources/Maps 폴더에는 3개의 레벨이 존재한다.
      • BasicLevelIntermediate LevelAdvanced Level 순으로 맵 크기가 커진다.
    • 기존 MainLevel을 삭제하고, BasicLevel을 기본 레벨로 설정했다.
      • EditProject SettingsMaps & ModesDefault Maps 변경
  1. 콜리전 컴포넌트로 스폰 영역 지정하기
  • 랜덤한 위치에 아이템을 스폰하려면?

    • 언리얼 엔진에서는 콜리전 컴포넌트(UBoxComponent)를 이용하면 특정 영역 내에서 랜덤 좌표를 생성할 수 있다!
    • 이를 활용해 아이템을 자연스럽게 배치해보자.
  • C++로 SpawnVolume 클래스 만들기

    1. UBoxComponent를 활용하여 스폰 영역을 설정
    2. GetRandomPointInVolume() 함수로 박스 내부 랜덤 좌표 얻기
    3. SpawnItem() 함수로 특정 아이템을 해당 위치에 스폰

핵심 코드 정리

// 1) 박스 내 랜덤한 좌표 얻기
FVector ASpawnVolume::GetRandomPointInVolume() const
{
    FVector BoxExtent = SpawningBox->GetScaledBoxExtent();
    FVector BoxOrigin = SpawningBox->GetComponentLocation();

    return BoxOrigin + FVector(
        FMath::FRandRange(-BoxExtent.X, BoxExtent.X),
        FMath::FRandRange(-BoxExtent.Y, BoxExtent.Y),
        FMath::FRandRange(-BoxExtent.Z, BoxExtent.Z)
    );
}

// 2) 특정 아이템을 랜덤한 위치에 스폰하기
void ASpawnVolume::SpawnItem(TSubclassOf<AActor> ItemClass)
{
    if (!ItemClass) return;

    GetWorld()->SpawnActor<AActor>(
        ItemClass,
        GetRandomPointInVolume(),
        FRotator::ZeroRotator
    );
}
  1. 아이템 랜덤 스폰 테스트하기

    1. BP_SpawnVolume 블루프린트 생성
    2. 기존 맵에 있던 아이템을 삭제하고, BP_SpawnVolume을 배치
    3. 블루프린트에서 BeginPlay 이벤트에 SpawnItem() 함수 연결
    4. 실행하면, 랜덤한 위치에 아이템이 스폰됨
  • 반복적으로 스폰하고 싶다면?

    • Tick 이벤트에 연결하거나
    • 타이머를 활용해 주기적으로 SpawnItem()을 호출하면 된다.
  1. 아이템 스폰 확률 적용하기
  • 아이템을 무작위로 생성하되, 확률을 적용하려면?
    • 데이터 테이블(Data Table)을 활용하면 관리가 편리하다!
    • 직접 코드에 확률을 하드코딩하면 변경할 때마다 빌드해야 하지만,
    • CSV 파일로 관리하면 바로 수정 가능!
  • FItemSpawnRow 구조체 만들기
USTRUCT(BlueprintType)
struct FItemSpawnRow : public FTableRowBase
{
    GENERATED_BODY()

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    FName ItemName;

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    TSubclassOf<AActor> ItemClass;

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    float SpawnChance; // 아이템의 스폰 확률
};
  • CSV 파일 작성 및 데이터 테이블 생성
    • CSV 파일에서 아이템별 확률 데이터를 작성
    • 언리얼 엔진에서 DataTable로 임포트
    • 이후 코드에서 ItemDataTable을 활용하여 확률 기반 스폰 구현
  1. 확률을 적용한 스폰 로직 구현
    1. 확률에 따라 아이템을 결정하는 로직(GetRandomItem())
FItemSpawnRow* ASpawnVolume::GetRandomItem() const
{
    if (!ItemDataTable) return nullptr;

    // 1) 데이터 테이블에서 모든 행을 가져오기
    TArray<FItemSpawnRow*> AllRows;
    static const FString ContextString(TEXT("ItemSpawnContext"));
    ItemDataTable->GetAllRows(ContextString, AllRows);

    if (AllRows.IsEmpty()) return nullptr;

    // 2) 전체 확률 합 구하기
    float TotalChance = 0.0f;
    for (const FItemSpawnRow* Row : AllRows)
    {
        if (Row)
        {
            TotalChance += Row->SpawnChance;
        }
    }

    // 3) 랜덤 값 생성 (0 ~ TotalChance 사이)
    float RandValue = FMath::FRandRange(0.0f, TotalChance);
    float AccumulateChance = 0.0f;

    // 4) 확률에 따라 아이템 선택
    for (FItemSpawnRow* Row : AllRows)
    {
        AccumulateChance += Row->SpawnChance;
        if (RandValue <= AccumulateChance)
        {
            return Row;
        }
    }

    return nullptr;
}
  • 먼저 데이터 테이블에서 모든 아이템과 확률 정보를 가져온다.

  • 각 아이템의 SpawnChance를 누적하여 랜덤 값과 비교 → 확률적으로 아이템 선택!

    1. 확률 적용하여 아이템 스폰 (SpawnRandomItem())
void ASpawnVolume::SpawnRandomItem()
{
    if (FItemSpawnRow* SelectedRow = GetRandomItem())
    {
        if (UClass* ActualClass = SelectedRow->ItemClass.Get())
        {
            SpawnItem(ActualClass);
        }
    }
}
  • GetRandomItem()을 호출해 확률적으로 선택된 아이템을 스폰.
  1. 레벨별로 다른 확률 적용하기
  • 레벨마다 확률을 다르게 적용하는 방법

    1. 각 레벨마다 다른 DataTable을 사용

    • BP_SpawnVolume에서 ItemSpawnTable_Level1, ItemSpawnTable_Level2 등 개별적으로 설정
      • 간단하고 직관적!

    2. 단일 DataTableLevelIndex 컬럼 추가하여 필터링

    • 하나의 DataTable에서 레벨별 데이터를 관리
      • 코드에서 현재 레벨을 체크하여 해당 레벨의 아이템만 필터링
      • 다만, 코드가 조금 더 복잡해질 수 있음

오늘의 배운 점 정리

  • UBoxComponent를 활용해 랜덤 위치에서 아이템을 스폰할 수 있다.

  • DataTable을 활용하면 아이템 스폰 확률을 손쉽게 관리할 수 있다.

  • 확률 기반 랜덤 스폰 로직은,

    1. 전체 확률 합을 구한 뒤
    2. 랜덤 값과 비교하여 아이템을 선택하는 방식으로 구현할 수 있다.
  • 레벨마다 다른 확률을 적용하려면, 개별 DataTable을 사용하거나, 레벨별 필터링을 활용할 수 있다.

오늘 배운 개념을 활용하면 적절한 확률로 다양한 아이템을 자연스럽게 스폰할 수 있다.

profile
내배캠 언리얼 엔진 1기

0개의 댓글