当前位置: 首页 > news >正文

Unity 对象池技术

介绍

是什么?

在开始时初始化若干对象,将它们存到对象池中。需要使用的时候从对象池中取出,使用完后重新放回对象池中。

优点

可以避免频繁创建和销毁对象带来性能消耗。

适用场景

如果需要对某种对象进行频繁创建和销毁时,例如应用在发射子弹、多个敌人创建等

代码逻辑

Unity中实现思路

1、设定初始化数量,创建List列表作为对象池容器。

2、初始化时通过Instantiate方法根据指定数量实例化一批对象,并存入List容器中。

3、使用时从容器中取出一个可用对象并SetActive(true),取出后从容器中移除。

4、使用完毕后,将对象SetActive(false),并重新放回List容器中。

主要方法

//初始化对象池
private void InitPool()
{}//创建单个对象池中的对象
private GameObject CreatePoolCell()
{}//从对象池中取出可用对象
private GameObject GetObjectFromPool()
{}//将对象放回对象池中
private void BackObjectToPool(GameObject obj)
{}//删除对象池
private void DestroyObjectPool()
{}

示例代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Test : MonoBehaviour
{public GameObject template;public Transform parentRoot;public Transform newRoot;private List<GameObject> objectPool;private int initCount;//对象池初始化的数量void Start(){InitPool();}void Update(){if (Input.GetKeyDown(KeyCode.Space)){var obj = GetObjectFromPool();ResetLocalPos(obj, newRoot);StartCoroutine(Check1(obj));}}IEnumerator Check1(GameObject obj){yield return new WaitForSeconds(5f);BackObjectToPool(obj);}#region 对象池逻辑//初始化对象池private void InitPool(){initCount = 10;objectPool = new List<GameObject>();for (var i = 0; i < initCount; i++){var obj = CreatePoolCell();objectPool.Add(obj);}}//创建单个对象池中的对象private GameObject CreatePoolCell(){var obj = Instantiate(template, parentRoot);obj.SetActive(false);obj.transform.localPosition = Vector3.zero;return obj;}//从对象池中取出可用对象private GameObject GetObjectFromPool(){for (var i = 0; i < objectPool.Count; i++){var obj = objectPool[i];if (!obj.activeInHierarchy){obj.SetActive(true);objectPool.Remove(obj);return obj;}}var newObj = CreatePoolCell();newObj.SetActive(true);return newObj;}//将对象放回对象池中private void BackObjectToPool(GameObject obj){if (objectPool.Contains(obj)){return;}obj.SetActive(false);ResetLocalPos(obj, parentRoot);objectPool.Add(obj);}//删除对象池private void DestroyObjectPool(){foreach (var iconObj in objectPool){DestroyImmediate(iconObj);}objectPool.Clear();}private void ResetLocalPos(GameObject obj,Transform parent){var trans = obj.transform;trans.SetParent(parent);trans.localPosition = Vector3.zero;}#endregion
}

Unity自带对象池

构造函数

//将会在创建新对象的时侯调用
Func<T> createFunc,    //会在从池子获取对象的时侯调用
Action<T> actionOnGet = null,  //将对象放回池子里的时侯调用
Action<T> actionOnRelease = null,  //会在彻底销毁对象的时侯调用
Action<T> actionOnDestroy = null,  //安全检查,防止将已经回收过的对象进行再一次的重复回收,默认参数的true即可
bool collectionCheck = true,    //池子初始的默认大小,会在初始化时创建一个该容量大小的 stack
//需要根据自己项目的实际需求去权衡一下初始容量的大小。
int defaultCapacity = 10,//主要是防止对象池内存过量增长,限定的对象池内最大可容纳的对象数量,
//如果池子超出了这个大小,接下来的回收对象将不会回到对象池
//而是直接调用它的 actionOnDestroy 回调进行销毁操作。
int maxSize = 10000)

主要属性和方法

接口

类型

描述

CountActive

属性

正在使用(即被激活的)的对象数量

CountInactive

属性

可以重用的对象数量

CountAll

属性

正在使用的对象和可以重用的对象的总数量

Get

方法

从对象池中获取对象

Release

方法

将对象放回池子中

Clear

方法

清理对象池

示例代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Pool;public class Test : MonoBehaviour
{public GameObject template;public Transform parentRoot;public Transform newRoot;private List<GameObject> objectPool;private int initCount;//对象池初始化的数量private ObjectPool<GameObject> testPool;public bool useObjectPool;void Start(){testPool = new ObjectPool<GameObject>(() =>{//createFunc//将会在创建新对象的时侯调用var obj = Instantiate(template, parentRoot);obj.SetActive(false);obj.transform.localPosition = Vector3.zero;return obj;},(go) =>{// actionOnGet // 会在通过池子获取对象的时侯调用,go.SetActive(true);var trans = go.transform;trans.SetParent(newRoot);trans.localPosition = Random.insideUnitSphere;},(go) =>{// actionOnRelease// 在对象放回池子里的时侯调用,这里我们取消激活需要放回池中的对象go.SetActive(false);var trans = go.transform;trans.SetParent(parentRoot);trans.localPosition = Vector3.zero;},(go) =>{/* actionOnDestroy 会在彻底销毁对象的时侯调用这里直接去destroy它就可以了对象池会在你手动释放对象或者内部空间无法存储你返回的对象的时侯调用这个函数来销毁它们*/Destroy(go); });}void Update(){if (Input.GetKeyDown(KeyCode.Space)){var obj = testPool.Get();StartCoroutine(Check1(obj));}}IEnumerator Check1(GameObject obj){yield return new WaitForSeconds(5f);testPool.Release(obj);}
}

其他类型的对象池

http://www.lryc.cn/news/546745.html

相关文章:

  • 算法1-4 凌乱的yyy / 线段覆盖
  • 【计网】数据链路层
  • javaweb自用笔记:Vue
  • CSS Overflow 属性详解
  • 沃丰科技结合DeepSeek大模型技术落地与应用前后效果对比
  • 突破光学成像局限:全视野光学血管造影技术新进展
  • 2.反向传播机制简述——大模型开发深度学习理论基础
  • 机器学习校招面经二
  • Spring Boot如何利用Twilio Verify 发送验证码短信?
  • 毕业项目推荐:基于yolov8/yolo11的苹果叶片病害检测识别系统(python+卷积神经网络)
  • Linux的用户与权限--第二天
  • 【Flink银行反欺诈系统设计方案】1.短时间内多次大额交易场景的flink与cep的实现
  • HashMap的table数组何时初始化?默认容量和扩容阈值是多少?
  • 基于CURL命令封装的JAVA通用HTTP工具
  • docker学习笔记(1)从安装docker到使用Portainer部署容器
  • 数据集/API 笔记:新加坡PSI(空气污染指数)API
  • 计算机网络数据传输探秘:包裹如何在数字世界旅行?
  • 笔记:代码随想录算法训练营day36:LeetCode1049. 最后一块石头的重量 II、494. 目标和、474.一和零
  • Bitmap -> Bitmap安卓设备上的显示和内存
  • QT study DAY2
  • QT-自定义参数设计框架软件
  • VUE集成Live2d
  • 【CPP面经】科大讯飞 腾讯后端开发面经分享
  • el-card 结合 el-descriptions 作为信息展示
  • GaussDB自带诊断工具实战指南
  • LeetCode 链表章节
  • SSL证书和HTTPS:全面解析它们的功能与重要性
  • 正交投影与内积空间:机器学习的几何基础
  • Qt中txt文件输出为PDF格式
  • 《HelloGitHub》第 107 期