【转】Unity 对象池(Object Pooling)理解与简单应用
原文章:https://blog.csdn.net/l773575310/article/details/71601460
参考Unity官方教程 : Object Pooling
Unity官方教程: Space Shooter
Github项目(使用对象池):Space Shooter
Github项目(封装对象池):GentleTank
对象池用于减少内存开销,其原理就是把可能用到到的对象,先存在一个地方(池),要用的时候就调出来,不用就放回去。而不是要用的时候创建,不用的时候销毁。
举个例子:
我有个飞机,射击子弹,按传统的方法就是,创建子弹,子弹击中目标或出界等销毁子弹。就是不断的创建与销毁,要知道创建和销毁是要消耗许多内存以及时间的。如果把子弹存在一个地方(池),需要子弹时,就从里面拿出来,不需要的时候放回去。
如果还有多个飞机,可以公用一个子弹库。
这个方法虽然一直保持着存储子弹空间的一个最大值,但相比不断创建与销毁的代价,是非常值得考虑的。
而实际开发中,可以按照需要适当放大或缩小池大小。
关于线程池还有连接池其原理类似对象池,不做介绍。
对象池简单应用
拿上面说的飞机射子弹的例子,上代码。
子弹对象池类
using System.Collections.Generic;
using UnityEngine;public class BulletsPool : MonoBehaviour
{public static BulletsPool bulletsPoolInstance; //子弹池单例public GameObject bulletObj; //子弹perfabspublic int pooledAmount = 5; //子弹池初始大小public bool lockPoolSize = false; //是否锁定子弹池大小private List<GameObject> pooledObjects; //子弹池链表private int currentIndex = 0; //当前指向链表位置索引void Awake(){bulletsPoolInstance = this; //把本对象作为实例。}void Start(){pooledObjects = new List<GameObject>(); //初始化链表for (int i = 0; i < pooledAmount; ++i){GameObject obj = Instantiate(bulletObj); //创建子弹对象obj.SetActive(false); //设置子弹无效pooledObjects.Add(obj); //把子弹添加到链表(对象池)中}}public GameObject GetPooledObject() //获取对象池中可以使用的子弹。{for (int i = 0; i < pooledObjects.Count; ++i) //把对象池遍历一遍{//这里简单优化了一下,每一次遍历都是从上一次被使用的子弹的下一个,而不是每次遍历从0开始。//例如上一次获取了第4个子弹,currentIndex就为5,这里从索引5开始遍历,这是一种贪心算法。int temI = (currentIndex + i) % pooledObjects.Count;if (!pooledObjects[temI].activeInHierarchy) //判断该子弹是否在场景中激活。{currentIndex = (temI + 1) % pooledObjects.Count;return pooledObjects[temI]; //找到没有被激活的子弹并返回}}//如果遍历完一遍子弹库发现没有可以用的,执行下面if(!lockPoolSize) //如果没有锁定对象池大小,创建子弹并添加到对象池中。{GameObject obj = Instantiate(bulletObj);pooledObjects.Add(obj);return obj;}//如果遍历完没有而且锁定了对象池大小,返回空。return null;}}
自动发射子弹类
using UnityEngine;public class AutoFire : MonoBehaviour {//传统创建子弹方法需要的子弹perfabs//public GameObject shotObj;public GameObject shotSpawn; //子弹发射的初始化位置public float fireRate = 0.2f; //每次发射子弹事件间隔private float nextFire; //下一次发射子弹的时间void Update(){if (Time.time > nextFire) //可以发射子弹时间{nextFire = Time.time + fireRate;//传统创建子弹方法//Instantiate(shotObj, shotSpawn.transform.position, shotSpawn.transform.rotation);//获取对象池中的子弹GameObject bullet = BulletsPool.bulletsPoolInstance.GetPooledObject();if(bullet != null) //不为空时执行{bullet.SetActive(true); //激活子弹并初始化子弹的位置bullet.transform.position = shotSpawn.transform.position;}}} }
子弹失效,回收子弹类
判断是否出界,这个类是放在场景的一个长方体里,飞机子弹都在这长方体内,所以时刻都是与这个长方体碰撞中的,当子弹出界,及子弹碰撞结束。这是Unity官方教程(Space shooter)里有的。using UnityEngine;public class DestroyByBoundary : MonoBehaviour {void OnTriggerExit(Collider other){//Destroy(other.gameObject); //传统方法,直接删除子弹other.gameObject.SetActive(false); //对象池方法,把子弹失效就好了} }
刚开始,如图已经发了三发Bolt1,对象池中还有两发active是false的:
当稳定后,子弹池稳定在7发。
进阶
见 Github:GentleTank/Assets/GameControl/Object%20Pool/Scripts/ObjectPool.cs
将对象池封装成ScriptObject。
将对象池重新封装,做成一个ScriptObject,就可把对象池抽象出来,就可以应用于任何物体。
在上图右下角Project面板上创建一个对象池文件。
其面板如下。
注意:使用前需要调用CreateObjectPool(),来初始化创建对象池。
【转】Unity 对象池(Object Pooling)理解与简单应用相关推荐
- Unity对象池技术
Unity对象池技术 https://blog.csdn.net/LemonXQ/article/details/77148886 顾名思义,对象池是存放对象的缓冲区.用户可以从缓冲区中放入/取出对象 ...
- unity 对象池模式
1.理解 对象池用于减少内存开销,其原理就是把可能用到到的对象,先存在一个地方(池),要用的时候就调出来,不用就放回去.而不是要用的时候创建,不用的时候销毁. Eg: 我有个飞机,射击子弹,按传统的方 ...
- Unity对象池简单应用
1.简单介绍 在Unity开发过程中,对象池是一种很好的能用于减少内存开销的方式.在许多场景中,比如角色射击出去的子弹,以及在游戏运行过程中频繁生成的敌人-如果在运行时实时在场景中Instance和D ...
- unity对象池(学习)
对象池: 假设有一个射击游戏,那么场景中必然会创建许多的子弹.如果对于子弹只进行创建子弹-销毁子弹的流程(创建子弹-->销毁),那么可能在1S间创建很多很多的子弹,也会销毁很多子弹,对于游戏 ...
- Unity中的资源管理-对象池技术(3)
本文分享Unity中的资源管理-对象池技术(3) 在上两篇文章中, 我们一起学习了普通类的两种对象池实现, 今天接着介绍Unity中GameObject(主要是预制实例化对象)的对象池. GameOb ...
- Unity程序框架总结归置系列(2)——对象池
上一篇--Unity程序框架总结归置系列(1)--单例基类 该说的,上一篇也说了.话不多说,直接开肝. unity对象池模块 先直接上源码: using System.Collections.Gene ...
- 池式结构:对象池(Object Pool)
本文是对 http://gameprogrammingpatterns.com/object-pool.html 的原创翻译.部分地方使用意译,不准确的地方请各位指证. 一.对象池的意义 通过重新使用 ...
- Unity3D 内存优化(一)对象池
一.定义: 关于U3D内存优化,一直是游戏开发者头疼的事情,由于在项目中我们会频繁地创建和销毁一些对象,例如:怪物模型或者是UI预设体,但是,部分对象在游戏中是会频繁出现的,例如战斗中的小怪物,假如每 ...
- Unity3D 对象池 静态预制件与动态单体
Unity3D 对象池 静态预制件与动态单体 效果 整体思路 静态预制件对象池 对象池接口 对象池接口继承类 动态单体对象池 游戏里为了利用内存资源一般对象池是用的比较多 这里总结了两版对象池. 请结 ...
- Unity中对象池的使用
unity中用到大量重复的物体,例如发射的子弹,可以引入对象池来管理,优化内存. 对象池使用的基本思路是: 将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用.恰当地使用对象池,可以在 ...
最新文章
- InputStreamReader/OutputStreamWriter乱码问题解决
- IE9(测试版)浏览器实用快捷键使用方法
- angular ngClick 阻止冒泡和默认行为
- 信息学复赛用linux,NOIP/CSPJ 复赛中noilinux里的atbiter测评机的使用(附数据)
- jstl:sql标签介绍
- nedata实时监控服务器运行情况
- mysql bundle.tar_MySQL 5.6 Bundle Tar安装
- java线程内存模型_深度解析Java多线程的内存模型
- CSS3 Flexbox轻松实现元素的水平居中和垂直居中
- [招聘]期待您的加盟,与博客园一起成长
- openjudge 7622 求排列的逆序数(归并)
- 三坐标最小二乘法原理_【最小二乘法 | 高斯法】来认识一下传说中的最小二乘法...
- nali for win golang版, 显示ip 的小工具
- Docker 构建统一的前端开发环境
- 校园招聘-2017携程秋招后台开发笔试编程题
- 如何关闭任务栏中chrome浏览器的通知图标
- 中国科学院大学毕业典礼致辞全文
- Crunching Cruncher send_music_thumb_backup.png failed, see logs
- 使用赫夫曼编码进行解码
- mysql useing查询_MySQL查询优化一例——也说说 Using intersect