1 using System.Collections.Generic; 2 using UnityEngine; 3 4 namespace TMoonObjectPool 5 { 6 /// <summary> 7 /// 对象池 8 /// </summary> 9 public class GameObjectPool 10 { 11 /// <summary> 12 /// 对象池的名字 13 /// </summary> 14 public string name = string.Empty; 15 16 /// <summary> 17 /// 对象池拥有的对象 18 /// </summary> 19 public GameObject obj = null; 20 21 /// <summary> 22 /// 对有效的对象栈存储 23 /// </summary> 24 private Stack<GameObject> available; 25 26 /// <summary> 27 /// 保存所有的对象 28 /// </summary> 29 private List<GameObject> all; 30 31 /// <summary> 32 /// 构造函数初始化 33 /// </summary> 34 /// <param name="name"></param> 35 /// <param name="obj"></param> 36 public GameObjectPool(string name, GameObject obj) 37 { 38 this.name = name; 39 this.obj = obj; 40 available = new Stack<GameObject>(); 41 all = new List<GameObject>(); 42 } 43 44 /// <summary> 45 /// 从对象池中分配一个对象 46 /// </summary> 47 /// <returns></returns> 48 public GameObject Allocate(Vector3 position, Quaternion rotation) 49 { 50 51 GameObject go; 52 53 // 创建对象 54 if (available.Count == 0) 55 { 56 go = GameObject.Instantiate(obj, position, rotation); 57 all.Add(go); 58 } 59 // 使用已存在的 60 else 61 { 62 go = available.Pop(); 63 go.transform.position = position; 64 go.transform.rotation = rotation; 65 } 66 67 //激活对象并发送消息给对象已激活执行回调 68 go.SetActive(true); 69 //MessageDispatcher.SendMessage(go.name or go.tag); 70 71 return go; 72 } 73 74 /// <summary> 75 /// 从对象池中预先加载对象 76 /// </summary> 77 /// <param name="count">预先加载数量的数目</param> 78 public void Preload(int count) 79 { 80 GameObject[] gos = new GameObject[count]; 81 GameObject parent = new GameObject(obj.name); 82 // 创建预先加载的对象 83 for (int i = 0; i < count; i++) 84 { 85 gos[i] = Allocate(Vector3.zero, Quaternion.identity); 86 gos[i].transform.parent = parent.transform; 87 } 88 89 for (int i = 0; i < count; i++) 90 { 91 Release(gos[i]); 92 } 93 } 94 95 /// <summary> 96 /// 把对象回收到对象池中去 97 /// </summary> 98 /// <param name="obj"></param> 99 public void Release(GameObject obj) 100 { 101 if (!available.Contains(obj)) 102 { 103 available.Push(obj); 104 105 //禁用对象并发送消息给对象已禁用执行回调 106 //MessageDispatcher.SendMessage(go.name or go.tag); 107 obj.SetActive(false); 108 } 109 } 110 111 /// <summary> 112 /// 对象池回收所有的对象 113 /// </summary> 114 public void ReleaseAll() 115 { 116 for (int i = 0; i < all.Count; i++) 117 { 118 GameObject go = all[i]; 119 if (go != null && go.activeInHierarchy) 120 { 121 Release(go); 122 } 123 } 124 } 125 126 /// <summary> 127 /// 清理对象池 128 /// </summary> 129 public void Clear() 130 { 131 ReleaseAll(); 132 available.Clear(); 133 all.Clear(); 134 } 135 136 /// <summary> 137 /// 返回已激活的对象 138 /// </summary> 139 /// <returns></returns> 140 public int GetActiveCount() 141 { 142 return all.Count - available.Count; 143 } 144 145 /// <summary> 146 /// 返回可用对象的数目 147 /// </summary> 148 /// <returns></returns> 149 public int GetAvailableCount() 150 { 151 return available.Count; 152 } 153 154 /// <summary> 155 /// 返回对象池中的对象 156 /// </summary> 157 /// <returns></returns> 158 public GameObject GetObject() 159 { 160 return obj; 161 } 162 } 163 }
1 using System.Collections; 2 using System.Collections.Generic; 3 using TMoonObjectPool; 4 using UnityEngine; 5 6 namespace TMoonObjectPool 7 { 8 /// <summary> 9 /// 对象池管理类 10 /// </summary> 11 public class PoolManager 12 { 13 private static PoolManager instance = null; 14 public static PoolManager Instance 15 { 16 get 17 { 18 if (instance == null) 19 { 20 instance = new PoolManager(); 21 } 22 return instance; 23 } 24 } 25 26 private List<GameObjectPool> pools = null; 27 28 private PoolManager() { pools = new List<GameObjectPool>(); } 29 30 //创建一个对象池 31 public GameObjectPool Create(string name, GameObject obj) 32 { 33 GameObjectPool pool = new GameObjectPool(name, obj); 34 pools.Add(pool); 35 return pool; 36 } 37 38 //移除一个对象池 39 public void Remove(string name) 40 { 41 int index = pools.FindIndex((pool) => pool.name == name); 42 pools[index].Clear(); 43 pools.RemoveAt(index); 44 } 45 46 //移除所有的对象池 47 public void RemoveAll() 48 { 49 pools.Clear(); 50 } 51 52 /// <summary> 53 /// 得到一个对象池 54 /// </summary> 55 /// <param name="name">对象池的名字</param> 56 /// <returns></returns> 57 public GameObjectPool GetPool(string name) 58 { 59 return pools.Find((pool) => pool.name == name); 60 } 61 } 62 }
示例代码:
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using TMoonObjectPool; 5 using UnityEngine; 6 7 public class test : MonoBehaviour 8 { 9 public GameObject go; 10 private GameObjectPool pool; 11 void Start() 12 { 13 pool = PoolManager.Instance.Create("go", go); 14 pool.Preload(5); 15 } 16 17 void Update() 18 { 19 if (Input.GetMouseButtonDown(0)) 20 { 21 pool.Allocate(Vector3.zero,Quaternion.identity); 22 } 23 24 if (Input.GetKeyDown(KeyCode.R)) 25 { 26 pool.ReleaseAll(); 27 } 28 } 29 }
今天看了下Unity UGUI的源码,发现了一个对象池的工具类,觉得写得又简单又好,在下面直接贴代码上来了。
1 using System.Collections.Generic; 2 using UnityEngine.Events; 3 4 namespace UnityEngine.UI 5 { 6 internal class ObjectPool<T> where T : new() 7 { 8 private readonly Stack<T> m_Stack = new Stack<T>(); 9 private readonly UnityAction<T> m_ActionOnGet; 10 private readonly UnityAction<T> m_ActionOnRelease; 11 12 public int countAll { get; private set; } 13 public int countActive { get { return countAll - countInactive; } } 14 public int countInactive { get { return m_Stack.Count; } } 15 16 public ObjectPool(UnityAction<T> actionOnGet, UnityAction<T> actionOnRelease) 17 { 18 m_ActionOnGet = actionOnGet; 19 m_ActionOnRelease = actionOnRelease; 20 } 21 22 public T Get() 23 { 24 T element; 25 if (m_Stack.Count == 0) 26 { 27 element = new T(); 28 countAll++; 29 } 30 else 31 { 32 element = m_Stack.Pop(); 33 } 34 if (m_ActionOnGet != null) 35 m_ActionOnGet(element); 36 return element; 37 } 38 39 public void Release(T element) 40 { 41 if (m_Stack.Count > 0 && ReferenceEquals(m_Stack.Peek(), element)) 42 Debug.LogError("Internal error. Trying to destroy object that is already released to pool."); 43 if (m_ActionOnRelease != null) 44 m_ActionOnRelease(element); 45 m_Stack.Push(element); 46 } 47 } 48 }