ObjectPoolManager增加异步加载API

ResourceObj类增加用于异步回调的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ResourceObj
{
//...

//---------------------------------------------
//是否放到场景节点下
public bool m_SetSceneParent = false;
//实例化资源完成的回调
public OnAsyncObjFinish m_DealFinish = null;
//异步参数
public object m_Param1, m_Param2, m_Param3;

public void Reset()
{
//...
m_SetSceneParent = false;
m_DealFinish = null;
m_Param1 = null;
m_Param2 = null;
m_Param3 = null;
}
}

添加AsyncInstantiateObject方法和回调方法

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
    /// <summary>
/// 从对象池中异步实例化对象
/// </summary>
/// <param name="path">对象路径</param>
/// <param name="dealFinish">回调</param>
/// <param name="priority">加载优先级</param>
/// <param name="setSceneObj">是否在场景设置父物体</param>
/// <param name="param1">回调参数1</param>
/// <param name="param2">回调参数2</param>
/// <param name="param3">回调参数3</param>
/// <param name="bClear">是否换场景销毁</param>
/// <param name="isSprite">是否加载Sprite</param>
/// <returns>此异步方法的ID,用于取消异步</returns>
public void AsyncInstantiateObject(
string path,
OnAsyncObjFinish dealFinish,
LoadResPriority priority,
bool setSceneObj = false,
object param1 = null,
object param2 = null,
object param3 = null,
bool bClear = true,
bool isSprite = false)
{
if (string.IsNullOrEmpty(path))
{
return;
}
uint crc = CRC32.GetCRC32(path);
ResourceObj resObj = GetObjectFromDicCache(crc);
if (resObj != null)
{
if (setSceneObj)
{
resObj.m_CloneObj.transform.SetParent(SceneTrans, false);
}
if(dealFinish != null)
{
dealFinish.Invoke(path, resObj.m_CloneObj, param1, param2, param3);
}
return;
}

resObj = m_ResourceObjPool.Spawn(true);
resObj.m_Crc = crc;
resObj.m_SetSceneParent = setSceneObj;
resObj.m_bClear = bClear;
resObj.m_DealFinish = dealFinish;
resObj.m_Param1 = param1;
resObj.m_Param2 = param2;
resObj.m_Param3 = param3;
//调用ResourceManager的对象池异步加载接口
ResourceManager.Instance.AsyncLoadPoolResource(path, resObj, OnLoadResourceObjFinish, priority, isSprite);
}
/// <summary>
/// 异步资源加载完成的回调
/// </summary>
/// <param name="path">路径</param>
/// <param name="resObj">中间类</param>
/// <param name="param1">参数1</param>
/// <param name="param2">参数2</param>
/// <param name="param3">参数3</param>
void OnLoadResourceObjFinish(string path, ResourceObj resObj, object param1 = null, object param2 = null, object param3 = null)
{
if (resObj == null)
{
return;
}
if(resObj.m_ResItem.m_Obj == null)
{
#if UNITY_EDITOR
Debug.LogError("异步加载的资源为空:" + path);
#endif
}
else
{
resObj.m_CloneObj = GameObject.Instantiate(resObj.m_ResItem.m_Obj) as GameObject;
}
if (resObj.m_CloneObj != null && resObj.m_SetSceneParent)
{
resObj.m_CloneObj.transform.SetParent(SceneTrans,false);
}
if (resObj.m_DealFinish != null)
{
int tempGUID = resObj.m_CloneObj.GetInstanceID();
if (!m_ResourceObjDic.ContainsKey(tempGUID))
{
m_ResourceObjDic.Add(tempGUID, resObj);
}
resObj.m_DealFinish(path,resObj.m_CloneObj,resObj.m_Param1,resObj.m_Param2,resObj.m_Param3);
}
}

ResourceManager增加用于对象池异步加载的API

增加用于对象池异步加载的回调

1
public delegate void OnAsyncPoolObjFinish(string path, ResourceObj resObj, object param1 = null, object param2 = null, object param3 = null);

AsyncCallBack回调类增加回调引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class AsyncCallBack 
{
public OnAsyncObjFinish m_DealFinish = null;

public OnAsyncPoolObjFinish m_PoolDealFinish = null;
public ResourceObj m_ResObj = null;

public object m_Param1 = null;
public object m_Param2 = null;
public object m_Param3 = null;
public void Reset()
{
m_DealFinish = null;
m_PoolDealFinish = null;
m_ResObj = null;
m_Param1 = null ;
m_Param2 = null ;
m_Param3 = null ;
}
}


添加AsyncLoadPoolResource方法

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
/// <summary>
/// 异步加载资源,针对给ObjectPoolManager的接口
/// </summary>
public void AsyncLoadPoolResource(string path, ResourceObj resObj, OnAsyncPoolObjFinish dealFinish, LoadResPriority priority, bool isSprite = false)
{
ResourceItem item = GetCacheResourceItem(resObj.m_Crc);
if (item != null)
{
resObj.m_ResItem = item;
if (dealFinish != null)
{
dealFinish(path, resObj,resObj.m_Param1,resObj.m_Param2,resObj.m_Param3 );
}
return;
}

//判断是否在加载中
AsyncLoadResParam para = null;
if (!m_LoadingAssetDic.TryGetValue(resObj.m_Crc, out para) || para == null)
{
para = m_AsyncLoadResParamPool.Spawn(true);
para.m_Crc = resObj.m_Crc;
para.m_Path = path;
para.m_isSprite = isSprite;
para.m_Priority = priority;
m_LoadingAssetDic.Add(resObj.m_Crc, para);
m_LoadingAssetList[(int)priority].Add(para);
}

AsyncCallBack callBack = m_AsyncCallBackPool.Spawn(true);
callBack.m_PoolDealFinish = dealFinish;
callBack.m_ResObj = resObj;
para.m_CallBackList.Add(callBack);
}

在异步协程中添加Pool回调的调用方法

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
IEnumerator AsyncLoadCor()
{
List<AsyncCallBack> callBackList = null;
//上一次Yield的时间
long lastYieldTime = System.DateTime.Now.Ticks;
while(true)
{
bool haveYield =false;
for (int i = 0; i < (int)LoadResPriority.RES_NUM; i++)
{
//...
for (int j = 0; j < callBackList.Count; j++)
{
AsyncCallBack callBack = callBackList[j];
//+++++++++++++++++++++++++++++
if (callBack != null && callBack.m_PoolDealFinish != null && callBack.m_ResObj != null)
{
ResourceObj tempResObj = callBack.m_ResObj;
tempResObj.m_ResItem = resItem;
callBack.m_PoolDealFinish(loadingItem.m_Path, tempResObj, tempResObj.m_Param1, tempResObj.m_Param2, tempResObj.m_Param3);
callBack.m_PoolDealFinish = null;
tempResObj = null;
}
//+++++++++++++++
if(callBack != null && callBack.m_DealFinish != null)
{
//...
}
//...
}
//...
}
//...
}
}

一些解释

Object Pool Manger的OnLoadResourceObjFinish方法匹配的是OnAsyncPoolObjFinish回调。

OnAsyncPoolObjFinish回调是在Resource Manager的协程里面调用的。

ResourceObj内部引用的是OnAsyncObjFinish回调

所以在OnAsyncPoolObjFinish调用之后,返回的ResourceObj需要再调用OnAsyncObjFinish回调

异步加载演示

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
48
49
using UnityEngine;

public class GameStart : MonoBehaviour
{
private GameObject m_GameObject;
private void Awake()
{
DontDestroyOnLoad(gameObject);
AssetBundleManager.Instance.LoadAssetBundleConfig();
ResourceManager.Instance.Init(this);//初始化异步加载
ObjectPoolManager.Instance.Init(transform.Find("RecyclePoolTrans"),transform.Find("SceneTrans"));
}
private void Start()
{
//从对象池实例化对象,并且设置父级
ObjectPoolManager.Instance.AsyncInstantiateObject("Assets/Prefabs/Attack.prefab",OnLoadFinish,LoadResPriority.RES_HIGH,true);
}
void OnLoadFinish(string path,Object obj,object param1 = null, object param2 = null, object param3 = null)
{
m_GameObject = obj as GameObject;
}
private void Update()
{
if(Input.GetKeyDown(KeyCode.A))
{
//从对象池回收对象,但不销毁
ObjectPoolManager.Instance.ReleaseObject(m_GameObject);
//在使用上面的方式回收对象时,一定要把对象的引用置空,因为对象并没有真正被清理掉,防止发生重复Release的情况
m_GameObject = null;
}
else if (Input.GetKeyDown(KeyCode.D))
{
//从对象池实例化对象,并且设置父级
ObjectPoolManager.Instance.AsyncInstantiateObject("Assets/Prefabs/Attack.prefab", OnLoadFinish, LoadResPriority.RES_HIGH, true);
}
else if (Input.GetKeyDown(KeyCode.S))
{
//从对象池回收对象,完全销毁
ObjectPoolManager.Instance.ReleaseObject(m_GameObject, 0, true);
m_GameObject = null;
}
}
private void OnApplicationQuit()
{
ResourceManager.Instance.ClearCache();
Resources.UnloadUnusedAssets();
}
}