Unity3D游戏架构设计之对象管理【二】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wuming2016/article/details/61413535

1     概述

       在上一篇 Unity3D游戏架构设计之对象管理【一】中已经介绍了对象管理的作用,在整个游戏架构中所处的位置,其内部模块组织。也提到了它的三个内部模块中的两个模块:“对象池管理器”和“缓存”主要的数据结构。而这一篇中重点介绍最后一个内部模块“对象池”的设计。前两个模块的和具体游戏相关性较大,“对象池管理器”采用Dictionary,key可能就是npc的分类;“缓存”采用Dictionary,key可能就是npc的实体ID(entityid)。而“对象池”相对而言就是一个“纯技术”的东西,程序设计的技巧性更大。

2     再探“对象池”的作用

       先概括在前篇中我们了解到“对象池”的几个作用:
       (1)从“资源管理器”加载对象
       (2)预存储了多个对象
       (3)当收到获取对象请求后把空闲对象传递出去
       (4)回收暂时不用的对象
       第(1)点没有太多技巧可言,基本上就是“资源管理器”提供什么接口供调用。
       第(2)点主要是要实现预存储的策略。这种策略可以参考C++  STL 的一些策略。这类策略通常是每次加载一定数目,使得可用个数比当前需要的多。比如,预加载32个,当不够用时,再一次性加载32个。还可以不预加载,第一次被索要对象时才加载32个。通过这种方式,使得大多数情况下对象是够用的,从而避免了频繁的调用“资源管理器”进行加载。
       第(3)(4)是相对的,很像c++的new 和 delete。(3)是给外界分配对象,取对象,(4)是回收分配出去的对象,还对象。这两点实现的好不好,直接影响了整个“对象池”的性能。

3     为“内存池”选择适合的数据结构

       我们先分析c#中几种常见的数据结构的可能性
       (1)Dictionary
       查找速度倒是快,但问题是该用什么做key?用EntityID?可是这都是预先存储的,还不知道EntityID是什么呢。
       (2)List
       如果单用List内部是数组,是无法实现O(1)的查找效率的。它想达到O(1),得用索引(下标)查。核心问题成了得到一个空闲对象在List中的索引。我曾经实现一个算法,用List再加上一些额外的变量实现了对List中空闲对象O(1)的查找和回收效率。实际使用过一段时间,性能是相当不错的,我还给它起了一个好听的名字“dfpool”,全名“double free pool”。但后来为逐渐放弃了这个算法。原因有两点:第一是,算法性能好,想明白了很简单,但是写出来程序不容易让其他人读懂。第二是,这个算法要对被存储的对象额外加一个字段。虽然我设计了一个对象的基类,要存储的对象从它继承,做到了对外界透明,也比较通用,但是,依然不是很满意。因为我认为“对象池”不应该对“对象”有要求。因此有了下面这种选择。
      (3)Queue
        完全满足了我的要求,O(1)的效率,程序简单易读,对存储的对象没有额外的要求。这个想明白了其实也很简单。“取对象”时,直接Dequeue出去,“还对象”时Enqueue回来。了解queue都应该知道,可以认为这两个操作都是O(1)的效率。只要是在Queue中的,都是空闲的对象。如果没有没有空闲的对象,Queue里就是空的,这时需要从“资源管理器”中加载32个对象。
       到目前为止,整个对象管理的实现思路就讲完了,下一篇我们用具体代码讲如何实现“对象池”,“缓存”,“对象池管理器”,以及用“对象管理器”把它们整合在一起。

猜你喜欢

转载自blog.csdn.net/wuming2016/article/details/61413535