├── ProjectSettings ├── TagManager.asset ├── TimeManager.asset ├── AudioManager.asset ├── EditorSettings.asset ├── InputManager.asset ├── NavMeshLayers.asset ├── NetworkManager.asset ├── DynamicsManager.asset ├── GraphicsSettings.asset ├── ProjectSettings.asset ├── QualitySettings.asset ├── EditorBuildSettings.asset └── Physics2DSettings.asset ├── Assets ├── Examples.meta ├── Scripts.meta ├── Examples │ ├── PoolingGameObjects │ │ ├── Bullet.png │ │ ├── Bullet.prefab │ │ ├── Bullet.prefab.meta │ │ ├── PoolingGameObjects.unity.meta │ │ ├── PoolingGameObjects.unity │ │ ├── Gun.cs.meta │ │ ├── Bullet.cs.meta │ │ ├── Bullet.cs │ │ ├── Gun.cs │ │ └── Bullet.png.meta │ ├── PoolingCSharpObjects.meta │ ├── PoolingGameObjects.meta │ └── PoolingCSharpObjects │ │ ├── PoolingCSharpObjects.unity.meta │ │ ├── PoolingCSharpObjects.unity │ │ ├── EventBus.cs.meta │ │ └── EventBus.cs └── Scripts │ ├── ObjectPool.cs.meta │ ├── Singleton.cs.meta │ ├── PoolManager.cs.meta │ ├── ObjectPoolContainer.cs.meta │ ├── ObjectPoolContainer.cs │ ├── Singleton.cs │ ├── ObjectPool.cs │ └── PoolManager.cs ├── .gitignore └── README.md /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshLayers.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/ProjectSettings/NavMeshLayers.asset -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /Assets/Examples.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fb37bff3530f9884f879e570ec145b8e 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8b8e380f70c7bc849b89c34c8de5d4a5 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /Assets/Examples/PoolingGameObjects/Bullet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/Assets/Examples/PoolingGameObjects/Bullet.png -------------------------------------------------------------------------------- /Assets/Examples/PoolingGameObjects/Bullet.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/Assets/Examples/PoolingGameObjects/Bullet.prefab -------------------------------------------------------------------------------- /Assets/Examples/PoolingCSharpObjects.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0f066329e0db13a4899e76875c9bdb02 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Examples/PoolingGameObjects.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b6f4a6e2b6c8fd048ac883e25ce2fe49 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Examples/PoolingGameObjects/Bullet.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e714f4b086504d747a4926157f5eb3e0 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Examples/PoolingGameObjects/PoolingGameObjects.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 568340644b012c441b25f22f4042b417 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Examples/PoolingCSharpObjects/PoolingCSharpObjects.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a080aca53c6f52e4b87b1653dfd85d53 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Examples/PoolingGameObjects/PoolingGameObjects.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/Assets/Examples/PoolingGameObjects/PoolingGameObjects.unity -------------------------------------------------------------------------------- /Assets/Examples/PoolingCSharpObjects/PoolingCSharpObjects.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thefuntastic/unity-object-pool/HEAD/Assets/Examples/PoolingCSharpObjects/PoolingCSharpObjects.unity -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /Library 2 | /Temp 3 | *.booproj 4 | *.pidb 5 | *.csproj 6 | *.unityproj 7 | *.sln 8 | *.userprefs 9 | *.sln 10 | *.Thumbs.db 11 | *.suo 12 | *.dgml 13 | /obj 14 | /Reference 15 | /_ReSharper.*-csharp -------------------------------------------------------------------------------- /Assets/Scripts/ObjectPool.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: abe90b2b30f65a548825fbeba21cf864 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Scripts/Singleton.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f1f18a1ef4b8dab4c867888556d08c85 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Scripts/PoolManager.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 430d968e63581624e84fc43c08982663 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Scripts/ObjectPoolContainer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 64373aeb4afc30d43a9cbef9f4e90778 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Examples/PoolingGameObjects/Gun.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 21a997f859b135548a90f7fed2b3a1c8 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Examples/PoolingCSharpObjects/EventBus.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 94c656b340657374f8761adc745aa367 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Examples/PoolingGameObjects/Bullet.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 699775de2619ccc44bb6a7aa5ed620ea 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Scripts/ObjectPoolContainer.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace MonsterLove.Collections 3 | { 4 | public class ObjectPoolContainer 5 | { 6 | private T item; 7 | 8 | public bool Used { get; private set; } 9 | 10 | public void Consume() 11 | { 12 | Used = true; 13 | } 14 | 15 | public T Item 16 | { 17 | get 18 | { 19 | return item; 20 | } 21 | set 22 | { 23 | item = value; 24 | } 25 | } 26 | 27 | public void Release() 28 | { 29 | Used = false; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Assets/Examples/PoolingGameObjects/Bullet.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class Bullet : MonoBehaviour 5 | { 6 | public float accel; 7 | private float velocity; 8 | 9 | void OnEnable() 10 | { 11 | velocity = 0; 12 | } 13 | 14 | void Update() 15 | { 16 | velocity += accel; 17 | 18 | transform.Translate(0, velocity, 0); 19 | 20 | if(transform.position.y > 10) 21 | { 22 | Finish(); 23 | } 24 | } 25 | 26 | void Finish() 27 | { 28 | PoolManager.ReleaseObject(this.gameObject); 29 | 30 | //Note: 31 | // This takes the gameObject instance, and NOT the prefab instance. 32 | // Without this call the object will never be available for re-use! 33 | // gameObject.SetActive(false) is automatically called 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Assets/Scripts/Singleton.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class Singleton : MonoBehaviour where T : Singleton 4 | { 5 | public static T Instance 6 | { 7 | get 8 | { 9 | if (instance == null) 10 | { 11 | T[] managers = Object.FindObjectsOfType(typeof(T)) as T[]; 12 | if (managers.Length != 0) 13 | { 14 | if (managers.Length == 1) 15 | { 16 | instance = managers[0]; 17 | instance.gameObject.name = typeof(T).Name; 18 | return instance; 19 | } 20 | else 21 | { 22 | Debug.LogError("Class " + typeof(T).Name + " exists multiple times in violation of singleton pattern. Destroying all copies"); 23 | foreach (T manager in managers) 24 | { 25 | Destroy(manager.gameObject); 26 | } 27 | } 28 | } 29 | var go = new GameObject(typeof(T).Name, typeof(T)); 30 | instance = go.GetComponent(); 31 | DontDestroyOnLoad(go); 32 | } 33 | return instance; 34 | } 35 | set 36 | { 37 | instance = value as T; 38 | } 39 | } 40 | private static T instance; 41 | } 42 | -------------------------------------------------------------------------------- /Assets/Examples/PoolingGameObjects/Gun.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class Gun : MonoBehaviour 5 | { 6 | public GameObject bulletPrefab; 7 | 8 | //Optional: Warm the pool and preallocate memory 9 | void Start() 10 | { 11 | PoolManager.WarmPool(bulletPrefab, 20); 12 | 13 | //Notes 14 | // Make sure the prefab is inactive, or else it will run update before first use 15 | } 16 | 17 | void Update() 18 | { 19 | if(Input.GetButton("Fire1")) 20 | { 21 | Vector3 pos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10f); 22 | FireBullet(Camera.main.ScreenToWorldPoint(pos), Quaternion.identity); 23 | } 24 | } 25 | 26 | //Spawn pooled objects 27 | void FireBullet(Vector3 position, Quaternion rotation) 28 | { 29 | var bullet = PoolManager.SpawnObject(bulletPrefab, position, rotation).GetComponent(); 30 | 31 | //Notes: 32 | // bullet.gameObject.SetActive(true) is automatically called on spawn 33 | // When done with the instance, you MUST release it! 34 | // If the number of objects in use exceeds the pool size, new objects will be created 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /Assets/Examples/PoolingGameObjects/Bullet.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 43f3d8a9a7fdd6f469aea742dd9af679 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 0 8 | linearTexture: 0 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | seamlessCubemap: 0 23 | textureFormat: -1 24 | maxTextureSize: 1024 25 | textureSettings: 26 | filterMode: -1 27 | aniso: 1 28 | mipBias: -1 29 | wrapMode: 1 30 | nPOTScale: 0 31 | lightmap: 0 32 | compressionQuality: 50 33 | spriteMode: 1 34 | spriteExtrude: 1 35 | spriteMeshType: 1 36 | alignment: 0 37 | spritePivot: {x: .5, y: .5} 38 | spritePixelsToUnits: 100 39 | alphaIsTransparency: 1 40 | textureType: 8 41 | buildTargetSettings: [] 42 | spriteSheet: 43 | sprites: [] 44 | spritePackingTag: 45 | userData: 46 | -------------------------------------------------------------------------------- /Assets/Examples/PoolingCSharpObjects/EventBus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using MonsterLove.Collections; 4 | using UnityEngine; 5 | using System.Collections; 6 | 7 | public class EventBus : MonoBehaviour 8 | { 9 | public float delay = 1; 10 | 11 | private ObjectPool eventPool; 12 | private List activeEvents; 13 | 14 | void Awake () 15 | { 16 | eventPool = new ObjectPool(()=> new DelayedEvent(), 5); 17 | activeEvents = new List(); 18 | } 19 | 20 | void Update() 21 | { 22 | if(Input.GetMouseButtonDown(0)) 23 | { 24 | SpawnEvent(); 25 | } 26 | 27 | for (int i = 0; i < activeEvents.Count; i++) 28 | { 29 | activeEvents[i].Update(Time.time); 30 | } 31 | } 32 | 33 | private void SpawnEvent() 34 | { 35 | var evt = eventPool.GetItem(); 36 | evt.Start(Time.time, delay); 37 | evt.Triggered += OnEvtComplete; 38 | activeEvents.Add(evt); 39 | 40 | } 41 | 42 | private void OnEvtComplete(DelayedEvent evt) 43 | { 44 | evt.Triggered -= OnEvtComplete; 45 | activeEvents.Remove(evt); 46 | eventPool.ReleaseItem(evt); 47 | Debug.Log("Delayed event started at " + evt.startTime + " completed at "+ evt.endTime); 48 | } 49 | 50 | private void OnGUI() 51 | { 52 | GUILayout.BeginArea(new Rect(20,20,400,200)); 53 | 54 | GUILayout.Label("Click Mouse to create Delayed Event"); 55 | GUILayout.Label("Total used objects: " + eventPool.CountUsedItems); 56 | GUILayout.Label("Total objects in pool: " + eventPool.Count); 57 | 58 | GUILayout.EndArea(); 59 | } 60 | } 61 | 62 | public class DelayedEvent 63 | { 64 | public event Action Triggered; 65 | 66 | public float startTime; 67 | public float endTime; 68 | private float delay; 69 | 70 | public void Start(float time, float delay) 71 | { 72 | this.delay = delay; 73 | this.startTime = time; 74 | } 75 | 76 | public void Update(float time) 77 | { 78 | if(time - startTime > delay) 79 | { 80 | endTime = time; 81 | Trigger(); 82 | } 83 | } 84 | 85 | public void Trigger() 86 | { 87 | if(Triggered != null) 88 | { 89 | Triggered(this); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Assets/Scripts/ObjectPool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace MonsterLove.Collections 6 | { 7 | public class ObjectPool 8 | { 9 | private List> list; 10 | private Dictionary> lookup; 11 | private Func factoryFunc; 12 | private int lastIndex = 0; 13 | 14 | public ObjectPool(Func factoryFunc, int initialSize) 15 | { 16 | this.factoryFunc = factoryFunc; 17 | 18 | list = new List>(initialSize); 19 | lookup = new Dictionary>(initialSize); 20 | 21 | Warm(initialSize); 22 | } 23 | 24 | private void Warm(int capacity) 25 | { 26 | for (int i = 0; i < capacity; i++) 27 | { 28 | CreateContainer(); 29 | } 30 | } 31 | 32 | private ObjectPoolContainer CreateContainer() 33 | { 34 | var container = new ObjectPoolContainer(); 35 | container.Item = factoryFunc(); 36 | list.Add(container); 37 | return container; 38 | } 39 | 40 | public T GetItem() 41 | { 42 | ObjectPoolContainer container = null; 43 | for (int i = 0; i < list.Count; i++) 44 | { 45 | lastIndex++; 46 | if (lastIndex > list.Count - 1) lastIndex = 0; 47 | 48 | if (list[lastIndex].Used) 49 | { 50 | continue; 51 | } 52 | else 53 | { 54 | container = list[lastIndex]; 55 | break; 56 | } 57 | } 58 | 59 | if (container == null) 60 | { 61 | container = CreateContainer(); 62 | } 63 | 64 | container.Consume(); 65 | lookup.Add(container.Item, container); 66 | return container.Item; 67 | } 68 | 69 | public void ReleaseItem(object item) 70 | { 71 | ReleaseItem((T) item); 72 | } 73 | 74 | public void ReleaseItem(T item) 75 | { 76 | if (lookup.ContainsKey(item)) 77 | { 78 | var container = lookup[item]; 79 | container.Release(); 80 | lookup.Remove(item); 81 | } 82 | else 83 | { 84 | Debug.LogWarning("This object pool does not contain the item provided: " + item); 85 | } 86 | } 87 | 88 | public int Count 89 | { 90 | get { return list.Count; } 91 | } 92 | 93 | public int CountUsedItems 94 | { 95 | get { return lookup.Count; } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Unity Object Pool 2 | ================= 3 | 4 | An elegant object pool and manager implementation for Unity 5 | 6 | Overview 7 | ---- 8 | 9 | An object pool provides an efficient way to reuse objects, and thus keep the memory foot print of all dynamically created objects within fixed bounds. This is crucial for maintianing consistent framerates in realtime games (especially on mobile), as frequent garbage collection spikes would likley lead to inconsistent performance. 10 | 11 | Usage 12 | ---- 13 | There are two main points of interest: 14 | 15 | 1. A pool manager class for Unity Game Objects that allows you to easily pool scene objects 16 | 17 | 2. A generic object pool collection that can be used for non Unity Game Objects. 18 | 19 | ###Pooling Unity Game Objects: 20 | PoolManager.cs is a very flexible class that co-ordinates all your pooling requirements in a scene. 21 | 22 | It requires no initialization, can be called from anywhere, and dynamically accomodates any prefab game object. 23 | 24 | ```csharp 25 | //Optional: Warm the pool and preallocate memory 26 | void Start() 27 | { 28 | PoolManager.WarmPool(bulletPrefab, 50); 29 | 30 | //Notes 31 | // Make sure the prefab is inactive, or else it will run update before first use 32 | } 33 | 34 | //Spawn pooled objects 35 | void FireBullet(Vector3 position, Quaternion rotation) 36 | { 37 | var bullet = PoolManager.SpawnObject(bulletPrefab, position, rotation).GetComponent(); 38 | 39 | //Notes: 40 | // bullet.gameObject.SetActive(true) is automatically called on spawn 41 | // When done with the instance, you MUST release it! 42 | // if the number of objects in use exceeds the pool size, new objects will be created 43 | 44 | } 45 | 46 | //In Bullet.cs 47 | void Finish() 48 | { 49 | PoolManager.ReleaseObject(this.gameObject); 50 | 51 | //Notes 52 | // This takes the gameObject instance, and NOT the prefab instance. 53 | // Without this call the object will never be available for re-use! 54 | // gameObject.SetActive(false) is automatically called; 55 | } 56 | 57 | ``` 58 | 59 | ###Pooling C# objects: 60 | This allows you to pool objects not derived from the Unity engine. In fact if you replaced the Debug statemetns you could use this in any other .NET or C# project. 61 | 62 | This is the backbone of the PoolManager.cs class, but you can use it directly. For instance you could use it to pool events in a memory friendly observer pattern: 63 | ```csharp 64 | //The factoryFunc (first arg) is the crux of the ObjectPool class. 65 | //It privodes a way for the ObjectPool to dynamically create new objects 66 | eventPool = new ObjectPool(()=> new DelayedEvent(), 5); 67 | 68 | var evt = eventPool.GetItem(); 69 | evt.Start(Time.time, delay); //Configure object 70 | 71 | //On event done: 72 | eventPool.ReleaseItem(evt); 73 | 74 | ``` 75 | 76 | History 77 | ---- 78 | Created by Peter Cardwell-Gardner 79 | 80 | Born out of the realization that he was writing the samething over and over again, this was designed to be the last object pool you ever need. 81 | 82 | This project is used extensively in the upcoming Unity game *[Cadence](http://www.playcadence.com)* by [Made With Monster Love](http://www.madewithmonsterlove.com). 83 | 84 | Licence 85 | --- 86 | MIT -------------------------------------------------------------------------------- /Assets/Scripts/PoolManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using MonsterLove.Collections; 4 | using UnityEngine; 5 | 6 | public class PoolManager : Singleton 7 | { 8 | public bool logStatus; 9 | public Transform root; 10 | 11 | private Dictionary> prefabLookup; 12 | private Dictionary> instanceLookup; 13 | 14 | private bool dirty = false; 15 | 16 | void Awake () 17 | { 18 | prefabLookup = new Dictionary>(); 19 | instanceLookup = new Dictionary>(); 20 | } 21 | 22 | void Update() 23 | { 24 | if(logStatus && dirty) 25 | { 26 | PrintStatus(); 27 | dirty = false; 28 | } 29 | } 30 | 31 | public void warmPool(GameObject prefab, int size) 32 | { 33 | if(prefabLookup.ContainsKey(prefab)) 34 | { 35 | throw new Exception("Pool for prefab " + prefab.name + " has already been created"); 36 | } 37 | var pool = new ObjectPool(() => { return InstantiatePrefab(prefab); }, size); 38 | prefabLookup[prefab] = pool; 39 | 40 | dirty = true; 41 | } 42 | 43 | public GameObject spawnObject(GameObject prefab) 44 | { 45 | return spawnObject(prefab, Vector3.zero, Quaternion.identity); 46 | } 47 | 48 | public GameObject spawnObject(GameObject prefab, Vector3 position, Quaternion rotation) 49 | { 50 | if (!prefabLookup.ContainsKey(prefab)) 51 | { 52 | WarmPool(prefab, 1); 53 | } 54 | 55 | var pool = prefabLookup[prefab]; 56 | 57 | var clone = pool.GetItem(); 58 | clone.transform.SetPositionAndRotation(position, rotation); 59 | clone.SetActive(true); 60 | 61 | instanceLookup.Add(clone, pool); 62 | dirty = true; 63 | return clone; 64 | } 65 | 66 | public void releaseObject(GameObject clone) 67 | { 68 | clone.SetActive(false); 69 | 70 | if(instanceLookup.ContainsKey(clone)) 71 | { 72 | instanceLookup[clone].ReleaseItem(clone); 73 | instanceLookup.Remove(clone); 74 | dirty = true; 75 | } 76 | else 77 | { 78 | Debug.LogWarning("No pool contains the object: " + clone.name); 79 | } 80 | } 81 | 82 | 83 | private GameObject InstantiatePrefab(GameObject prefab) 84 | { 85 | var go = Instantiate(prefab) as GameObject; 86 | if (root != null) go.transform.parent = root; 87 | return go; 88 | } 89 | 90 | public void PrintStatus() 91 | { 92 | foreach (KeyValuePair> keyVal in prefabLookup) 93 | { 94 | Debug.Log(string.Format("Object Pool for Prefab: {0} In Use: {1} Total {2}", keyVal.Key.name, keyVal.Value.CountUsedItems, keyVal.Value.Count)); 95 | } 96 | } 97 | 98 | #region Static API 99 | 100 | public static void WarmPool(GameObject prefab, int size) 101 | { 102 | Instance.warmPool(prefab, size); 103 | } 104 | 105 | public static GameObject SpawnObject(GameObject prefab) 106 | { 107 | return Instance.spawnObject(prefab); 108 | } 109 | 110 | public static GameObject SpawnObject(GameObject prefab, Vector3 position, Quaternion rotation) 111 | { 112 | return Instance.spawnObject(prefab, position, rotation); 113 | } 114 | 115 | public static void ReleaseObject(GameObject clone) 116 | { 117 | Instance.releaseObject(clone); 118 | } 119 | 120 | #endregion 121 | } 122 | 123 | 124 | --------------------------------------------------------------------------------