OnUpdate方法里调用LoadAsset加载配置文件对象及所有资源对象。每一帧都要判断是否加载结束,如果结束清空mScene和mSceneAsset对象为下一次加载做准备,并且取消update事件的注册。
最核心的LoadAsset方法:
C#代码
01
private Asset LoadAsset(Asset asset) {
02
03
string fullFileName = mResourcePath + “/” + asset.Source;
04
05
//if www resource is new, set into www cache
06
07
if (!wwwCacheMap.ContainsKey(fullFileName)) {
08
09
if (asset.www == null) {
10
11
asset.www = new WWW(fullFileName);
12
13
return null;
14
15
}
16
17
if (!asset.) {
18
19
return null;
20
21
}
22
23
wwwCacheMap.Add(fullFileName, asset.www);
24
25
}
26
传进来的是要加载的资源对象,先得到它的物理地址,mResourcePath是个全局变量保存资源服务器的网址,得到fullFileName类似 。然后通过wwwCacheMap判断资源是否已经加载完毕,如果加载完毕把加载好的www对象放到Map里缓存起来。看看前面Json配置文件,Chair 1和Chair 2用到了同一个资源Chair001.unity3d,加载Chair 2的时候就不需要下载了。如果当前帧没有加载完毕,返回null等到下一帧再做判断。这就是WWW类的特点,刚开始用WWW下载资源的时候是不能马上使用的,要等待诺干帧下载完成以后才可以使用。可以用yield返回www,这样代码简单,但是C#要求调用yield的方法返回IEnumerator类型,这样限制太多不灵活。
继续LoadAsset方法:
C#代码
01
if (asset.Type == Asset.TYPE_JSON) { //Json
02
03
if (mScene == null) {
04
05
string jsonTxt = mSceneAsset.;
06
07
mScene = JsonMapper.ToObject<Scene>(jsonTxt);
08
09
}
10
11
//load scene
12
13
foreach (Asset sceneAsset in mScene.AssetList) {
14
15
if (sceneAsset.isLoadFinished) {
16
17
continue;
18
19
} else {
20
21
LoadAsset(sceneAsset);
22
23
if (!sceneAsset.isLoadFinished) {
24
25
return null;
26
27
}
28
29
}
30
31
}
32
33
}
代码能够运行到这里,说明资源都已经下载完毕了。现在开始加载处理资源了。第一次肯定是先加载配置文件,因为是Json格式,用JsonMapper类把它转换成C#对象,我用的是LitJson开源类库。然后循环递归处理场景中的每一个资源。如果没有完成,返回null,等待下一帧处理。
继续LoadAsset方法:
C#代码
01
else if (asset.Type == Asset.TYPE_GAMEOBJECT) { //Gameobject
02
03
if (asset.gameObject == null) {
04
05
wwwCacheMap[fullFileName].assetBundle.LoadAll();
06
07
GameObject go = (GameObject)GameObject.Instantiate(wwwCacheMap[fullFileName].assetBundle.mainAsset);
08
09
UpdateGameObject(go, asset);
10
11
asset.gameObject = go;
12
13
}
14
15
if (asset.AssetList != null) {
16
17
foreach (Asset assetChild in asset.AssetList) {
18
19
if (assetChild.isLoadFinished) {
20
21
continue;
22
23
} else {
24
25
Asset assetRet = LoadAsset(assetChild);
26
27
if (assetRet != null) {
28
29
assetRet.gameObject.transform.parent = asset.gameObject.transform;
30
31
} else {
32
33
return null;
34
35
}
36
37
}
38
39
}
40
41
}
42
43
}
44
45
asset.isLoadFinished = true;
46
47
return asset;
48
49
}
50
终于开始处理真正的资源了,从缓存中找到www对象,调用Instantiate方法实例化成Unity3D的gameobject。 UpdateGameObject方法设置gameobject各个属性,如位置和旋转角度。然后又是一个循环递归为了加载子对象,处理 gameobject的父子关系。注意如果LoadAsset返回null,说明www没有下载完毕,等到下一帧处理。最后设置加载完成标志返回 asset对象。
UpdateGameObject方法:
C#代码
01
private void UpdateGameObject(GameObject go, Asset asset) {
02
03
//name
04
05
go.name = asset.Name;
06
07
//position
08
09
Vector3 vector3 = new Vector3((float)asset.Position[0], (float)asset.Position[1], (float)asset.Position[2]);
10
11
go.transform.position = vector3;
12
13
//rotation
14
15
vector3 = new Vector3((float)asset.Rotation[0], (float)asset.Rotation[1], (float)asset.Rotation[2]);
16
17
go.transform.eulerAngles = vector3;
18