diff --git a/Utils/ObjectPool.cs b/Utils/ObjectPool.cs new file mode 100644 index 0000000..a75b184 --- /dev/null +++ b/Utils/ObjectPool.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace DUCK.Pooling +{ + public static class ObjectPool + { + private interface Pool + { + Type ObjectType { get; } + + void Add(PoolableObject obj); + } + + private class Pool : Pool + where T : PoolableObject + { + private Queue pooledObjects = new Queue(); + + public Type ObjectType + { + get + { + return typeof(T); + } + } + + public T Get() + { + T obj = null; + while (pooledObjects.Count > 0) + { + obj = pooledObjects.Dequeue(); + } + + if (obj) + { + obj.RemoveFromPool(); + } + + return obj; + } + + public void Add(PoolableObject obj) + { + if (obj != null && !pooledObjects.Contains((T)obj)) + { + obj.AddToPool(); + pooledObjects.Enqueue((T)obj); + } + } + } + + private static Dictionary poolLookup = new Dictionary(); + + public static T Instantiate(T original = null) where T : PoolableObject + { + T obj = null; + + if (PoolExists(typeof(T))) + { + obj = GetFromPool(); + + if (obj != null) + { + if (original != null) + { + obj.CopyFrom(original); + } + + return obj; + } + } + else + { + CreatePool(); + } + + return obj ?? GameObject.Instantiate(original); + } + + public static T Instantiate(string resourcePath) where T : PoolableObject + { + T obj = null; + + if (PoolExists(typeof(T))) + { + obj = GetFromPool(); + } + else + { + CreatePool(); + } + + return obj ?? Resources.Load(resourcePath); + } + + public static void Destroy(PoolableObject obj) + { + if (obj == null) return; + + if (PoolExists(obj.GetType())) + { + ReturnToPool(obj); + } + else + { + Destroy(obj); + } + } + + private static void CreatePool() where T : PoolableObject + { + if (PoolExists(typeof(T))) return; + + poolLookup.Add(typeof(T), new Pool()); + } + + private static Pool FindPool() where T : PoolableObject + { + if (!PoolExists(typeof(T))) throw new KeyNotFoundException(typeof(T).ToString()); + + return (Pool )poolLookup[typeof(T)]; + } + + private static bool PoolExists(Type type) + { + return poolLookup.ContainsKey(type); + } + + private static T GetFromPool() where T : PoolableObject + { + return PoolExists(typeof(T)) + ? FindPool().Get() + : null; + } + + private static void ReturnToPool(PoolableObject obj) + { + if (!PoolExists(obj.GetType())) return; + + poolLookup[obj.GetType()].Add(obj); + } + } +} diff --git a/Utils/ObjectPool.cs.meta b/Utils/ObjectPool.cs.meta new file mode 100644 index 0000000..21949a1 --- /dev/null +++ b/Utils/ObjectPool.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: fd93943eb28cba74bb9c28d10409dabd +timeCreated: 1521045479 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Utils/PoolableObject.cs b/Utils/PoolableObject.cs new file mode 100644 index 0000000..281db91 --- /dev/null +++ b/Utils/PoolableObject.cs @@ -0,0 +1,24 @@ +using DUCK.Utils; +using System; +using UnityEngine; + +namespace DUCK.Pooling +{ + public class PoolableObject : MonoBehaviour + { + public event Action OnAddedToPool; + public event Action OnRemovedFromPool; + + public void AddToPool() + { + OnAddedToPool.SafeInvoke(); + } + + public void RemoveFromPool() + { + OnRemovedFromPool.SafeInvoke(); + } + + public void CopyFrom(PoolableObject instance) { } + } +} diff --git a/Utils/PoolableObject.cs.meta b/Utils/PoolableObject.cs.meta new file mode 100644 index 0000000..1a3d445 --- /dev/null +++ b/Utils/PoolableObject.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: a46d3d1059954344fb851aa38a9e4086 +timeCreated: 1521045479 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: