diff options
author | chai <215380520@qq.com> | 2023-05-16 16:03:51 +0800 |
---|---|---|
committer | chai <215380520@qq.com> | 2023-05-16 16:03:51 +0800 |
commit | 2afbb545027568fccc85853e18af02a7c6b2929e (patch) | |
tree | 3827873af133fe9f81041e4babbfd0d54a53f9d1 /WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs | |
parent | 88f739ea0f3440152082f34707e79328a71aabed (diff) |
*misc
Diffstat (limited to 'WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs')
-rw-r--r-- | WorldlineKeepers/Assets/Scripts/Tools/UnityObjectPool.cs | 128 |
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 + } +} |