본문 바로가기

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

C#(Unity) - 오브젝트 풀링 라이브러리

유니티 작업에 들어가면 풀링을 사용할 상황이 자주 나오다보니, 매번 만드는 것이 귀찮아 직접 만들어본 스크립트입니다. 라이브러리 정도의 수준은 아니지만 마땅히 떠오르는 단어가 없어 라이브러리라 지칭했습니다. 간단하게 Enum으로 타입을 지정한 뒤 상속만 받으면 쉽게 사용이 가능합니다.


1. 풀링매니저 메인 스크립트

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

// Pooling 할 오브젝트 정보
[System.Serializable]
public class MultiplePoolingInfo<T>
    where T : Enum
{
    public T type;                  // 풀링 타입
    public int createCount;         // 만들 수량
    public GameObject prefab;       // 풀링 프리팹
    public Transform container;     // 생성할 공간

    // 관리용 Queue 선언
    public Queue<GameObject> queue = new Queue<GameObject>();
}

// 메인 스크립트
public class MultiplePoolingManager<T> : Singleton<MultiplePoolingManager<T>>
    where T : Enum
{
    // 다중 오브젝트 풀링을 위한 List
    public List<MultiplePoolingInfo<T>> poolList = new List<MultiplePoolingInfo<T>>();

    private void Start()
    {
        for (int i = 0; i < poolList.Count; i++)
        {
            FillStack(poolList[i]);
        }
    }

    // 저장소에 지정한 프리팹으로 채워넣는다.
    public void FillStack(MultiplePoolingInfo<T> info)
    {
        for (int i = 0; i < info.createCount; i++)
        {
            GameObject pulledObject = Instantiate(info.prefab, info.container);
            pulledObject.SetActive(false);

            info.queue.Enqueue(pulledObject);
        }
    }

    // 타입을 받아와 Peek()과 Dequeue로 빼준다.
    public GameObject Pop(T type)
    {
        for (int i = 0; i < poolList.Count; i++)
        {
            if (type.Equals(poolList[i].type))
            {
                // 개수가 0 이하면 다시 채워준다.
                if (poolList[i].queue.Count <= 0)
                {
                    FillStack(poolList[i]);
                }

                // 오브젝트를 켜주고 넘겨준다.
                poolList[i].queue.Peek().SetActive(true);

                return poolList[i].queue.Dequeue();
            }
        }

        return null;
    }

    // 반환 받는 함수.
    public void ReturnToStack(T type, GameObject go)
    {
        // 리스트를 검색하여
        for (int i = 0; i < poolList.Count; i++)
        {
            // 넘어온 오브젝트와 타입이 같으면
            if (type.Equals(poolList[i].type))
            {
                // 그 타입을 관리하는 queue에 추가하고, 오브젝트를 꺼준다.
                poolList[i].queue.Enqueue(go);
                go.SetActive(false);
            }
        }
    }
}

2. 적용

ㆍ이전 Enemy 풀링 매니저 스크립트에 EnemyType으로 상속만 해주면 똑같이 적용이 가능하게 됩니다.

스크립트

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

public enum EnemyType
{
    Square,
    Sphere,
    Capsule,
}

public class EnemyManager : MultiplePoolingManager<EnemyType>
{  
}

Scene