Forked from CodeSmile-0000011110110111/gist:34c31bd7f00670ae64e229b0063e64bf
Created
October 21, 2024 13:01
-
-
Save unitycoder/616cce4e253ac2ad91ff45c24fd24591 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using CodeSmile.Components.Registry; | |
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEditor; | |
using UnityEngine; | |
namespace CodeSmile.Components.Pool | |
{ | |
[DisallowMultipleComponent] | |
public sealed class PrefabPool : MonoBehaviour | |
{ | |
[SerializeField] [Range(10, 10000)] private Int32 m_InitialCapacity = 100; | |
[SerializeField] [Range(10, 10000)] private Int32 m_MaxCapacity = 10000; | |
private readonly Dictionary<Int32, PrefabInstancePool> m_Pools = new(); | |
private void Awake() => ComponentsRegistry.Set(this); | |
public GameObject GetInstance(GameObject prefab) | |
{ | |
var pool = GetOrCreatePool(prefab); | |
return pool.GetInstance(); | |
} | |
public void ReleaseInstance(GameObject prefab, GameObject instance) | |
{ | |
var pool = GetOrCreatePool(prefab); | |
pool.ReleaseInstance(instance); | |
} | |
public GameObject GetInstance(GameObject prefab, Vector3 position, Quaternion rotation) | |
{ | |
var pool = GetOrCreatePool(prefab); | |
var instance = pool.GetInstance(); | |
instance.transform.SetPositionAndRotation(position, rotation); | |
return instance; | |
} | |
public PrefabInstancePool CreatePool(GameObject prefab, Int32 initialCapacity, Int32 maxCapacity) | |
{ | |
var pool = GetPool(prefab); | |
if (pool != null) | |
DisposePool(prefab); | |
initialCapacity = initialCapacity <= 0 ? m_InitialCapacity : initialCapacity; | |
maxCapacity = maxCapacity <= 0 ? m_MaxCapacity : maxCapacity; | |
CreatePool(prefab, prefab.GetInstanceID(), initialCapacity, maxCapacity); | |
return GetPool(prefab); | |
} | |
public void ClearPool(GameObject prefab) | |
{ | |
var pool = GetOrCreatePool(prefab); | |
pool.Clear(); | |
} | |
public void DisposePool(GameObject prefab) | |
{ | |
var pool = GetOrCreatePool(prefab); | |
m_Pools[prefab.GetInstanceID()] = null; | |
pool.Clear(); | |
Destroy(pool.Container); | |
} | |
public PrefabInstancePool GetPool(GameObject prefab) => m_Pools[prefab.GetInstanceID()]; | |
public PrefabInstancePool GetOrCreatePool(GameObject prefab) | |
{ | |
var prefabId = prefab.GetInstanceID(); | |
if (m_Pools.ContainsKey(prefabId) == false) | |
CreatePool(prefab, prefabId, m_InitialCapacity, m_MaxCapacity); | |
return m_Pools[prefabId]; | |
} | |
private void CreatePool(GameObject prefab, Int32 prefabId, Int32 initialCapacity, Int32 maxCapacity) => | |
m_Pools[prefabId] = new PrefabInstancePool(prefab, transform, initialCapacity, maxCapacity); | |
#if UNITY_EDITOR | |
[Header("Debug")] | |
[Tooltip("Updates container names frequently with pool statistics. Editor-only.")] | |
[SerializeField] private Boolean m_ShowPoolStats; | |
[SerializeField] [Range(0.05f, 1f)] private Single m_StatsUpdateFrequency = 0.2f; | |
private void Start() => StartCoroutine(UpdatePoolNames()); | |
private IEnumerator UpdatePoolNames() | |
{ | |
while (true) | |
{ | |
yield return new WaitForSeconds(m_StatsUpdateFrequency); | |
var activeTotal = 0; | |
var inactiveTotal = 0; | |
var allTotal = 0; | |
if (m_ShowPoolStats) | |
{ | |
foreach (var pool in m_Pools.Values) | |
{ | |
var active = pool.CountActive; | |
var inactive = pool.CountInactive; | |
var all = pool.CountAll; | |
pool.Container.name = $"{pool.Prefab.name} (Active: {active}, Inactive: {inactive}, Total: {all})"; | |
activeTotal += active; | |
inactiveTotal += inactive; | |
allTotal += all; | |
} | |
name = $"{nameof(PrefabPool)} (Active: {activeTotal}, Inactive: {inactiveTotal}, Total: {allTotal})"; | |
} | |
} | |
} | |
#endif | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using UnityEditor; | |
using UnityEngine; | |
using UnityEngine.Pool; | |
using Object = UnityEngine.Object; | |
namespace CodeSmile.Components.Pool | |
{ | |
public sealed class PrefabInstancePool | |
{ | |
private readonly GameObject m_Prefab; | |
private readonly Transform m_Container; | |
private readonly ObjectPool<GameObject> m_Pool; | |
public GameObject Prefab => m_Prefab; | |
public Transform Container => m_Container; | |
public Int32 CountActive => m_Pool.CountActive; | |
public Int32 CountInactive => m_Pool.CountInactive; | |
public Int32 CountAll => m_Pool.CountAll; | |
public PrefabInstancePool(GameObject prefab, Transform parent, Int32 initialCapacity = 100, | |
Int32 maximumCapacity = 10000) | |
{ | |
if (prefab == null) | |
throw new ArgumentNullException(nameof(prefab)); | |
m_Prefab = prefab; | |
m_Container = new GameObject($"{prefab.name} Instances").transform; | |
m_Container.parent = parent; | |
m_Pool = new ObjectPool<GameObject>(OnCreate, OnGet, OnRelease, OnDestroy, true, initialCapacity, | |
maximumCapacity); | |
} | |
public GameObject GetInstance() => m_Pool.Get(); | |
public void ReleaseInstance(GameObject go) => m_Pool.Release(go); | |
public void Clear() => m_Pool.Clear(); | |
private GameObject OnCreate() => Object.Instantiate(m_Prefab, m_Container); | |
private void OnGet(GameObject go) => go.SetActive(true); | |
private void OnRelease(GameObject go) => go.SetActive(false); | |
private void OnDestroy(GameObject go) {} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEditor; | |
using UnityEngine; | |
namespace CodeSmile.Components.Pool | |
{ | |
[DisallowMultipleComponent] | |
internal sealed class AutoReleasePooledObject : MonoBehaviour | |
{ | |
internal PrefabInstancePool Pool { get; set; } | |
private void OnDisable() => Pool.ReleaseInstance(gameObject); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment