[Unity] 오브젝트 풀링(Object Pooling)

Mando_727·2023년 8월 11일
0

Unity

목록 보기
3/6
post-thumbnail

오브젝트 풀링(Object Pooling) 이란?

프로그래밍에서 많은 오브젝트를 생성하고 파괴하면 오브젝트 수에 따라 많은 성능소모와 CPU에 부담이 생기게됩니다.

이때 최적화 기법 오브젝트 풀링으로, 생성한 오브젝트들을 풀(큐,리스트, 스택)에 미리 담아 관리하여 프레임 저하를 방지할 수 있습니다.

따라서 오브젝트 풀링은 비활성화된 오브젝트들을 미리 생성한 후 활성화,비활성화를 사용해 재활용하여 메모리를 효율적으로 사용하는 기법입니다.

오브젝트 풀링 사용 방법

  1. 사용할 오브젝트 미리 (비활성화 상태로) 생성 , 모두 Queue 삽입
  2. 오브젝트 사용할 때 - Queue에서 삭제, 오브젝트 활성화
  3. 오브젝트 버릴 때 - 다시 Queue 삽입, 오브젝트 비활성화

풀링 스크립트

먼저 PoolingManager 스크립트를 작성해줍니다.

[Enemy PoolingManager 스크립트]

  1. 싱글톤 구현
  2. 반복문 통해 미리 설정해 놓은 수만큼 오브젝트 생성
    (생성오브젝트 Queue 삽입, 오브젝트 비활성화)
  3. InsertQueue() - Queue 삽입, 오브젝트 비활성화 (오브젝트 사용할 때)
  4. GetQueue() - Queue 삭제, 오브젝트 활성화 (오브젝트 다 썼을 때)
public class EnemyPoolingManager : MonoBehaviour
{
	//싱클톤 구현
    public static EnemyPoolingManager instance;

    public GameObject Enemy_Prefabs = null; //생성 오브젝트
    public Transform[] spawnPos = new Transform[2]; //스폰장소

    public Queue<GameObject> queue = new Queue<GameObject>();

    int rand_Pos; //랜덤스폰장소

    void Start()
    {
        instance = this;

        for (int i = 0; i < 100; i++)
        {
            rand_Pos = Random.Range(0, 2);
            //오브젝트 생성 후 비활성화, Enqueue
            GameObject t_object = Instantiate(Enemy_Prefabs, spawnPos[rand_Pos].position, Quaternion.identity);
            queue.Enqueue(t_object);
            t_object.SetActive(false);
        }
    }

	//오브젝트 버릴 때
    public void InsertQueue(GameObject Enque_Obj)
    {
        queue.Enqueue(Enque_Obj);
        Enque_Obj.SetActive(false);

    }
    //오브젝트 사용할 때
    public GameObject GetQueue()
    {
        GameObject Deque_Obj = queue.Dequeue();
        Deque_Obj.SetActive(true);
        return Deque_Obj;
    }
}

다음은 오브젝트를 스폰할 spawnManager스크립트 작성해줍니다.

[Enemy spawnManager 스크립트]

  1. randNum 난수를 통해 랜덤된 장소에 스폰.
  2. 0.1초마다 Coroutine에서 풀링 스크립트 GetQueue()함수를 호출.
    (GetQueue() = Queue에서 삭제, 오브젝트 활성화.)
  3. 마지막으로 활성화한 오브젝트의 위치값을 재설정해 주었습니다.
public class Enemy_SpawnManager : MonoBehaviour
{
    public Transform[] spawnPos = new Transform[2];

    int randNum;
    void Start()
    {
        StartCoroutine(CreateCoroutine());
    }
    IEnumerator CreateCoroutine()
    {
        while (true)
        {
            yield return new WaitForSeconds(0.1f);
            GameObject Enque_Obj = EnemyPoolingManager.instance.GetQueue();

            randNum = Random.Range(0,2);
            Enque_Obj.transform.position = spawnPos[randNum].position;
        }
    }
}

마지막으로 오브젝트를 다 사용하고 삭제와 같은 기능코드입니다.

[Enemy Destroy 스크립트]

오브젝트 풀링을 사용할 땐 삭제 대신 비활성화를 통해 재활용한다.

void is_Dead()
    {
        if (Mons_curHp <= 0)
        {
            //충돌 시 비활성화
            EnemyPoolingManager.instance.InsertQueue(gameObject);
        }
    }

1개의 댓글

comment-user-thumbnail
2023년 8월 11일

개발자로서 배울 점이 많은 글이었습니다. 감사합니다.

답글 달기