1
2
|
//回收接口。参数是待回收GameObject
public static void recycle(GameObject recycleObj);
|
1
2
|
public static GameObject alloc( string type, float lifetime = 0);
public static void recycle(GameObject recycleObj);
|
参数lifeTime是存活时间,以秒为单位,定义如下
lifeTime > 0 lifeTime秒后自动回收对象。
lifeTime = 0 不自动回收对象,需游戏主动调用recycle回收。
lifeTime < 0 创建Pool实例并实例化Pool中的对象,但不返回对象,返回值null。
当lifeTime>0时,分配出去的GameObject上挂的PrefabInfo脚本会执行倒计时协程,计时器为0时调用recycle方法回收自己。它的适用对象如射击游戏中的子弹,申请时设定了lifeTime后不必关心回收的问题,当然游戏可以计时器在到时前主动发起回收。
lifeTime < 0的目的预创建对象池,在游戏场景Loading时可以用这个方法先把对象池创建起来,避免游戏中创建对象池造成掉帧。
ObjectPoolMgr用成员poolDic维护已分配的对象池实例
1
|
private Dictionary< string , ObjectPool> poolDic = new Dictionary< string , ObjectPool >();
|
使用objectPoolList记录面板上的用户设置
![](http://gameweb-img.qq.com/gad/20161017/phpTaVIOm.1476667748.png)
ObjectPoolMgr初始化时会在Unity的层次(Hierarchy)面板中创建GameObject并添加自身脚本。开发者可以在Inspector面板中直接创建新的对象池,如下图。Pre Alloc Size是对象池创建时预申请的对象数量。Auto Increase Size是池中的对象被申请完后进行一定数量的自增。prefab对象池关联的预制类型
1
2
3
4
5
6
7
|
public static GameObject alloc( string type, float lifetime = 0){
//根据传入type取出或创建对应类型对象池
ObjectPool subPool = Instance._getpool(type);
//从对象池中取一个对象返回
GameObject returnObj = subPool.alloc(lifetime);
return returnObj;
}
|
ObjectPoolMgr会根据传入的类型type,调用_getpool(type)找到对应的Pool,再从其中取一个对象返回。
代码中_getpool(string type)是ObjectPoolMgr中的私有方法。前面说过,ObjectPoolMgr有一个成员poolDic用来记录已创建的对象池实例,_getpool方法先去poolDic中查找,找到直接返回。如果找不到说明还未创建,使用反射创建对象池,记录入poolDic,代码如下
![](http://gameweb-img.qq.com/gad/20161017/phphbvy4h.1476667850.png)
1
2
3
4
5
6
7
8
9
10
|
protected Queue queue = new Queue (); //用来保存池中对象
[SerializeField]
protected int _freeObjCount = 0; //池中待分配对象数量
public int preAllocCount; //初始化时预分配对象数量
public int autoIncreaseCount; //池中可增加对象数量
protected bool _binit = false ; //是否初始化
[HideInInspector]
public GameObject prefab; //prefab引用
[HideInInspector]
public string objTypeString; //池中对象描述字符串
|
ObjectPool中的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
public virtual GameObject alloc( float lifetime){
//如果没有进行过初始化,先初始化创建池中的对象
if (!_binit){
_init();
_binit = true ;
}
if (lifetime<0){
Debug.LogWarning( "lifetime <= 0, return null" );
return null ; //lifetime<0时,创建对象池并返回null
}
GameObject returnObj;
if (_freeObjCount > 0){ //池中有待分配对象
returnObj = queue.Dequeue(); //分配
_freeObjCount--;
} else { //池中没有对象了,实例化一个
returnObj = Instantiate(prefab , new Vector3(0,0,0), Quaternion.identity) as GameObject;
returnObj.SetActive( false ); //防止挂在returnObj上的脚本自动开始执行
returnObj.transform.parent = this .transform;
}
//使用PrefabInfo脚本保存returnObj的一些信息
PrefabInfo info = returnObj.GetComponent《 PrefabInfo 》();
if (info == null ){
info = returnObj.AddComponent 《 PrefabInfo 》();
}
if (lifetime > 0){
info.lifetime = lifetime;
}
info.types = objTypeString;
returnObj.SetActive( true );
return returnObj;
}
public virtual void recycle(GameObject obj){
//待分配对象已经在对象池中
if (queue.Contains(obj)){
Debug.LogWarning( "the obj " + obj.name + " be recycle twice!" );
return ;
}
if ( _freeObjCount > preAllocCount + autoIncreaseCount ){
Destroy(obj); //当前池中object数量已满,直接销毁
} else {
queue.Enqueue(obj); //入队,并进行reset
obj.transform.parent = this .transform;
obj.SetActive( false );
_freeObjCount++;
}
}
|
这里要注意的是,基类alloc和recycle方法要使用虚函数,子类override实现多态。
3>对象池子类CubePool
子类override父类的alloc和recycle,进行个性化的申请和回收工作。
1
2
3
4
5
6
7
|
public class CubePool : ObjectPool {
public override GameObject alloc( float lifetime){
GameObject cubeObject= base .alloc(lifetime);
//在这里进行CubePool个性化的的初始化工作
return cubeObject;
}
}
|
当然也可以直接复用基类的alloc方法,甚至不写CubePool类。当ObjectPoolMgr申请一个Cube但找不到CubePool类时,会使用通用方法进行分配和回收。
4>PrefabInfo
PrefabInfo是挂在prefab实例上,用来记录prefab类型和lifetime等数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public class PrefabInfo : MonoBehaviour {
public string types;
[HideInInspector]
public float lifetime = 0;
void OnEnable(){
if (lifetime > 0){
StartCoroutine(countTime(lifetime));
}
}
IEnumerator countTime( float lifetime){
yield return new WaitForSeconds(lifetime);
ObjectPoolMGR.recycle(gameObject);
}
}
|
新增Pool方法
为一个新Perfab创建对象池需要以下两步,
1、在unity面板中把prefab挂上,并设置prefab的实例化数量和可增加数量
2、(可选)实现一个对应的Pool脚本。如果不实现,这个对象池会使用通用的申请和回收方法。
调用申请和释放方法
1
2
3
4
5
6
|
//申请
GameObject obj1 = ObjectPoolMGR.alloc( "Cube" ,5);
GameObject obj2 = ObjectPoolMGR.alloc( "Sphare" );
//回收
ObjectPoolMGR.recycle(obj2);
|