본문 바로가기

[내배캠] 본 캠프 개발 학습/매일매일 쓰는 TIL

11월 28일 목요일 본 캠프 개발 일지

📌


 어제 오늘 작업을 통해 알게 된 사실을 가볍게 정리해보고자 한다.

학습 내용 


1. 오브젝트 풀링 
2. 데이터 ID를 통해 데이터 인덱스 가져오기 
3. 디버깅 


1. 오브젝트 풀링 (Object Pooling)

✅ 오브젝트 풀링?

 사람들이 너무 자주 쓰길래 유니티에서 제공하는 내장 기능인 줄 알았지만 디자인 패턴이었다. 
 오브젝트 풀링은 일정 수의 오브젝트를 미리 생성하여 풀(pool)에 보관하고, 필요할 때 풀에서 꺼내 사용한 후 다시 반환하는 방식이다. 이를 통해 오브젝트를 매번 생성하거나 삭제하는 데 드는 비용을 절감할 수 있다. 쉽게 말해서 최적화와 관련이 있다. 

2. 데이터ID를 통해 데이터 인덱스 가져오기 

 

11월 27일 수요일 본 캠프 개발 일지

지금 던전 - 스포너를 작업하고 있는데 모든 걸 데이터화 해서 쓰려니까 너무 어렵다. 미연시 다이어그램의 악몽이 다시 재생되고 있다. 구조는 던전 데이터에 던전에 생성되어야 할 스포너를

note8918.tistory.com

  

 이와 관련된 고민을 전날부터 했었다. 배열이든 리스트이든, 데이터들은 인덱스로 분류될 텐데 어떻게 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] 룸 매니저를 만들어서 룸 스폰 포인트에 닿았을 때 스포너가 활성화 되게 하기 

 세 개 중에 구현하기 쉬운 쪽으로 잡아서 이 부분도 리펙토링하기! 

 

뇌가 아프다.