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

你都学会栈和队列了赶紧手搓一个对象池吧!!!(超详细,超简单适合新手宝宝学习)

前置知识:en造数据结构与算法C# 用数组实现个栈还不简单???看我一秒破之!!!(unity演示)-CSDN博客

c#有官方造好的关于stack的轮子,建议学习学习拿来直接用 

本节实现目标:(注意右侧的Cube数量没有增加而是循环激活和失活)

1.对象池详解

        对象池是一种优化游戏性能的技术,特别适用于需要频繁创建和销毁对象的场景,比如子弹、敌人、特效等。在Unity中,对象池可以显著减少内存分配和垃圾回收的开销,从而提高游戏的运行效率

 流程图解:对象池的基本原理无非就三个步骤:创建指定数量的物体,调用物体(激活%拿出),释放物体(失活&放回),之后就是激活&拿出和失活&放回之间的循环

内存图解:因为对象池就像是一个定长数组一样,所以内存是一连串而非碎片化的

对象状态图解:传统创造和销毁物体后,需要新的物体就要再创建

对象池是把需要销毁的物体重新放回池子里

2.代码详解 

之所以全部拿过来了,是因为我注释写的巨详细,直接看下去会很连贯

using System.Collections.Generic;
using UnityEngine;public class MyPool {//stack作为对象池容器private Stack<GameObject> pool;//玩家可能需要调用的预制体private GameObject prefab;//像对象池创建预制体prefab和指定的数量initialCapacitypublic MyPool(GameObject prefab, int initialCapacity) {this.prefab = prefab;//实例化容器对象pool = new Stack<GameObject>(initialCapacity);for (int i = 0; i < initialCapacity; i++) {//存储实例化物体GameObject obj = GameObject.Instantiate(prefab);//失活obj.SetActive(false);//压栈pool.Push(obj);}}//玩家调用物体public GameObject Get() {//保险判断,如果对象池中有可用对象就弹栈返回出该对象if (pool.Count > 0) {return pool.Pop();}//如果没有的话,就创建并失活并返回else {GameObject obj = GameObject.Instantiate(prefab);obj.SetActive(false);//这里可以改成ture//至于为什么不压栈了,因为直接创建直接返回出去就得了,再压栈就还需要再弹栈,代码就重复了// pool.Push(obj); 如果有这行//return pool.Pop(); 那么得有这行return obj;}}//释放物体public void Release(GameObject obj) {//失活obj.SetActive(false);pool.Push(obj);}
}

3.使用示例

using System.Collections;
using UnityEngine;public class UsePool : MonoBehaviour {//我用来演示的方块预制体public GameObject cubePrefab;//对象池对象private MyPool myPool;void Start() {//向对象池放东西myPool = new MyPool(cubePrefab, 10);}void Update() {//通过旧输入系统,按下空格就使用对象池的调用物体方法if (Input.GetKeyDown(KeyCode.Space)) {GameObject obj = myPool.Get();obj.transform.position = Random.insideUnitSphere * 5; // 随机位置obj.SetActive(true);//如果你的get方法里面obj.SetActive(false);改成ture了,就不需要这行代码了StartCoroutine(AutoRelease(obj, 2f)); // 启动协程,2秒后自动释放}}private IEnumerator AutoRelease(GameObject obj, float delay) {//注意是先等两秒再释放,第一次调用直接释放会出现空引用或者其他有意思的情况,你可以复制下来自己试试yield return new WaitForSeconds(delay);myPool.Release(obj);}
}

 4.一个小细节(重要)

在第二个大标题,也就是MyPool代码中的Get方法中,有一处可以改成ture

那么我为什么还要在UsePool类中添加这行

 是因为,你传进来的是一个预制体,难免预制体上会挂在脚本,或者像我一样在UsePool类中的Update里面写一些逻辑

如果你在Get中激活了,那么我的逻辑赶不上你激活的速度,就会发生意想不到事情

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 跨系统环境下LabVIEW程序稳定运行
  • CSP-J 之C++常用英文缩写
  • minio的下载和springboot整合minio使用
  • Docker容器技术1——docker基本操作
  • 线性代数 第七讲 二次型_标准型_规范型_坐标变换_合同_正定二次型详细讲解_重难点题型总结
  • 天童教育:课外阅读图书推荐
  • C++20 新特征:概念(Concepts)全面解析
  • Qt实现登录界面
  • Spark的介绍
  • 【高中数学/基本不等式】已知ab皆为正实数,且(a+5b)*(2a+b)=36,求a+2b之最小值?
  • Unet改进30:添加CAA(2024最新改进方法)|上下文锚定注意模块来捕获远程上下文信息。
  • USB摄像头视频流转RTSP流
  • Python | Leetcode Python题解之第401题二进制手表
  • Python世界:基于PESQ的自动化语音打分脚本实践
  • 2024全球数字电影摄像机、相机、广播摄像机市场报告
  • 实现windows 窗体的自己画,网上摘抄的,学习了
  • C++类的相互关联
  • CentOS 7 修改主机名
  • HTTP中的ETag在移动客户端的应用
  • JAVA_NIO系列——Channel和Buffer详解
  • js正则,这点儿就够用了
  • js作用域和this的理解
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • Python3爬取英雄联盟英雄皮肤大图
  • SpringBoot 实战 (三) | 配置文件详解
  • win10下安装mysql5.7
  • 番外篇1:在Windows环境下安装JDK
  • 简单易用的leetcode开发测试工具(npm)
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 云栖大讲堂Java基础入门(三)- 阿里巴巴Java开发手册介绍
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • ​补​充​经​纬​恒​润​一​面​
  • ​如何防止网络攻击?
  • #### go map 底层结构 ####
  • #Js篇:单线程模式同步任务异步任务任务队列事件循环setTimeout() setInterval()
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (32位汇编 五)mov/add/sub/and/or/xor/not
  • (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作...
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • (一)认识微服务
  • (转)shell调试方法
  • ******之网络***——物理***
  • ***linux下安装xampp,XAMPP目录结构(阿里云安装xampp)
  • **PHP分步表单提交思路(分页表单提交)
  • .form文件_SSM框架文件上传篇
  • .NET Core引入性能分析引导优化
  • .NET/C# 项目如何优雅地设置条件编译符号?
  • .skip() 和 .only() 的使用
  • /var/log/cvslog 太大
  • @Bean有哪些属性
  • @CacheInvalidate(name = “xxx“, key = “#results.![a+b]“,multi = true)是什么意思