原文章: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)理解与简单应用相关推荐

  1. Unity对象池技术

    Unity对象池技术 https://blog.csdn.net/LemonXQ/article/details/77148886 顾名思义,对象池是存放对象的缓冲区.用户可以从缓冲区中放入/取出对象 ...

  2. unity 对象池模式

    1.理解 对象池用于减少内存开销,其原理就是把可能用到到的对象,先存在一个地方(池),要用的时候就调出来,不用就放回去.而不是要用的时候创建,不用的时候销毁. Eg: 我有个飞机,射击子弹,按传统的方 ...

  3. Unity对象池简单应用

    1.简单介绍 在Unity开发过程中,对象池是一种很好的能用于减少内存开销的方式.在许多场景中,比如角色射击出去的子弹,以及在游戏运行过程中频繁生成的敌人-如果在运行时实时在场景中Instance和D ...

  4. unity对象池(学习)

    对象池:   假设有一个射击游戏,那么场景中必然会创建许多的子弹.如果对于子弹只进行创建子弹-销毁子弹的流程(创建子弹-->销毁),那么可能在1S间创建很多很多的子弹,也会销毁很多子弹,对于游戏 ...

  5. Unity中的资源管理-对象池技术(3)

    本文分享Unity中的资源管理-对象池技术(3) 在上两篇文章中, 我们一起学习了普通类的两种对象池实现, 今天接着介绍Unity中GameObject(主要是预制实例化对象)的对象池. GameOb ...

  6. Unity程序框架总结归置系列(2)——对象池

    上一篇--Unity程序框架总结归置系列(1)--单例基类 该说的,上一篇也说了.话不多说,直接开肝. unity对象池模块 先直接上源码: using System.Collections.Gene ...

  7. 池式结构:对象池(Object Pool)

    本文是对 http://gameprogrammingpatterns.com/object-pool.html 的原创翻译.部分地方使用意译,不准确的地方请各位指证. 一.对象池的意义 通过重新使用 ...

  8. Unity3D 内存优化(一)对象池

    一.定义: 关于U3D内存优化,一直是游戏开发者头疼的事情,由于在项目中我们会频繁地创建和销毁一些对象,例如:怪物模型或者是UI预设体,但是,部分对象在游戏中是会频繁出现的,例如战斗中的小怪物,假如每 ...

  9. Unity3D 对象池 静态预制件与动态单体

    Unity3D 对象池 静态预制件与动态单体 效果 整体思路 静态预制件对象池 对象池接口 对象池接口继承类 动态单体对象池 游戏里为了利用内存资源一般对象池是用的比较多 这里总结了两版对象池. 请结 ...

  10. Unity中对象池的使用

    unity中用到大量重复的物体,例如发射的子弹,可以引入对象池来管理,优化内存. 对象池使用的基本思路是: 将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用.恰当地使用对象池,可以在 ...

最新文章

  1. InputStreamReader/OutputStreamWriter乱码问题解决
  2. IE9(测试版)浏览器实用快捷键使用方法
  3. angular ngClick 阻止冒泡和默认行为
  4. 信息学复赛用linux,NOIP/CSPJ 复赛中noilinux里的atbiter测评机的使用(附数据)
  5. jstl:sql标签介绍
  6. nedata实时监控服务器运行情况
  7. mysql bundle.tar_MySQL 5.6 Bundle Tar安装
  8. java线程内存模型_深度解析Java多线程的内存模型
  9. CSS3 Flexbox轻松实现元素的水平居中和垂直居中
  10. [招聘]期待您的加盟,与博客园一起成长
  11. openjudge 7622 求排列的逆序数(归并)
  12. 三坐标最小二乘法原理_【最小二乘法 | 高斯法】来认识一下传说中的最小二乘法...
  13. nali for win golang版, 显示ip 的小工具
  14. Docker 构建统一的前端开发环境
  15. 校园招聘-2017携程秋招后台开发笔试编程题
  16. 如何关闭任务栏中chrome浏览器的通知图标
  17. 中国科学院大学毕业典礼致辞全文
  18. Crunching Cruncher send_music_thumb_backup.png failed, see logs
  19. 使用赫夫曼编码进行解码
  20. mysql useing查询_MySQL查询优化一例——也说说 Using intersect

热门文章

  1. 企业数据架构和集成架构规划方案(PPT)
  2. 聚类算法---Kmeans算法、K均值算法
  3. 高中开计算机课吗,高中信息技术课的开设意义和课程实施方法
  4. 西门子G120变频器初始化参数设置
  5. 2021.05.26【R语言】丨clusterProfiler注释大肠杆菌GO/KEGG富集图
  6. PLC和变频器通讯方式
  7. 动作捕捉用于索并联机构中的理论验证
  8. PREEvision软件-汽车电子电气架构的开发工具
  9. 动作捕捉助力无人车多源传感器信息融合导航技术
  10. Mac fliqlo 时钟屏保