之前查找网络上一些资料,说是重复的使用 AssetBundle.LoadAsset<T>()来获取资源对象; 虽然不会导致重复的反序列化资源,但是相比于将对象存储在字典中的管理方式,依然会慢上三倍的速度,对此一直比较疑惑,想必Unity官方的内部实现应该也不至于如此不堪,于是做了如下测试,(为了公平起见资源包中仅有一个预制体Cube,字典中也只存有一条内容,这样两种方式查询时的干扰都一样):
this.GetComponent<UnityEngine.UI.Button>().onClick.AddListener(() => {
UnityEngine.Networking.UnityWebRequest _request = UnityEngine.Networking.UnityWebRequestAssetBundle.GetAssetBundle(
"file:///" + Application.streamingAssetsPath + "/base.db");
UnityEngine.Networking.UnityWebRequestAsyncOperation _operation = _request.SendWebRequest();
while (!_operation.isDone)
{
System.Threading.Thread.Sleep(5);
}
Debug.Log("_operation.isDone");
if (_request.isNetworkError)
{
throw new Exception(_request.error);
}
else
{
UnityEngine.AssetBundle _ab = (_request.downloadHandler as UnityEngine.Networking.DownloadHandlerAssetBundle).assetBundle;
long _startTick = 0;
long _endTick = 0;
System.Collections.Generic.Dictionary<string, object> _dict = new Dictionary<string, object>();
_startTick = System.DateTime.Now.Ticks;
GameObject _cube1= _ab.LoadAsset<GameObject>("Cube");
_endTick = System.DateTime.Now.Ticks;
Debug.Log("_cube1 tick:" + (_startTick - _endTick).ToString());
_dict.Add("Cube", _cube1);
GameObject[] _cube2=new GameObject[10000];
GameObject[] _cube3 = new GameObject[10000];
//开始测试-----------------------------------------------------------------
System.Threading.Thread.Sleep(10);
_startTick = System.DateTime.Now.Ticks;
for (int i = 0; i < 10000; i++)
{
_cube2[i] = _ab.LoadAsset<GameObject>("Cube");
}
_endTick = System.DateTime.Now.Ticks;
Debug.Log("_cube2 tick:" + (_startTick - _endTick).ToString());
_startTick = System.DateTime.Now.Ticks;
for (int i = 0; i < 10000; i++)
{
if (_dict.ContainsKey("Cube"))
{
_cube3[i] = _dict["Cube"] as GameObject;
}
}
_endTick = System.DateTime.Now.Ticks;
Debug.Log("_cube3 tick:" + (_startTick - _endTick).ToString());
Debug.Log("click");
}
});
结果如下:
_cube1 tick: 因为是第一次loadAsset 需要反序列化 用8毫秒,之后 _cube2 tick 和 _cube3 tick 分别采用直接loadAsset 和 字典查询的方式 获取10000次资源对象,结果 loadAsset 用时超过数倍的时间,但是就此下结论还为时尚早,我将查询次数改到1000次,结果如下:
1000次的情况下 loadAsset 用时依然较长,但是仅1毫秒而已,虽然不如用字典来的快,但是实际的开发中不可能同时需要LoadAsset 上百次的情况.所以结论是,虽然重复的 LoadAsset 相对于用字典来管理 资源对象,的确要慢,但是并不是慢的不可接受,如果不是要求极为苛刻的情况,我认为可以忽略不计此性能损耗。不过还是要感叹一下,真的不能高估Unity官方的代码质量,很多地方大家还是要多做测试。