using System; using System.Collections.Generic; using UnityEngine; namespace GuruClient { public class GameObjectPool { private int _capacity = 10; private GameObject _prefab; private Transform _root; private Stack _cache; private Dictionary _activeObj; private List _tmpList; private Action _onInit; private Action _onRecycle; public static GameObjectPool CreatePool(GameObject prefab, int capacity = 10, bool isPreLoad = false) { GameObjectPool pool = new GameObjectPool(); pool._prefab = prefab; pool._capacity = capacity; pool._cache = new Stack(capacity); pool._tmpList = new List(); pool._activeObj = new Dictionary(); pool._root = new GameObject(prefab.name + " [Pool]").transform; // pool._root.DontDestroyOnLoad(pool._root); pool._root.gameObject.SetActive(false); if (isPreLoad) { PreLoad(pool); } return pool; } private static void PreLoad(GameObjectPool pool, bool worldPositionStays = true) { for (int i = 0; i < pool._capacity; i++) { GameObject obj = GameObject.Instantiate(pool._prefab); obj.transform.SetParent(pool._root, worldPositionStays); } } private GameObjectPool() {} public void OnInit(Action action) { _onInit = action; } public void OnRecycle(Action action) { _onRecycle = action; } public GameObject GetObj(Transform parent = null, bool worldPositionStays = true) { GameObject obj = null; if (_cache.Count <= 0) { obj = GameObject.Instantiate(_prefab); } else { obj = _cache.Pop(); if (obj == null) { obj = GameObject.Instantiate(_prefab); } } int hash = obj.GetHashCode(); _activeObj[hash] = obj; obj.transform.SetParent(parent, worldPositionStays); if (!obj.activeSelf) { obj.SetActive(true); } obj.transform.localScale=Vector3.one; _onInit?.Invoke(obj); return obj; } public bool RecycleObj(GameObject obj) { if (obj == null) { return false; } int hash = obj.GetHashCode(); if (_activeObj.ContainsKey(hash)) { _activeObj.Remove(hash); } if (_cache.Count < _capacity) { _onRecycle?.Invoke(obj); _cache.Push(obj); obj.transform.SetParent(_root); return true; } GameObject.Destroy(obj); return false; } public void RecycleAll() { foreach (var kv in _activeObj) { _tmpList.Add(kv.Value); } foreach (GameObject obj in _tmpList) { if (!RecycleObj(obj)) { break; } } _activeObj.Clear(); _tmpList.Clear(); } public void Destroy() { GameObject.Destroy(_root.gameObject); _cache.Clear(); } } }