(网页转载)Unity对象池的创建与使用
Chinar 教程效果:
1
MonoSingleton —— 单例基类
2
ObjectPool —— 对象池
3
PoolTest —— 测试对象池的使用
支持
May Be —— 搞开发,总有一天要做的事!
1
MonoSingleton —— 单例基类
using UnityEngine; /// <summary> /// 泛型单例基类 —— 任何继承自该类的类,都是单例类 /// </summary> /// <typeparam name="T">泛型</typeparam> public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T> { private static T instance; public static T Instance { get { if (instance == null) { instance = FindObjectOfType(typeof(T)) as T; if (instance == null) instance = new GameObject("Chinar Single of " + typeof(T).ToString(), typeof(T)).GetComponent<T>(); } return instance; } } private void Awake() { if (instance == null) instance = this as T; } private void OnApplicationQuit() { instance = null; } }
2
ObjectPool —— 对象池
新建一个脚本 ObjectPool 继承自泛型基类 MonoSingleton《ObjectPool》
是以 ObjectPool 就会是一个单例类
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 5 6 /// <summary> 7 /// 对象池(重复调用/使用的游戏物体) 子弹,技能,导弹,敌人 8 /// </summary> 9 public class ObjectPool : MonoSingleton<ObjectPool> 10 { 11 //字段 池 技能预设物(因为一个技能可能有多个预制件) 技能的复用性 12 private Dictionary<string, List<GameObject>> cache = new Dictionary<string, List<GameObject>>(); 13 int i = 0; //标记 0 14 15 16 /// <summary> 17 /// 创建显示对象 18 /// </summary> 19 /// <returns>The object.</returns> 20 /// <param name="key">对象名称</param> 21 /// <param name="go">对象的预制件</param> 22 /// <param name="position">对象的新位置</param> 23 /// <param name="quaternion">对象的角度</param> 24 public GameObject CreateObject(string key, GameObject go, Vector3 position, Quaternion quaternion) 25 { 26 GameObject tempgo = cache.ContainsKey(key) ? cache[key].Find(p => !p.activeSelf) : null; //返回池中未激活的对象,所有都被激活就返回空,赋值给临时对象 27 if (tempgo != null) //如果临时对象不为空 28 { 29 tempgo.transform.position = position; //设置位置 30 tempgo.transform.rotation = quaternion; //旋转信息 31 } 32 else //否则,就是空了。(也就是没能从池子里取出对象) 33 { 34 tempgo = Instantiate(go, position, quaternion); //那就根据传入的预设物,生成一个新物体 35 print("实例化物体数量:" + i++); 36 if (!cache.ContainsKey(key)) //池中没有键 37 { 38 cache.Add(key, new List<GameObject>()); //新建一个 列表 39 } 40 41 cache[key].Add(tempgo); //给字典中的列表加入/add 临时物体,如果有键就直接添加了 42 } 43 44 tempgo.SetActive(true); //并启用临时物体 45 return tempgo; //返回 46 } 47 48 49 /// <summary> 50 /// 直接回收 51 /// </summary> 52 /// <param name="go">Go.</param> 53 public void CollectObject(GameObject go) 54 { 55 go.SetActive(false); 56 } 57 58 59 /// <summary> 60 /// 延迟回收 61 /// </summary> 62 /// <param name="go">Go.</param> 63 /// <param name="delay">Delay.</param> 64 public void CollectObject(GameObject go, float delay) 65 { 66 StartCoroutine(Collect(go, delay)); 67 } 68 69 70 private IEnumerator Collect(GameObject go, float delay) 71 { 72 yield return new WaitForSeconds(delay); 73 CollectObject(go); 74 } 75 76 77 /// <summary> 78 /// 释放资源 79 /// </summary> 80 /// <returns>The clear.</returns> 81 /// <param name="key">Key.</param> 82 public void Clear(string key) 83 { 84 if (cache.ContainsKey(key)) 85 { 86 //Destroy当中所有的对象 87 for (int i = 0; i < cache[key].Count; i++) 88 { 89 Destroy(cache[key][i]); 90 } 91 92 //清除键当中的所有值 93 //cache[key].Clear(); 94 //清除这个键(键值一起清除) 95 cache.Remove(key); 96 } 97 } 98 99 100 /// <summary> 101 /// 释放所有对象池 102 /// </summary> 103 public void ClearAll() 104 { 105 var list = new List<string>(cache.Keys); 106 for (int i = 0; i < list.Count; i++) 107 { 108 Clear(list[i]); 109 } 110 } 111 }
3
PoolTest —— 测试对象池的使用
新建一个脚本 PoolTest 用来测试对象池的使用
1 using UnityEngine; 2 3 4 /// <summary> 5 /// 测试对象池的调用 6 /// </summary> 7 public class PoolTest : MonoBehaviour 8 { 9 GameObject go; //临时对象 10 GameObject item; //临时对象池对象 11 12 13 void Start() 14 { 15 go = Resources.Load<GameObject>("Cube"); //在Resources文件目录下做一个Cube预设物 16 } 17 18 19 void Update() 20 { 21 if (Input.GetKey(KeyCode.Space)) //按下空格创建一个Cube 22 { 23 item = ObjectPool.Instance.CreateObject("Object1", go, Vector3.zero, new Quaternion(0, 0, 0, 0)); 24 item.transform.position += new Vector3(0, 0, 1); 25 } 26 27 28 if (Input.GetMouseButtonDown(0)) //按下左键执行回收对象 29 { 30 if (item != null) 31 { 32 ObjectPool.Instance.CollectObject(item, 0.2f); 33 } 34 } 35 36 37 if (Input.GetMouseButtonDown(1)) //按下右键执行清除已经生成的对象 38 { 39 ObjectPool.Instance.Clear("Object1"); 40 } 41 } 42 }
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 后端思维之高并发处理方案
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· 后端思维之高并发处理方案
· 千万级大表的优化技巧
· 在 VS Code 中,一键安装 MCP Server!
· 想让你多爱自己一些的开源计时器
· 10年+ .NET Coder 心语 ── 继承的思维:从思维模式到架构设计的深度解析