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);}
}
其他类型的对象池

相关文章:
Unity 对象池技术
介绍 是什么? 在开始时初始化若干对象,将它们存到对象池中。需要使用的时候从对象池中取出,使用完后重新放回对象池中。 优点 可以避免频繁创建和销毁对象带来性能消耗。 适用场景 如果需要对某种对象进行频繁创建和销毁时,例…...
算法1-4 凌乱的yyy / 线段覆盖
题目描述 现在各大 oj 上有 n 个比赛,每个比赛的开始、结束的时间点是知道的。 yyy 认为,参加越多的比赛,noip 就能考的越好(假的)。 所以,他想知道他最多能参加几个比赛。 由于 yyy 是蒟蒻,…...
【计网】数据链路层
数据链路层 3.1 数据链路层概述3.2 封装成帧3.3 差错检测3.4 可靠传输3.4.1 可靠传输的概念3.4.2 可靠传输的实现机制 - 停止等待协议3.4.3 可靠传输的实现机制 -回退N帧协议3.4.4 可靠传输的实现机制 -选择重传协议 3.5 点对点协议3.5.1 帧格式3.5.2 透明传输 3.6 媒体接入控制…...
javaweb自用笔记:Vue
Vue 什么是vue vue案例 1、引入vue.js文件 2、定义vue对象 3、定义vue接管的区域el 4、定义数据模型data 5、定义视图div 6、通过标签v-model来绑定数据模型 7、{{message}}直接将数据模型message展示出来 8、由于vue的双向数据绑定,当视图层标签input里的…...
CSS Overflow 属性详解
CSS Overflow 属性详解 在网页设计和开发中,CSS Overflow 属性是一个非常重要的特性,它决定了当内容超出其容器大小时应该如何处理。本文将详细介绍 CSS Overflow 属性的相关知识,包括其语法、作用、常用属性值以及一些实际应用场景。 1. CSS Overflow 属性概述 CSS Over…...
沃丰科技结合DeepSeek大模型技术落地与应用前后效果对比
技术突破:DeepSeek算法创新,显著降低了显存占用和推理成本。仅需少量标注数据即可提升推理能力。这种突破减少了对海量数据的依赖,削弱了数据垄断企业的优势! 商业模式颠覆:DeepSeek选择完全开源模式,迫使…...
突破光学成像局限:全视野光学血管造影技术新进展
全视野光学血管造影(FFOA)作为一种实时、无创的成像技术,能够提取生物血液微循环信息,为深入探究生物组织的功能和病理变化提供关键数据。然而,传统FFOA成像方法受到光学镜头景深(DOF)的限制&am…...
2.反向传播机制简述——大模型开发深度学习理论基础
在深度学习开发中,反向传播机制是训练神经网络不可或缺的一部分。它让模型能够通过不断调整权重,从而将预测误差最小化。本文将从实际开发角度出发,简要介绍反向传播机制的核心概念、基本流程、在现代网络中的扩展,以及如何利用自…...
机器学习校招面经二
快手 机器学习算法 一、AUC(Area Under the ROC Curve)怎么计算?AUC接近1可能的原因是什么? 见【搜广推校招面经四】 AUC 是评估分类模型性能的重要指标,用于衡量模型在不同阈值下区分正负样本的能力。它是 ROC 曲线…...
Spring Boot如何利用Twilio Verify 发送验证码短信?
Twilio提供了一个名为 Twilio Verify 的服务,专门用于处理验证码的发送和验证。这是一个更为简化和安全的解决方案,适合需要用户身份验证的应用。 使用Twilio Verify服务的步骤 以下是如何在Spring Boot中集成Twilio Verify服务的步骤: 1.…...
毕业项目推荐:基于yolov8/yolo11的苹果叶片病害检测识别系统(python+卷积神经网络)
文章目录 概要一、整体资源介绍技术要点功能展示:功能1 支持单张图片识别功能2 支持遍历文件夹识别功能3 支持识别视频文件功能4 支持摄像头识别功能5 支持结果文件导出(xls格式)功能6 支持切换检测到的目标查看 二、数据集三、算法介绍1. YO…...
Linux的用户与权限--第二天
认知root用户(超级管理员) root用户用于最大的系统操作权限 普通用户的权限,一般在HOME目录内部不受限制 su与exit命令 su命令: su [-] 用户名 -符号是可选的,表示切换用户后加载环境变量 参数为用户名,…...
【Flink银行反欺诈系统设计方案】1.短时间内多次大额交易场景的flink与cep的实现
【flink应用系列】1.Flink银行反欺诈系统设计方案 1. 经典案例:短时间内多次大额交易1.1 场景描述1.2 风险判定逻辑 2. 使用Flink实现2.1 实现思路2.2 代码实现2.3 使用Flink流处理 3. 使用Flink CEP实现3.1 实现思路3.2 代码实现 4. 总结 1. 经典案例:短…...
HashMap的table数组何时初始化?默认容量和扩容阈值是多少?
HashMap 的 table 数组何时初始化? 答案: table 数组在第一次调用 put() 方法时初始化。 为什么? HashMap 为了节省内存,采用了“懒加载”机制。即使用 new HashMap() 创建对象时,只是计算了参数(如容量、…...
基于CURL命令封装的JAVA通用HTTP工具
文章目录 一、简要概述二、封装过程1. 引入依赖2. 定义脚本执行类 三、单元测试四、其他资源 一、简要概述 在Linux中curl是一个利用URL规则在命令行下工作的文件传输工具,可以说是一款很强大的http命令行工具。它支持文件的上传和下载,是综合传输工具&…...
docker学习笔记(1)从安装docker到使用Portainer部署容器
docker学习笔记第一课 先交代背景 docker宿主机系统:阿里云ubuntu22.04 开发机系统:win11 docker镜像仓库:阿里云,此阿里云与宿主机系统没有关系,是阿里云提供的一个免费的docker仓库 代码托管平台:github&…...
数据集/API 笔记:新加坡PSI(空气污染指数)API
data.gov.sg 数据范围:2016年2月 - 2025年3月 1 获取API方式 curl --request GET \--url https://api-open.data.gov.sg/v2/real-time/api/psi 2 返回数据 API 的数据结构可以分为 3 大部分: 区域元数据(regionMetadata) →…...
计算机网络数据传输探秘:包裹如何在数字世界旅行?
计算机网络数据传输探秘:包裹如何在数字世界旅行? 一、从快递网络看数据传输本质 想象你网购了一件商品: 打包:商家用纸箱包装,贴上地址标签(数据封装)运输:包裹经过网点→分拣中心→运输车(网络节点与链路)签收:快递员核对信息后交付(数据校验与接收)数据的网络…...
笔记:代码随想录算法训练营day36:LeetCode1049. 最后一块石头的重量 II、494. 目标和、474.一和零
学习资料:代码随想录 1049.最后一块石头的重量II 力扣题目链接 思路:如何讲该问题转化为背包问题:还是对半分去碰,对半分去碰碰剩下的就是最小的。然后背包容量就是一半儿,物品重量等于物品价值等于stones[i] 和上…...
Bitmap -> Bitmap安卓设备上的显示和内存
Android 屏幕显示与 Bitmap 内存详解 前言 在 Android 开发中,理解屏幕显示单位和 Bitmap 内存占用是构建高效应用的基础。本文将详细介绍相关概念、计算公式及单位转换,并通过实例分析 Bitmap 在内存中的表现。 一、屏幕显示单位基础 1.1 基本单位及…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释
以Module Federation 插件详为例,Webpack.config.js它可能的配置和含义如下: 前言 Module Federation 的Webpack.config.js核心配置包括: name filename(定义应用标识) remotes(引用远程模块࿰…...
【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...
