📌
어제 오늘 작업을 통해 알게 된 사실을 가볍게 정리해보고자 한다.
학습 내용
1. 오브젝트 풀링
2. 데이터 ID를 통해 데이터 인덱스 가져오기
3. 디버깅
1. 오브젝트 풀링 (Object Pooling)
✅ 오브젝트 풀링?
사람들이 너무 자주 쓰길래 유니티에서 제공하는 내장 기능인 줄 알았지만 디자인 패턴이었다.
오브젝트 풀링은 일정 수의 오브젝트를 미리 생성하여 풀(pool)에 보관하고, 필요할 때 풀에서 꺼내 사용한 후 다시 반환하는 방식이다. 이를 통해 오브젝트를 매번 생성하거나 삭제하는 데 드는 비용을 절감할 수 있다. 쉽게 말해서 최적화와 관련이 있다.
2. 데이터ID를 통해 데이터 인덱스 가져오기
이와 관련된 고민을 전날부터 했었다. 배열이든 리스트이든, 데이터들은 인덱스로 분류될 텐데 어떻게 ID 값으로 원하는 데이터를 찾는다는 건가?
3. 디버깅
✅ 원래 start에서 실행해주던 함수를 OnEnterTrigger에서 실행했을 때 데이터가 초기화 되지 않는다!
초기화 타이밍의 문제였다.
튜터(=그냥 신.)님이 빠르게 샤샥 고쳐주셨지만 완전히 이해하기 위해 하나씩 뜯어보자.
if (matchingIndex.Count > 0)
{
foreach (int index in matchingIndex)
{
Spawn spawnData = DatabaseManager.Instance.Parse<Spawn>(Spawners.SpawnersList[index]);
GameObject newSpawner = Instantiate(SpawnerPrefab, spawnData.SpawnPosition, Quaternion.identity);
newSpawner.GetComponent<SpawnSystem>().spawnData = spawnData; // 데이터 전달
}
}
이 코드가 뭐냐면 던전 데이터에서 생성해야 할 스포너 아이디를 찾고 그 아이디에 맞는 스포너 데이터 인덱스를 찾아서 spawnData 객체에 데이터를 초기화해주는 애다.
데이터를 전달 X 데이터를 집어넣는 구조다. 데이터를 넘겨주는 방식으로 하는 게 옳다.
여기까진 문제가 없었다. 실제로 생성된 스포너의 spawnData는 초기화는 제대로 되고 있는 상태이다. 그럼 스포너 시스템 스크립트를 살펴보자.
public class SpawnSystem : MonoBehaviour
{
[SerializeField] private GameObject[] objectPool;
public Spawn spawnData;
public GameObject TestPrefab;
private void Awake()
{
TestPrefab = Resources.Load<GameObject>("Monster");
InitializeObjectPool();
}
public void InitializeObjectPool() // 오브젝트 객체 생성
{
objectPool = new GameObject[spawnData.SpawnCount];
for (int i = 0; i < spawnData.SpawnCount; i++)
{
GameObject obj = Instantiate(TestPrefab);
obj.SetActive(false);
obj.transform.SetParent(this.transform);
objectPool[i] = obj;
}
}
Awake에서 ObjectPool을 초기화 해주고 있다. 이때 ObjectPool은 spawnData를 받고 있다. 문제는 여기서 발생했다. 스포너가 생성되자마자 InitializeObjectPool()가 바로 실행돼서 InitializeObjectPool()에서 넣을 spawnData는 null이라는 것.
갓림판으로 다시 살펴보자.
이렇게 데이터를 넣어주는 코드가 스포너 객체 초기화보다 뒤에 실행된 게 원인이었다! 타이밍이 원인이라고는 생각하고 있었지만, 계속 OnTriggerEnter 쪽에서 문제가 발생했을 거라고 생각해서 시간을 오래 써버렸다 ㅎ.
✅ 해결
if (matchingIndex.Count > 0)
{
foreach (int index in matchingIndex)
{
Spawn spawnData = DatabaseManager.Instance.Parse<Spawn>(Spawners.SpawnersList[index]);
GameObject newSpawner = Instantiate(SpawnerPrefab, spawnData.SpawnPosition, Quaternion.identity);
newSpawner.GetComponent<SpawnSystem>().InitializeObjectPool(spawnData); // 데이터 전달
}
던전 매니저에서 InitializeObjectPool를 실행시켜주면서 데이터를 넘겨주는 방식으로 해결했다. 하지만 이 상태의 데이터 핸들링도 데이터 특강에서 들었던 거랑 왠지 다른... 것 같아서 (아닐 수도 있다. 이게 맞을 수도 있다.) 리펙토링 해야할 듯!
일단 현재의 데이터 파싱 시스템을 통해서는 던전ID에 따라 데이터를 넣어주고, 그 데이터에 있는 스포너를 배치하고, 또 해당 스포너가 몬스터를 스폰해주는 일련의 과정은 완벽히 구현했다!
내일은 던전 입장을 연결해줄 UI를 만들고, UGS를 이용한 데이터 파싱 방법을 제대로 연구해보려고 한다. 또한, Find 메서드 등을 통해서 기존 스크립트를 조금 더 깔끔하게 정리해야 할 것 같다. 튜터님께서 던전 내에 있을 하나의 방에 스포너가 여러개가 있을 경우를 생각하라고 했으니까 이 방법도 픽스해보자.
방법은 세 개가 있을 것 같은데,
[1] 방마다 딱 하나의 스포너를 두고 스폰 위치를 정할 수 있도록 하기 (중심점을 다르게)
[2] 방마다 여러 개의 스포너를 두고 스포너를 그룹으로 묶어서 동시에 몬스터가 스폰되도록 하기
[3] 룸 매니저를 만들어서 룸 스폰 포인트에 닿았을 때 스포너가 활성화 되게 하기
세 개 중에 구현하기 쉬운 쪽으로 잡아서 이 부분도 리펙토링하기!
뇌가 아프다.
'[내배캠] 본 캠프 개발 학습 > 매일매일 쓰는 TIL' 카테고리의 다른 글
11월 29일 금요일 본 캠프 개발 일지 (0) | 2024.11.29 |
---|---|
11월 27일 수요일 본 캠프 개발 일지 (1) | 2024.11.27 |
11월 26일 화요일 본 캠프 개발 일지 | 직렬화 (0) | 2024.11.26 |
11월 25일 월요일 본 캠프 개발 일지 | 프레임워크 (0) | 2024.11.25 |
11월 22일 금요일 본 캠프 개발 일지 (0) | 2024.11.22 |