Advertisement
Guest User

Untitled

a guest
Jun 25th, 2017
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.11 KB | None | 0 0
  1. // Modified from Quill18's version
  2.  
  3. using UnityEngine;
  4. using System.Collections.Generic;
  5.  
  6. public static class SimplePool
  7. {
  8. // You can avoid resizing of the Stack's internal array by
  9. // setting this to a number equal to or greater to what you
  10. // expect most of your pool sizes to be.
  11. // Note, you can also use Preload() to set the initial size
  12. // of a pool -- this can be handy if only some of your pools
  13. // are going to be exceptionally large (for example, your bullets.)
  14. const int DEFAULT_POOL_SIZE = 3;
  15.  
  16. /// <summary>
  17. /// The Pool class represents the pool for a particular prefab.
  18. /// </summary>
  19. class Pool
  20. {
  21. // We append an id to the name of anything we instantiate.
  22. // This is purely cosmetic.
  23. int nextId = 1;
  24.  
  25. // The structure containing our inactive objects.
  26. // Why a Stack and not a List? Because we'll never need to
  27. // pluck an object from the start or middle of the array.
  28. // We'll always just grab the last one, which eliminates
  29. // any need to shuffle the objects around in memory.
  30. Stack<GameObject> inactive;
  31.  
  32. // The prefab that we are pooling
  33. GameObject prefab;
  34.  
  35. // Constructor
  36. public Pool(GameObject prefab, int initialQty)
  37. {
  38. this.prefab = prefab;
  39.  
  40. // If Stack uses a linked list internally, then this
  41. // whole initialQty thing is a placebo that we could
  42. // strip out for more minimal code.
  43. inactive = new Stack<GameObject>(initialQty);
  44. }
  45.  
  46. // Spawn an object from our pool
  47. public GameObject Spawn(Vector3 pos, Quaternion rot)
  48. {
  49. GameObject obj;
  50. if (inactive.Count == 0)
  51. {
  52. // We don't have an object in our pool, so we
  53. // instantiate a whole new object.
  54. obj = (GameObject)GameObject.Instantiate(prefab, pos, rot);
  55. obj.name = prefab.name + " (" + (nextId++) + ")";
  56.  
  57. // Add a PoolMember component so we know what pool
  58. // we belong to.
  59. obj.AddComponent<PoolMember>().myPool = this;
  60. }
  61. else
  62. {
  63. // Grab the last object in the inactive array
  64. obj = inactive.Pop();
  65.  
  66. if (obj == null)
  67. {
  68. // The inactive object we expected to find no longer exists.
  69. // The most likely causes are:
  70. // - Someone calling Destroy() on our object
  71. // - A scene change (which will destroy all our objects).
  72. // NOTE: This could be prevented with a DontDestroyOnLoad
  73. // if you really don't want this.
  74. // No worries -- we'll just try the next one in our sequence.
  75.  
  76. return Spawn(pos, rot);
  77. }
  78. }
  79.  
  80. obj.transform.localScale = Vector3.one;
  81. obj.transform.position = pos;
  82. obj.transform.rotation = rot;
  83. obj.SetActive(true);
  84. return obj;
  85.  
  86. }
  87.  
  88. // overload to allow for setting a parent
  89. public GameObject Spawn(Vector3 pos, Quaternion rot, Transform parent)
  90. {
  91. GameObject go = Spawn(pos, rot);
  92. go.transform.SetParent(parent);
  93. return go;
  94. }
  95.  
  96. // Return an object to the inactive pool.
  97. public void Despawn(GameObject obj)
  98. {
  99. obj.SetActive(false);
  100.  
  101. // Since Stack doesn't have a Capacity member, we can't control
  102. // the growth factor if it does have to expand an internal array.
  103. // On the other hand, it might simply be using a linked list
  104. // internally. But then, why does it allow us to specificy a size
  105. // in the constructor? Stack is weird.
  106. inactive.Push(obj);
  107. }
  108.  
  109. }
  110.  
  111.  
  112. /// <summary>
  113. /// Added to freshly instantiated objects, so we can link back
  114. /// to the correct pool on despawn.
  115. /// </summary>
  116. class PoolMember : MonoBehaviour
  117. {
  118. public Pool myPool;
  119. }
  120.  
  121. // All of our pools
  122. static Dictionary<GameObject, Pool> pools;
  123.  
  124. /// <summary>
  125. /// Init our dictionary.
  126. /// </summary>
  127. static void Init(GameObject prefab = null, int qty = DEFAULT_POOL_SIZE)
  128. {
  129. if (pools == null)
  130. {
  131. pools = new Dictionary<GameObject, Pool>();
  132. }
  133. if (prefab != null && pools.ContainsKey(prefab) == false)
  134. {
  135. pools[prefab] = new Pool(prefab, qty);
  136. }
  137. }
  138.  
  139. /// <summary>
  140. /// If you want to preload a few copies of an object at the start
  141. /// of a scene, you can use this. Really not needed unless you're
  142. /// going to go from zero instances to 10+ very quickly.
  143. /// Could technically be optimized more, but in practice the
  144. /// Spawn/Despawn sequence is going to be pretty darn quick and
  145. /// this avoids code duplication.
  146. /// </summary>
  147. static public void Preload(GameObject prefab, int qty = 1)
  148. {
  149. Init(prefab, qty);
  150.  
  151. // Make an array to grab the objects we're about to pre-spawn.
  152. GameObject[] obs = new GameObject[qty];
  153. for (int i = 0; i < qty; i++)
  154. {
  155. obs[i] = Spawn(prefab, Vector3.zero, Quaternion.identity);
  156. }
  157.  
  158. // Now despawn them all.
  159. for (int i = 0; i < qty; i++)
  160. {
  161. Despawn(obs[i]);
  162. }
  163. }
  164.  
  165. // overload for parent setting
  166. static public void Preload(GameObject prefab, int qty, Transform parent)
  167. {
  168. Init(prefab, qty);
  169.  
  170. // Make an array to grab the objects we're about to pre-spawn.
  171. GameObject[] obs = new GameObject[qty];
  172. for (int i = 0; i < qty; i++)
  173. {
  174. obs[i] = Spawn(prefab, Vector3.zero, Quaternion.identity, parent);
  175. }
  176.  
  177. // Now despawn them all.
  178. for (int i = 0; i < qty; i++)
  179. {
  180. Despawn(obs[i]);
  181. }
  182. }
  183.  
  184. /// <summary>
  185. /// Spawns a copy of the specified prefab (instantiating one if required).
  186. /// NOTE: Remember that Awake() or Start() will only run on the very first
  187. /// spawn and that member variables won't get reset. OnEnable will run
  188. /// after spawning -- but remember that toggling IsActive will also
  189. /// call that function.
  190. /// </summary>
  191. static public GameObject Spawn(GameObject prefab, Vector3 pos, Quaternion rot)
  192. {
  193. Init(prefab);
  194.  
  195. return pools[prefab].Spawn(pos, rot);
  196. }
  197.  
  198. static public GameObject Spawn(GameObject prefab, Vector3 pos, Quaternion rot, Transform parent)
  199. {
  200. Init(prefab);
  201.  
  202. return pools[prefab].Spawn(pos, rot, parent);
  203. }
  204.  
  205. /// <summary>
  206. /// Despawn the specified gameobject back into its pool.
  207. /// </summary>
  208. static public void Despawn(GameObject obj)
  209. {
  210. PoolMember pm = obj.GetComponent<PoolMember>();
  211. if (pm == null)
  212. {
  213. Debug.Log("Object '" + obj.name + "' wasn't spawned from a pool. Destroying it instead.");
  214. GameObject.Destroy(obj);
  215. }
  216. else
  217. {
  218. pm.myPool.Despawn(obj);
  219. }
  220. }
  221.  
  222. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement