Unity教程之-Unity5.x版本AssetBundle加载研究

之前说了 “unity4.x版本AssetBundle打包研究”,没看过的请先看一下《Unity教程之-Unity3d打包Assetbundle并加载》,再来看本文,有一定的连接性。

先梳理一下思路:
要加载一个资源A,必须先去加载它的所有依赖资源
要知道这个资源A依赖了哪些资源,必须先去加载AssetBundleManifest
通过AssetBundleManifest对象的GetAllDependencies(A)方法,获取它依赖的所有资源。
依赖资源都加载了,就可以去真正加载资源A了。

注意点:
1.资源A加载完了后,要记得Unload(false),资源A的依赖资源要在 资源A加载完成后,才能Unload(false),否则无法正常加载资源A
2.不Unload的话也可以,那就自己做一个字典记录所有加载过的AssetBundle,还有它们的引用计数器。那样就可以先判断是否存在,然后再确定是否要去加载。

我下面的例子,采用1的方式。就是加载完了后就Unload的方式。

?
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
 
public class AssetBundleLoaderMgr : Singleton
{
public string m_assetPath = Application.streamingAssetsPath;
string assetTail = ".unity3d" ;
 
#region LoadAssetBundle
 
///
/// 加载目标资源
///
///
///
public void LoadAssetBundle(string name, Action callback)
{
name = name + assetTail; //eg:ui/panel.unity3d
 
Action> action = (depenceAssetBundles) =>
{
 
string realName = this .GetRuntimePlatform() + "/" + name; //eg:Windows/ui/panel.unity3d
 
LoadResReturnWWW(realName, (www) =>
{
int index = realName.LastIndexOf( "/" );
string assetName = realName.Substring(index + 1);
assetName = assetName.Replace(assetTail, "" );
AssetBundle assetBundle = www.assetBundle;
UnityEngine.Object obj = assetBundle.LoadAsset(assetName); //LoadAsset(name),这个name没有后缀,eg:panel
 
//卸载资源内存
assetBundle.Unload( false );
for ( int i = 0; i < depenceAssetBundles.Count; i++)
{
depenceAssetBundles[i].Unload( false );
}
 
//加载目标资源完成的回调
callback(obj);
});
 
};
 
LoadDependenceAssets(name, action);
}
 
///
/// 加载目标资源的依赖资源
///
///
///
private void LoadDependenceAssets(string targetAssetName, Action> action)
{
Debug.Log( "要加载的目标资源:" + targetAssetName); //ui/panel.unity3d
Action dependenceAction = (manifest) =>
{
List depenceAssetBundles = new List(); //用来存放加载出来的依赖资源的AssetBundle
 
string[] dependences = manifest.GetAllDependencies(targetAssetName);
Debug.Log( "依赖文件个数:" + dependences.Length);
int length = dependences.Length;
int finishedCount = 0;
if (length == 0)
{
//没有依赖
action(depenceAssetBundles);
}
else
{
//有依赖,加载所有依赖资源
for ( int i = 0; i < length; i++)
{
string dependenceAssetName = dependences[i];
dependenceAssetName = GetRuntimePlatform() + "/" + dependenceAssetName; //eg:Windows/altas/heroiconatlas.unity3d
 
//加载,加到assetpool
LoadResReturnWWW(dependenceAssetName, (www) =>
{
int index = dependenceAssetName.LastIndexOf( "/" );
string assetName = dependenceAssetName.Substring(index + 1);
assetName = assetName.Replace(assetTail, "" );
AssetBundle assetBundle = www.assetBundle;
UnityEngine.Object obj = assetBundle.LoadAsset(assetName);
//assetBundle.Unload(false);
depenceAssetBundles.Add(assetBundle);
 
finishedCount++;
 
if (finishedCount == length)
{
//依赖都加载完了
action(depenceAssetBundles);
}
});
}
}
};
LoadAssetBundleManifest(dependenceAction);
}
 
///
/// 加载AssetBundleManifest
///
///
private void LoadAssetBundleManifest(Action action)
{
string manifestName = this .GetRuntimePlatform();
manifestName = manifestName + "/" + manifestName; //eg:Windows/Windows
LoadResReturnWWW(manifestName, (www) =>
{
AssetBundle assetBundle = www.assetBundle;
UnityEngine.Object obj = assetBundle.LoadAsset( "AssetBundleManifest" );
assetBundle.Unload( false );
AssetBundleManifest manif = obj as AssetBundleManifest;
action(manif);
});
}
#endregion
 
#region ExcuteLoader
public void LoadResReturnWWW(string name, Action callback)
{
string path = "file://" + this .m_assetPath + "/" + name;
Debug.Log( "加载:" + path);
StartCoroutine(LoaderRes(path, callback));
}
 
IEnumerator LoaderRes(string path, Action callback)
{
WWW www = new WWW(path);
yield return www;
if (www.isDone)
{
callback(www);
}
}
#endregion
 
#region Util
///
/// 平台对应文件夹
///
///
private string GetRuntimePlatform()
{
string platform = "" ;
if (Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsEditor)
{
platform = "Windows" ;
}
else if (Application.platform == RuntimePlatform.Android)
{
platform = "Android" ;
}
else if (Application.platform == RuntimePlatform.IPhonePlayer)
{
platform = "IOS" ;
}
else if (Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXEditor)
{
platform = "OSX" ;
}
return platform;
}
}

测试一下咯

?
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
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
 
public class TestAssetBundleLoader : MonoBehaviour
{
Dictionary GameObjectPool = new Dictionary();
 
void Start()
{
//要加载的资源的队列
Queue needLoadQueue = new Queue();
needLoadQueue.Enqueue( "ui/plane" );
needLoadQueue.Enqueue( "ui/cube" );
needLoadQueue.Enqueue( "ui/sphere" );
 
Load(needLoadQueue);
}
 
void Load(Queue needLoadQueue)
{
if (needLoadQueue.Count > 0)
{
string needLoadAssetName = needLoadQueue.Dequeue();
AssetBundleLoaderMgr.Instance.LoadAssetBundle(needLoadAssetName, (obj) =>
{
GameObject go = GameObject.Instantiate(obj) as GameObject;
int index = needLoadAssetName.LastIndexOf( "/" );
string assetName = needLoadAssetName.Substring(index + 1);
 
//加载出来的GameObject放到GameObjectPool存储
GameObjectPool.Add(assetName, go);
 
Load(needLoadQueue);
});
}
else
{
Debug.Log( "all finished" );
}
}
}

可能代码写的还有很多优化的地方 ,毕竟100个人有100种写法,思路才是最重要的。你说呢?
其实我想说的是,代码都在了,自己尝试一下吧!好了,本篇unity3d教程到此结束,下篇我们再会!

你可能感兴趣的:(Unity3D)