Unity 简易对象池

“每隔x秒随机产生10-20个物体(cube或者sphere),要求显示在屏幕上,并在x秒的显示后将其回收”。看似简单的题目小菜也楞是在紧张中满头大汗的调试了两个小时左右才得以完成Unity 简易对象池Unity 简易对象池

Unity 简易对象池

    本篇就来讨论下对象池的那些事。对象池的概念也算是老生常谈的话题了,小菜简单直白的理解就是解决瞬间克隆(Instance)大量对象带来的性能问题,将预创建和已使用过的对象缓存起来供下次的直接使用,用内存来换取性能的一种手段。Unity 简易对象池Unity 简易对象池

Unity 简易对象池

    面试中面试官常常提及到你的性能优化手段和你解决过游戏卡顿的实操方法。对象池就是其中一种,那个被举的最多的例子就数:Player发射大量子弹的过程吧Unity 简易对象池Unity 简易对象池。实际情况也确实是这样,更多的情况还有游戏特效,UI上的滑动列表甚至是音效播放等等。预加载和对象池在游戏研发中尤为重要。

Unity 简易对象池

    回忆往昔,小菜兴趣燃起又将自己编写的对象池拿出来分享下Unity 简易对象池Unity 简易对象池

    先上小菜的uml类图吧(Unity 简易对象池家里没网没有工具将就下吧)

    

Unity 简易对象池

    尽管网上给出了茫茫多的对象池设计模型,而在这里仅仅代表小菜自己的见解和使用,望各位大佬莫要吐槽Unity 简易对象池

 

对象池解析

    首先从上图中可以直观看出,小菜包装了4个类。这4个类的作用分别是:

    1).ResPool            

        小菜以一类GameOjbect划分为一类对象池。而每一类对象池又以一个字符串的key作为索引。ResPool 便是对象池个体的包装。

    2).ResPoolMgr

        故名思意这是一个管理众多(ResPool)对象池个体的类。ResPool与ResPoolMgr属于聚合关系。ResPoolMgr包含ResPool对象,但ResPool并不是ResPoolMgr的一部分。

    3).AssetMgr

        通常AssetMgr这一层打交道的一般是所有资源的加载管理,包括AssetBundle、Resource、AssetDataBase各种同步异步等。小菜的演示过程里简化了,AssetMgr仍代表资源加载的核心接口类。

    4).PoolKeyDefine

     PoolKeyDefine仅仅作为一个ResPool的key的定义类,抽离出来的目的是由于项目中要做大量的频繁修改。根据对象的开闭包装原则,我们最不希望的是修改编码的时候来轻易侵入触动我们设计的核心类里。Unity 简易对象池Unity 简易对象池

 

对象池编码

1).ResPool      

Unity 简易对象池

 

Unity 简易对象池

大量的接口说明都已经在注释中详细说明。mObjList便是维护存入池子的集合。mOriginalRes为存入的原始对象,要小心处理避免将原始对象也给回收了Unity 简易对象池Unity 简易对象池Unity 简易对象池

 

2).ResPoolMgr

Unity 简易对象池

 

Unity 简易对象池

Unity 简易对象池

Unity 简易对象池

本类并不需产生多余的实例,小菜定义为了单例类。仅仅通过对象的静态实例来访问。

 

3).AssetMgr

Unity 简易对象池

 

Unity 简易对象池

 

 4).PoolKeyDefine

    最后是这个定义key的类,仅仅是为了约束开发时的规范不至于开发时常常写错Unity 简易对象池Unity 简易对象池

Unity 简易对象池

 

外部调用接口

1).弹出obj对象

GameObject tempObj = AssetMgr.GetInstance().PopGameObject(PoolKeyDefine.CreateCube, obj);

 

2).回收obj对象

 AssetMgr.GetInstance().PushGameObject(PoolKeyDefine.CreateCube, this.gameObject);

 

3).清理对象池

 AssetMgr.GetInstance().ClearPoolByKey(PoolKeyDefine.CreateCube);

 

4).查询对象池缓存情况

int poolNum = AssetMgr.GetInstance().GetResPoolObjCount(PoolKeyDefine.CreateCube);

 

真的很希望wx团队能开发一个可以贴代码的编辑法,尝试了好多方式都没法排版只能图片了Unity 简易对象池Unity 简易对象池Unity 简易对象池

最后是小菜的一个demo展示:

Unity 简易对象池

    对于对象池的再进一步的包装也可以在预加载的时候完成一些事情,用loading来解决一些用户流畅性上的体验。甚至是加入池子中对象的数量判断,当缓存对象大于某个阈值时清理一部分(避免内存的占用过高),毕竟对象池也不是万能的,也是以内存的开销为代价的。