using System.Collections.Generic; using UnityEngine; namespace Pooling { public class Pooler : MonoBehaviour { private static Pooler _instance; public static Pooler Instance { get { if (_instance != null) return _instance; _instance = FindObjectOfType(); if (_instance != null) return _instance; GameObject obj = new("[Object Pool]"); _instance = obj.AddComponent(); return _instance; } } private static List _tempList = new(); private Dictionary> _pooledObjects = new(); private Dictionary _spawnedObjects = new(); public static void CreatePool(T prefab, int initialPoolSize) where T : Component { CreatePool(prefab.gameObject, initialPoolSize); } public static void CreatePool(GameObject prefab, int initialPoolSize) { if (prefab == null || Instance._pooledObjects.ContainsKey(prefab)) return; List list = new(); Instance._pooledObjects.Add(prefab, list); if (initialPoolSize <= 0) return; bool active = prefab.activeSelf; prefab.SetActive(false); Transform parent = Instance.transform; while (list.Count < initialPoolSize) { GameObject obj = Instantiate(prefab, parent); list.Add(obj); } prefab.SetActive(active); } public static T Spawn(T prefab, Transform parent, Vector3 position, Quaternion rotation) where T : Component => Spawn(prefab.gameObject, parent, position, rotation).GetComponent(); public static T Spawn(T prefab, Vector3 position, Quaternion rotation) where T : Component => Spawn(prefab.gameObject, null, position, rotation).GetComponent(); public static T Spawn(T prefab, Transform parent, Vector3 position) where T : Component => Spawn(prefab.gameObject, parent, position, Quaternion.identity).GetComponent(); public static T Spawn(T prefab, Vector3 position) where T : Component => Spawn(prefab.gameObject, null, position, Quaternion.identity).GetComponent(); public static T Spawn(T prefab, Transform parent) where T : Component => Spawn(prefab.gameObject, parent, Vector3.zero, Quaternion.identity).GetComponent(); public static T Spawn(T prefab) where T : Component => Spawn(prefab.gameObject, null, Vector3.zero, Quaternion.identity).GetComponent(); public static GameObject Spawn(GameObject prefab, Transform parent, Vector3 position) => Spawn(prefab, parent, position, Quaternion.identity); public static GameObject Spawn(GameObject prefab, Vector3 position, Quaternion rotation) => Spawn(prefab, null, position, rotation); public static GameObject Spawn(GameObject prefab, Transform parent) => Spawn(prefab, parent, Vector3.zero, Quaternion.identity); public static GameObject Spawn(GameObject prefab, Vector3 position) => Spawn(prefab, null, position, Quaternion.identity); public static GameObject Spawn(GameObject prefab) => Spawn(prefab, null, Vector3.zero, Quaternion.identity); public static GameObject Spawn(GameObject prefab, Transform parent, Vector3 position, Quaternion rotation) { List list; Transform trans; GameObject obj; if (Instance._pooledObjects.TryGetValue(prefab, out list)) { obj = null; if (list.Count > 0) { while (!obj && list.Count > 0) { obj = list[0]; list.RemoveAt(0); } if (obj != null) { trans = obj.transform; trans.parent = parent; trans.localPosition = position; trans.localRotation = rotation; obj.SetActive(true); Instance._spawnedObjects.Add(obj, prefab); TryCallPooledObject(obj); return obj; } } obj = Instantiate(prefab); trans = obj.transform; trans.parent = parent; trans.localPosition = position; trans.localRotation = rotation; Instance._spawnedObjects.Add(obj, prefab); TryCallPooledObject(obj); return obj; } obj = Instantiate(prefab); trans = obj.transform; trans.parent = parent; trans.localPosition = position; trans.localRotation = rotation; TryCallPooledObject(obj); return obj; } private static void TryCallPooledObject(GameObject obj) { if(obj.TryGetComponent(out IPooledObject pooledObject)) pooledObject.OnObjectSpawn(); } public static void Recycle(T obj) where T : Component { Recycle(obj.gameObject); } public static void Recycle(GameObject obj) { GameObject prefab; if (Instance._spawnedObjects.TryGetValue(obj, out prefab)) Recycle(obj, prefab); else Destroy(obj); } private static void Recycle(GameObject obj, GameObject prefab) { Instance._pooledObjects[prefab].Add(obj); Instance._spawnedObjects.Remove(obj); obj.transform.parent = Instance.transform; obj.SetActive(false); } } }