AssetBundle.LoadFromMemoryAsync
AssetBundleCreateRequest LoadFromMemoryAsync(byte[] binary, uint crc = 0);
使用二进制数据异步加载ab对象,通常我们对ab进行加密后,下载到本地解密,然后将解密后的二进制数据传进来,最后获取到ab对象。
如果是LZMA压缩的AB,会在加载的过程中进行解压;如果是LZ4压缩的AB,会直接加载压缩状态的数据。
与同步版接口LoadFromMemory立即返回ab对象不同,LoadFromMemoryAsync会在后台线程中执行解压操作。
IEnumerator LoadFromMemoryAsync(string path)
{
AssetBundleCreateRequest createRequest = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path));
yield return createRequest;
AssetBundle bundle = createRequest.assetBundle;
var prefab = bundle.LoadAsset.("MyObject");
Instantiate(prefab);
}
AssetBundle.LoadFromFile
AssetBundle LoadFromFile(string path, uint crc = 0, ulong offset = 0);
从本地加载未压缩(uncompressed)或使用LZ4压缩的AB,效率很高。
加载LZMA压缩的AB时,会先将其解压,然后再载入内存。
在Unity5.3及之前的版本中,在Android平台下调用这个接口去加载StreamingAssets目录下的ab会失败,因为安卓下这个目录是一个.jar的压缩文件。不过Unity5.4以及之后的版本已经修复这个问题,可以正常使用。
var myLoadedAssetBundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "myassetBundle"));
if (myLoadedAssetBundle == null) {
Debug.Log("Failed to load AssetBundle!");
return;
}
var prefab = myLoadedAssetBundle.LoadAsset.("MyObject");
Instantiate(prefab);
WWW.LoadFromCacheOrDownload
WWW LoadFromCacheOrDownload(string url, int version);
不推荐使用此接口,因为使用www对象来存储ab对象会造成内存开销过多,WebStreaming问题。
先从本地缓存中获取ab,如果不存在或者不是最新版本,则会从远程下载。如果ab是压缩过的,则会在线程中解压ab,然后写入本地缓存中。一但ab解压完成并缓存之后的加载流程就跟AssetBundle.LoadFromFile完全一样。
version用法??
IEnumerator Start()
{
while (!Caching.ready)
yield return null;
var www = WWW.LoadFromCacheOrDownload("http://myserver.com/myassetBundle.unity3d", 5);
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log(www.error);
yield return null;
}
var myLoadedAssetBundle = www.assetBundle;
var asset = myLoadedAssetBundle.mainAsset;
}
ab缓存由Caching类管理,Caching还可以用来做ab备份以及回滚。
https://docs.unity3d.com/ScriptReference/Caching.html
由于www的性能问题,使用这个接口时需要注意:
单个ab不能太大,一般建议不超过1M
在移动平台,同一时间最多下载一个ab,避免造成内存高峰
其它:
如果本地缓存没有足够空间,则会先删除最久没访问的资源;如果找不到可以删除的资源,则会跳过缓存过程,直接将文件加载到内容中,流程就跟"new WWW()"一样。
只能用此方法来访问AB,对其它类型资源不适用。
url中的'%'必须被省去。
UnityWebRequest
UnityWebRequest UnityWebRequest.GetAssetBundle(string uri, uint crc);
AssetBundle DownloadHandlerAssetBundle.GetContent(Networking.UnityWebRequest www);
最推荐的方式来替代www的方式加载AB,以减少webstream内存占用问题
先用UnityWebRequest.GetAssetBundle进行下载
再用DownloadHandlerAssetBundle.GetContent(UnityWebRequest)获取AB对象
IEnumerator InstantiateObject()
{
string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
yield return request.Send();
AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);
GameObject cube = bundle.LoadAsset("Cube");
GameObject sprite = bundle.LoadAsset("Sprite");
Instantiate(cube);
Instantiate(sprite);
}
LoadAsset
- 同步加载
T objectFromBundle = bundleObject.LoadAsset(assetName);
GameObject gameObject = loadedAssetBundle.LoadAsset(assetName);
Unity.Object[] objectArray = loadedAssetBundle.LoadAllAssets();
- 异步加载
AssetBundleRequest request = loadedAssetBundleObject.LoadAssetAsync(assetName);
yield return request;
var loadedAsset = request.asset;
AssetBundleRequest request = loadedAssetBundle.LoadAllAssetsAsync();
yield return request;
var loadedAssets = request.allAssets;
Load Manifests
- 在AB根目录,会有一个Manifest的AB文件,跟加载普通AB一样
- 存储了依赖关系,哈希值,AB变体等
AssetBundle assetBundle = AssetBundle.LoadFromFile(manifestFilePath);
AssetBundleManifest manifest = assetBundle.LoadAsset("AssetBundleManifest");
- 在加载AB前,需要先加载其依赖
AssetBundle assetBundle = AssetBundle.LoadFromFile(manifestFilePath);
AssetBundleManifest manifest = assetBundle.LoadAsset("AssetBundleManifest");
string[] dependencies = manifest.GetAllDependencies("assetBundle"); //Pass the name of the bundle you want the dependencies for.
foreach(string dependency in dependencies)
{
AssetBundle.LoadFromFile(Path.Combine(assetBundlePath, dependency));
}
其它
- 同一个AB只能加载一次,否则会报错,提示已经加载过
- 同一个AB只有在Unload后,才可以再次加载
https://docs.unity3d.com/Manual/AssetBundles-Native.html