- 最后登录
- 2016-10-1
- 注册时间
- 2013-12-28
- 阅读权限
- 90
- 积分
- 5805
- 纳金币
- 2954
- 精华
- 3
|
今早看到了一篇关于对象池介绍的文章。想起了以前自己做类似的事情碰到的问题。先看下文章是如何介绍的。如下
对象池
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一个。
所以,一般对象池的使用场景是在对象池的对象只会在场景中出现一次。也就是一个地方出现。比如游戏中的怪物。生成了一个怪物。保存这个怪物在对象池里面。当这只怪物被打死之后,不销毁这个怪物,把这个怪物放回到对象池。下一次,下一个关卡还需要同样的怪物的时候,那我们就不需要去实例化怪物了,直接从对象池取上次一的对象就可以。这样就达到了性能的优化。
但是这样的操作带来一个问题就是内存峰值的增加。如果我们有很多这样的对象,那用对象池也是不合适的。所以对象池是视情况而用。不能盲目用。并且知道其运用的场景。
不知道我的理解对不对。望大神们不吝赐教。多多点评。
|
|