C++와 Unreal Engine으로 3D 게임 개발

C++와 Unreal Engine으로 3D 게임 개발 3-3

jh009 2026. 6. 20. 15:33

3-3. 아이템 스폰 및 레벨 데이터 관리하기

레벨 셋팅하기

BasicLevel, Intermediate, Level Advanced Level 순서로 난이도에 따라 맵의 크기가 작아짐


스폰 영역(Spawn Volume) 설정 방법

가장 직관적이고 효율적으로 스폰 영역을 지정하는 절차

  1. 클래스 생성: Actor 클래스를 기반으로 블루프린트(BP)를 생성
  2. 컴포넌트 추가: Components 패널에서 Box Collision을 추가
  3. 영역 조정: 뷰포트에서 박스의 크기와 위치를 원하는 스폰 영역에 맞게 조절
  4. 로직 구현: 스폰 시 GetScaledBoxExtent 와 GetComponentLocation 노드를 활용하여 해당 박스 내부의 랜덤한 좌표를 계산후 객체를 생성

콜리전 컴포넌트를 스폰 영역으로 사용하는 이유

구분 장점
시각적 편의성 뷰포트에서 직접 보며 크기와 위치를 정밀하게 조절 가능
직관적 제어 변수 수정 없이 마우스 드래그만으로 영역을 즉각적으로 변경 가능
위치 계산 최적화 엔진이 제공하는 내장 함수로 영역 내 랜덤 좌표 산출이 간편함
다목적 활용 단순 스폰 영역뿐만 아니라, 트리거, 충돌 체크까지 동시에 수행할 수 있음
성능 효율성 엔진 내부적으로 최적화된 물리 엔진의 연산을 사용하므로, 별도의 커스텀 수학적 계산보다 가볍고 안정적

콜리전 컴포넌트로 스폰 영역 지정하기

C++ Class → Actor 선택 → 이름 설정 SpawnVolume

 

UBoxComponent* SpawningBox;

  • 박스 형태의 콜리전 영역을 나타냄
  • 언리얼 엔진의 UBoxComponent 는 박스 내부에서 오버랩이나 충돌을 감지할 수 있는 컴포넌트
  • 실제로 눈에 보이는 3D 메시 X,  박스 형태의 충돌 범위만 제공

GetRandomPointInVolume()

  • SpawningBox 범위 내부에서 랜덤 좌표(FVector)를 리턴
  • 이 좌표를 이용해 아이템을 생성하면 직육면체 형태 범위 안에서 임의의 위치에 아이템이 뜨는 효과를 낼 수 있음

SpawnItem()

  • 파라미터로 받은 아이템 클래스를 SpawnVolume 내부의 랜덤 위치에 생성하는 함수

SpawnVolume.h


GetScaledBoxExtent()

박스 컴포넌트의 실제 가로/세로/높이 절반 길이(Extent)를 반환

에디터에서 Scale을 조절하면 여기에도 반영됨

 

FRandRange(a, b)

a ~ b 사이 임의의 float 값을 반환

X, Y, Z 좌표마다 랜덤 값을 생성하여 BoxOrigin에 더해주었음

SpawnVolume.cpp


아이템 랜덤 스폰 테스트

빌드 후 언리얼 에디터

SpawnVolume 클래스를 상속받은 BP_SpawnVolume Blueprint 클래스를 생성

 

BP_SpawnVolume 이벤트 그래프

Begin Play 노드 → SpawnItem() 함수를 호출하는 Blueprint 노드를 추가


2. 아이템 스폰 확률 데이터 테이블 만들기

Item Data 구조체 만들기

아이템을 확률적으로 스폰되는지 코드로 직접 하드코딩 → 수정할 때마다 빌드를 해야돼서 번거로움

 

언리얼 엔진의 데이터 테이블을 사용하면

이를 엑셀 (CSV)이나 JSON 파일로 관리해서 엔진 안으로 임포트하고, 코드나 블루프린트에서 쉽게 불러 쓸 수 있음

기획자, 디자이너도 엑셀에서 숫자만 바꾸면 되므로 매우 편리함

 

데이터 테이블의 각 행(Row)을 C++ 구조체로 매핑해야 함

언리얼 엔진은 FTableRowBase 라는 기본 구조체를 제공

→ 상속한 구조체를 만들면, 각 CSV (또는 JSON) 행을 FItemSpawnRow 구조체에서 정해준 형태로 받아올 수 있게 됨

 

이러한 구조체는 클래스가 아님

None을 선택해서 C++ 파일 생성 (이름 ItemSpawnRow) 


TSubclassOf : 하드 레퍼런스

클래스가 항상 메모리에 로드된 상태에서 바로 접근

 

TSoftclassPtr : 소프트 레퍼런스

클래스의 경로만 유지 

SpawnVolume.cpp


언리얼 에디터에서 직접 데이터 테이블 수정하기 (방법 1)

Content Browser 창에서 우클릭 → Miscellaneous → Data Table 선택

팝업창에서 Row Structure로 FItemSpawnRow를 선택

DataTable 에셋 → Add Row 버튼을 눌러 행 추가

→ Row Name, ItemName, ItemClass, SpawnChance 등을 원하는 값으로 넣기

참조를 하려면 꼭 경로 끝에 C가 붙는 것이 특징   

SpawnChance : 스폰 확률 / 전부 합쳐서 100이 되어야함


3. 스폰에 확률 적용하기

SpawnVolume 클래스에서 확률 로직으로 어떤 아이템을 스폰할지 결정하는 코드로 다시 수정

SpawnVolume.h


 

GetRandomItem()

  • 테이블의 모든 Row를 가져와 확률합을 구하고, 확률에 따라 한 개를 뽑아 리턴

SpawnVolume.cpp


빌드 후, BP_SpawnVolume → Class Defaults → Spawning 에 Item Data Table 선택

→ 기존에 만들어둔 데이터 테이블인 ItemSpawnTable 에셋을 할당

 

이벤트 그래프 SpawnRandomItem() 함수를 10번의 호출을 하도록 로직 노드를 생성 (테스트용)


레벨마다 다른 확률 데이터 적용하기

1. 레벨별로 서로 다른 DataTable 에셋을 사용

  • CSV(또는 JSON)에 각각 다른 확률을 넣고, 레벨1 맵에서는 BP_SpawnVolume 가 ItemSpawnTable_Level1을 바라보도록 설정
  • 레벨2 맵에서는 ItemSpawnTable_Level2 할당 등 (관리가 직관적이며 간단함)

 

맵 마다 SpawnTable를 각각 적용시키고 확률을 다르게 하여 난이도를 조절하면 됨   

 

2. 단일 DataTable에 레벨 구분 컬럼 추가

  • CSV에 LevelIndex (또는 LevelName) 같은 컬럼을 하나 더 두고, 각각 어느 레벨에 해당하는지 적기
  • 코드를 수정하여, 현재 레벨이 1인지 2인지 확인 후 필터링된 Row만 확률 계산.
  • 한 DataTable에서 모든 레벨 정보를 한 번에 관리할 수 있는 장점이 있음 → 코드가 약간 복잡해짐

레벨마다 다른 DataTable 에셋을 사용한다는 예시로 이해만 하기