summaryrefslogtreecommitdiff
path: root/WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs
diff options
context:
space:
mode:
authorchai <215380520@qq.com>2023-05-16 16:03:51 +0800
committerchai <215380520@qq.com>2023-05-16 16:03:51 +0800
commit2afbb545027568fccc85853e18af02a7c6b2929e (patch)
tree3827873af133fe9f81041e4babbfd0d54a53f9d1 /WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs
parent88f739ea0f3440152082f34707e79328a71aabed (diff)
*misc
Diffstat (limited to 'WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs')
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs128
1 files changed, 128 insertions, 0 deletions
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs b/WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs
new file mode 100644
index 0000000..3005b27
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs
@@ -0,0 +1,128 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace WK
+{
+
+ public class UnityObjectPool<T> : System.IDisposable where T : UnityEngine.Object
+ {
+ public interface IPooledInstanceInitializer
+ {
+ void InitPooledInstance(T instance);
+ void DestroyPooledInstance(T instance);
+ }
+
+ private T _sourceObject;
+ private Transform _poolParent;
+ private int _initialSize;
+
+ private IPooledInstanceInitializer _initalizer;
+
+ private List<T> _usedInstances;
+ private Stack<T> _freeInstances;
+
+ public UnityObjectPool(T sourceObject, Transform poolParent, IPooledInstanceInitializer initializer, int initialSize = 0)
+ {
+ Debug.Assert(sourceObject != null);
+ Debug.Assert(poolParent != null);
+ Debug.Assert(initializer != null);
+ Debug.Assert(initialSize >= 0);
+
+ _sourceObject = sourceObject;
+ _poolParent = poolParent;
+ _initalizer = initializer;
+ _initialSize = initialSize;
+
+ _usedInstances = new List<T>();
+ _freeInstances = new Stack<T>(initialSize);
+
+ for (int i = 0; i < _initialSize; ++i)
+ {
+ T instance = CreateInstance();
+ _freeInstances.Push(instance);
+ }
+ }
+
+ public T Acquire()
+ {
+ T instance;
+ if (_freeInstances.Count > 0)
+ {
+ instance = _freeInstances.Pop();
+ }
+ else
+ {
+ instance = CreateInstance();
+ }
+
+ _usedInstances.Add(instance);
+
+ return instance;
+ }
+
+ public void Release(T instance)
+ {
+ Debug.Assert(instance != null);
+ Debug.Assert(!_freeInstances.Contains(instance));
+
+ bool res = _usedInstances.Remove(instance);
+ Debug.Assert(res);
+ _freeInstances.Push(instance);
+ }
+
+ private T CreateInstance()
+ {
+ T instance = Object.Instantiate(_sourceObject, _poolParent);
+
+ // Let the client code initialize the object however it want to
+ _initalizer.InitPooledInstance(instance);
+
+ return instance;
+ }
+
+ #region IDisposable Support
+ private bool _disposed = false;
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (Application.isPlaying)
+ {
+ Debug.Assert(!_disposed, "Trying to dispose an pool twice!");
+ Debug.Assert(_usedInstances.Count == 0, "Disposing pool before releasing all objects!");
+ }
+
+ foreach (T instance in _freeInstances)
+ {
+ // We can't destroy a UnityEngine.Object without knowing if it's a Gameobject or Component. Calling Destroy(instance) directly here will give not destroy the Gameobject if it's a component
+ _initalizer.DestroyPooledInstance(instance);
+ }
+ _freeInstances.Clear();
+
+ _sourceObject = null;
+ _poolParent = null;
+ _initalizer = null;
+
+ _disposed = true;
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ System.GC.SuppressFinalize(this);
+ }
+
+#if ENABLE_ASSERTS
+ ~UnityObjectPool()
+ {
+ MainThreadDispatcher.BeginInvoke(() => // Can't call Application.isPlaying in Unity's finalizer thread
+ {
+ if (Application.isPlaying)
+ {
+ DebugTools.Assert(false, string.Format("Failed to dispose a pool of type {0}!", typeof(T)));
+ }
+ });
+ }
+#endif
+ #endregion
+ }
+}