using System.Collections.Generic; using System.Linq; using UnityEngine; public class PoolManager { #region Pool // Pool하는데 만약에 A 와 B가 있는데 이게 전부 다 같은 Pool_root 밑에 있으면 // A를 Push 했다가 B를 Pop 할 수도 있음 // 그래서 A와 B를 구분하기 위해서 Dictionary를 사용함 class Pool { public GameObject Original {get; private set;} // A 나 B같은 오브젝트들이 뭉쳐질 위치 public Transform Root {get; private set;} // 스택 큐 다상관 없는데 Stack _poolStack = new Stack(); 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++) { Poolable poolable = Create(); Push(poolable); } } Poolable Create() { GameObject go = Object.Instantiate(Original); go.name = Original.name; return go.GetOrAddComponent(); } 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(); poolable.gameObject.SetActive(true); //@DontDestroyOnLoad 해제 if (parent == null) poolable.transform.parent = Managers.Scene.CurrentScene.transform; poolable.transform.parent = parent; poolable.IsUsing = true; return poolable; } } #endregion Dictionary _pool = new Dictionary(); Transform _root; public void Init() { if (_root == null) { _root = new GameObject { name = "@Pool_Root" }.transform; Object.DontDestroyOnLoad(_root); } } 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 void CreatePool(GameObject original, int count = 5) { Pool pool = new Pool(); pool.Init(original, count); pool.Root.parent = _root.transform; _pool.Add(original.name, pool); } 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; // return Managers.Resource.Load($"Prefabs/{path}"); } // 이걸 다 날려야 하나 안날려야 하나는 게임마다 다를거 같다. // 대부분의 경우에는 안날려도 큰 문제는 없을거 같긴한데 // 대규모 MMORPG 같은 경우 - 지역풀이 너무 다른 경우 기존의 리소스를 날려버리고 다시 받는 경우가 있을 수 있다. public void Clear() { foreach (Transform child in _root) GameObject.Destroy(child.gameObject); _pool.Clear(); } }