|
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记录面板上的用户设置

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,代码如下

|
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); |
本文介绍Unity3D中对象池的设计与实现细节,包括模块设计、数据管理、接口及调用流程等,并通过对比测试展示其在资源管理和性能优化方面的优势。
1340

被折叠的 条评论
为什么被折叠?



