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

unity对象缓存技术ObjectPool

首先先看下通过ObjectPool实现的一个小的效果,效果如下

“”

通过视频我们可以在Hierarchy窗口看到Sphere对象列表,出现,隐藏然后又active,然后又隐藏。
具体实现逻辑如下

step1 创建子弹预制体并绑定脚本。

子弹的预制体比较简单这里就不列举了,脚本我们呢取名字为BulletController,脚本处理如下:

 public class BulletController : MonoBehaviour
{public float speed;public float exitTime;public float radiam;public float timer;public void ResetTime(){timer = 0f;}void Update(){timer += Time.deltaTime;if (timer > exitTime){PlayerController.bulletPool.Release(gameObject);// Destroy(gameObject);}transform.position += new Vector3(speed * Time.deltaTime * Mathf.Sign(radiam+ timer*5),speed * Time.deltaTime * Mathf.Cos(radiam + timer * 5), 0);}
}

基本逻辑实现就是在update里面做时间累加,累加到一定时间就销毁物体,但是3D物体的创建销毁会造成UI的堵塞,因此我们这边使用对象池调用对象池的Release方法回收物体。ResetTime作用是重置物体状态。

step2 创建子弹发射器并通过对象池实现子弹的发射收集过程

//创建对象池并添加回调  
//defaultCapacity默认开辟对象数量(unity会给我们在内存开辟空间但并不会实例化对象)
// maxSize 对象池最大容量ulletPool = new ObjectPool<GameObject>(CreateFunc, ActionOnGet, ActionOnRelease, ActionOnDestroy, true, defaultCapacity: 10, maxSize:20);//创建物体回调 在这个回调中当对象池内容不够时会被回调private GameObject CreateFunc(){return  Instantiate(bulletPrefab, _MTransform.position, Quaternion.identity);}//当使用物体时调用 这里我们的处理是让物体显示private void ActionOnGet(GameObject @object){@object.SetActive(true);}
//当物体回收的时候调用这块处理是让物体隐藏
private void ActionOnRelease(GameObject @object)
{@object.SetActive(false);
}//当要创建的物体超过对象池容量的时候//然后对象池需要回收掉需要的对象多余创建的对象会调用这个回调通知销毁private void ActionOnDestroy(GameObject @object){Destroy( @object );}

通过上面的处理我们理解了对象池各个回调的作用以及调用时机,下面我们看下调用逻辑

step3 调用对象池处理

这块处理也是很简单的

btn.onClick.AddListener(() => {int d = 2;float d_angle = 360 / d;float radium = 360 / d * Mathf.PI / 180;for (int i = 0; i < d; i++){GameObject g = bulletPool.Get();BulletController bullet = g.GetComponent<BulletController>();bullet.transform.position = _MTransform.position;bullet.transform.rotation = Quaternion.identity;bullet.radiam = radium * i;bullet.ResetTime();}
});

这块处理也是很简单for循环创建物体,当然我们不是实例化预制体也不是new Object而是通过**bulletPool.Get()**这个方法取到对象,并给对象的脚本赋默认值。

step4总结
最后我们总结一下ObjectPool使用
1,.首先创建对象,并完成各个回调处理
2.然后在需要获取物体的地方使用 ObjectPool.Get() 获取物体
3.然后当物体需要销毁的时候通过 ObjectPool.Release(gameObject) 回收物体(ObjectPool会根据设置的阈值判定是回收物体还是销毁物体)

最后把PlayerController的源码放在这里

public class PlayerController : MonoBehaviour
{[SerializeField]private float speed;[SerializeField]private GameObject bulletPrefab;[SerializeField]private Button btn;private Transform _MTransform;public static ObjectPool<GameObject> bulletPool;void Start(){_MTransform = transform;bulletPool = new ObjectPool<GameObject>(CreateFunc, ActionOnGet, ActionOnRelease, ActionOnDestroy, true,defaultCapacity: 10, maxSize:20);btn.onClick.AddListener(() => {int d = 2;float d_angle = 360 / d;float radium = 360 / d * Mathf.PI / 180;for (int i = 0; i < d; i++){/* GameObject g = Instantiate(bulletPrefab, _MTransform.position, Quaternion.identity);BulletController bullet = g.GetComponent<BulletController>();*/GameObject g = bulletPool.Get();BulletController bullet = g.GetComponent<BulletController>();bullet.transform.position = _MTransform.position;bullet.transform.rotation = Quaternion.identity;bullet.radiam = radium * i;bullet.ResetTime();}});}private GameObject CreateFunc(){GameObject g = Instantiate(bulletPrefab, _MTransform.position, Quaternion.identity);BulletController bullet = g.GetComponent<BulletController>();Debug.Log("CreateFunc  " + bulletPool.CountInactive);return g;}private void ActionOnGet(GameObject @object){@object.SetActive(true);Debug.Log("ActionOnGet  " + bulletPool.CountInactive);}private void ActionOnRelease(GameObject @object){@object.SetActive(false);Debug.Log("ActionOnRelease  " + bulletPool.CountInactive);}private void ActionOnDestroy(GameObject @object){Destroy( @object );Debug.Log("ActionOnDestroy  " + bulletPool.CountInactive);}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【算法】KMP算法
  • 硬盘分区读不出来:原因深度剖析与高效恢复实践
  • 通用分页处理:从繁琐到简洁的转变
  • PYTHON专题-(7)python都有包了?
  • 【王道数据结构-第二章-线性表算法题】
  • 50etf期权行权采用什么交割方式 ?
  • Python爬虫与MySQL完美结合:从环境搭建到实战优化
  • Linux——文件(1)
  • SQL注入实例(sqli-labs/less-9)
  • Ubuntu22.04安装Docker教程
  • 微信开放平台更换服务器证书通知
  • Tomcat 漏洞
  • 基于飞腾E2000的科东软件Intewell工业实时操作系统方案
  • 音质提升秘籍:专业音频剪辑软件汇总
  • 【蘑菇书EasyRL】强化学习,笔记整理
  • (十五)java多线程之并发集合ArrayBlockingQueue
  • 2019.2.20 c++ 知识梳理
  • 5、React组件事件详解
  • flutter的key在widget list的作用以及必要性
  • Java方法详解
  • Spark学习笔记之相关记录
  • SpiderData 2019年2月23日 DApp数据排行榜
  • 产品三维模型在线预览
  • 高度不固定时垂直居中
  • 利用阿里云 OSS 搭建私有 Docker 仓库
  • 巧用 TypeScript (一)
  • 使用docker-compose进行多节点部署
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • #etcd#安装时出错
  • #pragma multi_compile #pragma shader_feature
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • (二)学习JVM —— 垃圾回收机制
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (四)图像的%2线性拉伸
  • (算法二)滑动窗口
  • **PyTorch月学习计划 - 第一周;第6-7天: 自动梯度(Autograd)**
  • *1 计算机基础和操作系统基础及几大协议
  • *2 echo、printf、mkdir命令的应用
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .NET Core中Emit的使用
  • .net 按比例显示图片的缩略图
  • .NET 设计模式初探
  • .NET3.5下用Lambda简化跨线程访问窗体控件,避免繁复的delegate,Invoke(转)
  • .net解析传过来的xml_DOM4J解析XML文件
  • .NET面试题(二)
  • .NET中的Event与Delegates,从Publisher到Subscriber的衔接!
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)
  • ??myeclipse+tomcat
  • @Autowired注解的实现原理
  • @RequestMapping处理请求异常
  • [1]从概念到实践:电商智能助手在AI Agent技术驱动下的落地实战案例深度剖析(AI Agent技术打造个性化、智能化的用户助手)
  • [Angular] 笔记 21:@ViewChild
  • [c]扫雷
  • [c语言]小课堂 day2