[Unity] PoolManager

풀링

유니티에서 성능 향상을 위해 게임 내에 객체를 생성할 때 일일히 프리팹을 가져와 인스턴스화 하는것은 성능에 부하가 심하게 된다.

따라서 처음에 게임을 시작할 때 여러 개의 객체를 생성한 뒤, 그 객체들을 비활성화 했다가 필요시에 활성화를 하는 방법으로 성능 부하를 줄일 수 있다.

PoolManager

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

public class PoolManager
{
    #region pool
    class Pool
    {
        public GameObject Original { get; private set; }
        public Transform Root { get; set; }

        Stack<Poolable> _poolStack =  new Stack<Poolable> ();

        public void init(GameObject original, int count = 5)
        {
            Original = original;
            Root = new GameObject().transform;
            Root.name = $"{original.name}_Root";

            for (int i = 0; i < count; i++)
                Push(Create());
        }

        Poolable Create()
        {
            GameObject go = Object.Instantiate<GameObject>(Original);
            go.name = Original.name;
            return go.GetOrAddComponent<Poolable> (); 
        }

        public void Push(Poolable poolable)
        {
            if (poolable == null)
                return;

            poolable.transform.parent = Root;
            poolable.gameObject.SetActive(false);
            poolable.IsUsing = false;

            _poolStack.Push (poolable);
        }

        public Poolable Pop(Transform parent)
        {
            Poolable poolable;

            if (_poolStack.Count > 0)
                poolable = _poolStack.Pop();
            else
                poolable = Create();

            if (parent == null)
                poolable.transform.parent = Managers.Scene.CurrentScene.transform;

            poolable.gameObject.SetActive(true);
            poolable.transform.parent = parent;
            poolable.IsUsing = true;

            return poolable;
        }
    }
    #endregion

    Dictionary<string, Pool> _pool = new Dictionary<string, Pool>();
    Transform _root;

    public void init()
    {
        if (_root == null)
        {
            _root = new GameObject { name = "@Pool_Root" }.transform;
            Object.DontDestroyOnLoad(_root);
        }
    }

    public void CreatePool(GameObject original, int count = 5)
    {
        Pool pool = new Pool();
        pool.init(original, count);
        pool.Root.parent = _root;

        _pool.Add(original.name, pool);
    }

    public void Push(Poolable poolable)
    {
        string name = poolable.gameObject.name;
        if (_pool.ContainsKey(name) == false)
        {
            GameObject.Destroy(poolable.gameObject);
            return;
        }

        _pool[name].Push(poolable);
    }

    public Poolable Pop(GameObject original, Transform parent = null)
    {
        if (_pool.ContainsKey(original.name) == false)
            CreatePool(original);

        return _pool[original.name].Pop(parent);
    }

    public GameObject GetOriginal(string name)
    {
        if (_pool.ContainsKey(name) == false)
            return null;
        return _pool[name].Original;
    }

    public void Clear()
    {
        foreach (Transform child in _root)
            GameObject.Destroy(child.gameObject);

        _pool.Clear();  
    }
}

스택을 사용해서 풀링할 오브젝트를 관리한다.

먼저 Pool이라는 클래스를 생성, 풀링과 관련된 함수들을 정의한 뒤 Pool 클래스를 Dictionary로 관리한다.

PoolManager는 init으로 텅 빈 오브젝트 @Pool_Root를 생성하고 그 아래에 풀링할 오브젝트들을 넣는다.

사진과 같은 경우에는 PoolManager.Init()으로 @Pool_Root을 생성,
PoolManger.CreatePool("UnityChan")를 한 상황이다.

게임 내의 Pool_Root 아래의 [Name]_Root 하나 하나가 Dictionary의 요소가 된다.

좋은 웹페이지 즐겨찾기