본문 바로가기

Design Pattern/유니티에 적용해보기

C#(Unity) - 오브젝트 풀링(Object Pool)

1. 개요

ㆍ오브젝트를 생성과 제거할 때, Instantiate와 Destroy를 사용해야 합니다.

ㆍ하지만 Instantiate와 Destroy는 상대적으로 무거운 작업이고, GC(Garbage Collector)의 대상이기 때문에 메모리 낭비를 할 수 있어 메모리 관리 측면에서도 풀링을 사용해야 합니다.

 

※ 유니티 매뉴얼에서도 풀링을 통해 가비지를 줄일 수 있도록 권장합니다.


2. 스크립트 구현

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PoolingManager : Singleton<PoolingManager>
{
    [Header("Pooling Information")]
    [SerializeField] GameObject go;			// 풀링할 오브젝트(프리팹)
    [SerializeField] Transform container;		// 오브젝트를 담을 공간
    [SerializeField] int createCount;			// 풀링할 수

    // 오브젝트 관리를 위한 Queue.
    Queue<GameObject> gos = new Queue<GameObject>();

    // Start에서 채워준다.
    private void Start()
    {
        FillStack();
    }

    private void Update()
    {
        // 마우스 좌클릭을 할 때 마다, 오브젝트를 풀링해오고 저장소의 위치에 생성시켜준다.
        if(Input.GetMouseButtonDown(0))
        {
            GameObject pooledObject = Pop();
            pooledObject.transform.position = container.position;
        }
    }

    // 오브젝트 생성
    public void FillStack()
    {
        for (int i = 0; i < createCount; i++)
        {
            GameObject pulledObject = Instantiate(go, container.transform);
            pulledObject.gameObject.SetActive(false);
            gos.Enqueue(pulledObject);
        }
    }

    // 오브젝트 전달
    public GameObject Pop()
    {
        // queue가 비어있으면, 다시 채워준다.
        if (gos.Count <= 0)
        {
            FillStack();
        }

        // 오브젝트를 켜주고 전달
        gos.Peek().gameObject.SetActive(true);
        return gos.Dequeue();
    }

    // 오브젝트 꺼주고 반환
    public void ReturnToStack(GameObject go)
    {
        go.SetActive(false);
        gos.Enqueue(go);
    }
}

필요할 때 마다 풀링매니저에 접근하여 Pop()을 해주고, 사용이 종료된다면 ReturnToStack()으로 되돌려주면 됩니다.


3. Scene 적용

플레이 예시
Inspector와 Hierarchy 창에서의 설정