纳金网

标题: 关于游戏对象池中的那些事(转载) [打印本页]

作者: 刀锋狼    时间: 2014-4-30 02:49
标题: 关于游戏对象池中的那些事(转载)
今早看到了一篇关于对象池介绍的文章。想起了以前自己做类似的事情碰到的问题。先看下文章是如何介绍的。如下
对象池

1.建立一个名为ObjectPool的脚本,设计ObjectPool类的一个单例。拖拽到ObjectPoolManager物体上
2.Awake中调用协同程序generateObjects()
3.generateObjects()中将游戏中所需要的所有物体实例化,给物体取一个名字,该名字与实例化时所用的prefab名相同,并调用公有函数addObject(obj),每次实例化相隔一帧(yield return 0)
4.在addObject(obj)中,将上面生成的物体隐藏,使它们的父物体为ObjectPoolManager,并以它们的名字(name)为key添加(Add)到一个Dictionary中,由于可能有同名的很多物体(如金币),所以需要将这个Dictionary定义为private Dictionary<string, List<GameObject>> dict;'
添加时,先判断这个Dictionary中是否已经存在以物体的名字为key的值(TryGetValue(key,out value)),若存在,说明是像金币那样的同名物体,就将物体添加到value(这里是一个list数组)中;若不存在,则要新建一个list,将物体添加到list中,再以物体名字为key,list为value,添加到Dictionary中。
5.再写一个公有函数getObject(obj)函数,实现从对象池中取物体操作。

如果Dictionary已经存在该物体,则激活该物体,并从list中移除,父物体设为null
如果不存在就要再实例化了
--------------------------------------------------------------------------------------------------------------------------------------
      其实,我想说的也没有什么。上面的做法是正确的。但是其实是有一个前提,那就是场景中这个物体只会出现一次。也就只会在一个地方出现。如果这个GameObject在两个地方出现的话。对象池估计就失去意义了。而且还会给你带来不必要的麻烦。

      怎么解释呢?:
      如上文章所说。用getObject从对象池取物体。已经存在直接用。不存在就实例化。那么第一次我们去取物体,不存在,实例化了。然后这个实例化的对象存入字典里面。并且把这个实例化的物体加入到父物体中。这一步没错。
      但是,如果这时候,我还需要一个这样的物体呢?那我们是不是还需要用getObject方法取一次。那这时候取一次的操作获得的物体我们是要用上次生成的对象呢,还是重新生成?如果用上一次的对象。那么由于上一次的对象已经被加入到其他物体作为子对象了。这样的操作将使其从上一次的父物体上移除,然后加入到新的父物体上。这样就出问题了。如果我们重新生成一个的话。那对象池有啥意义呢?每次还不是一样要重新new一个。

      所以,一般对象池的使用场景是在对象池的对象只会在场景中出现一次。也就是一个地方出现。比如游戏中的怪物。生成了一个怪物。保存这个怪物在对象池里面。当这只怪物被打死之后,不销毁这个怪物,把这个怪物放回到对象池。下一次,下一个关卡还需要同样的怪物的时候,那我们就不需要去实例化怪物了,直接从对象池取上次一的对象就可以。这样就达到了性能的优化。
     但是这样的操作带来一个问题就是内存峰值的增加。如果我们有很多这样的对象,那用对象池也是不合适的。所以对象池是视情况而用。不能盲目用。并且知道其运用的场景。
     不知道我的理解对不对。望大神们不吝赐教。多多点评。


作者: hyui    时间: 2014-4-30 03:52
Thank you for sharing this!!!
作者: kk123456    时间: 2014-4-30 10:23
多謝分享
作者: xx232    时间: 2014-4-30 19:59
很多情况下都是可以复用的  这很有用  当然不考虑资源占用  那无所谓了




欢迎光临 纳金网 (http://www.narkii.com/club/) Powered by Discuz! X2.5