Unity C# 对象池

  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 }
GameObjectPool
 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 }
PoolManager

示例代码:

 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 }
ObjectPool
原文地址:https://www.cnblogs.com/SeaSwallow/p/6550920.html