首先,相比AssetBundle,更推荐使用Addressable Assets System
本文对AssetBundle使用做简要介绍,同时分析四种下载方式的内存占用情况
注意:小游戏环境不支持assetbundle本地加载
自行组织资源如何分组,以及各个bundle之间依赖关系,包名相同的资源会打包到一起
public static void Build()
{
string dst = Application.streamingAssetsPath + "/AssetBundles";
if (!Directory.Exists(dst))
{
Directory.CreateDirectory(dst);
}
BuildPipeline.BuildAssetBundles(dst, BuildAssetBundleOptions.AppendHashToAssetBundleName | BuildAssetBundleOptions.ChunkBasedCompression | BuildAssetBundleOptions.None, BuildTarget.WebGL);
}
打包bundle时,请使用如下参数
- 【重要】BuildAssetBundleOptions.AppendHashToAssetBundleName:bundle带上hash。在小游戏底层对bundle做缓存及缓存淘汰时,hash是重要依据。
- BuildAssetBundleOptions.ChunkBasedCompression:LZ4压缩方式,加载速度和包体大小更均衡。
从服务器下载bundle的方式主要以下四种。 注意:WWW和WWW.LoadFromCacheOrDownload已不被Unity推荐使用
-
UnityWebRequestAssetBundle.GetAssetBundle
UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(uriPath); yield return request.SendWebRequest(); if (request.isHttpError) { Debug.LogError(GetType() + "/ERROR/" + request.error); } else { AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle; // ab.LoadAsset ab.Unload(false); } request.Dispose();
-
UnityWebRequest
UnityWebRequest www = new UnityWebRequest(uriPath); DownloadHandlerAssetBundle handler = new DownloadHandlerAssetBundle(www.uri.ToString(), 0); www.downloadHandler = handler; yield return www.Send(); if (www.isHttpError) { Debug.LogError(GetType() + "/ERROR/" + www.error); } else { AssetBundle ab = handler.assetBundle // ab.LoadAsset ab.Unload(false); } www.Dispose();
-
WWW www = WWW.LoadFromCacheOrDownload(uriPath, 2); yield return www; if (www.error != null) { Debug.Log(www.error); yield break; } AssetBundle ab = www.assetBundle; // ab.LoadAsset ab.Unload(false); www.Dispose();
-
WWW
WWW www = new WWW(uriPath); yield return www; if (www.error != null) { Debug.Log(www.error); yield break; } AssetBundle ab = www.assetBundle; ab.Unload(false); www.Dispose();
界面如下
按钮从上往下加载方式分别为使用UnityWebRequestAssetBundle.GetAssetBundle
, UnityWebRequest
, WWW.LoadFromCacheOrDownload
, WWW
。
下载完毕后,加载bundle内资源可使用AssetBundle.LoadAsset
代码示意如下
StartCoroutine(UnityWebRequestLoad(string.Format("http://127.0.0.1:8080/StreamingAssets/AssetBundles/{0}", bundleName), (ab) => {
Sprite img = ab.LoadAsset<Sprite>("deer");
image.GetComponent<SpriteRenderer>().sprite = img;
ab1 = ab;
img1Loaded = true;
}));
小游戏因其平台特殊性,需要保证加载速度,因此我们在底层对bundle文件做了缓存,开发者无须自己实现缓存。
游戏逻辑还是按照未缓存需要从网络下载去编写,插件底层会判断是否已有缓存。若未缓存则缓存此bundle;若已缓存,则返回缓存文件,实际不会发起网络请求。
可参见资源缓存与淘汰
加载的bundle文件大小为5403162字节
-rw-r--r-- 1 Users 5403162 6 22 16:07 image1_751427a66d22b184c95342d556354150
通过加载前后snapshot来对比总内存变化
-
UnityWebRequestAssetBundle.GetAssetBundle/UnityWebRequest/WWW 这三种加载方式加载前后内存无变化
-
WWW.LoadFromCacheOrDownload 加载bundle后内存增加了5403162字节,增加了bundle大小的内存,是因为WWW.LoadFromCacheOrDownload除了会将文件存入IndexDB外,还会存入内存中的UnityCache
因此需要注意业务中不要使用已淘汰的WWW类,尤其WWW.LoadFromCacheOrDownload,当bundle数量多时,会浪费不少内存。
- Introduction to Asset Bundles https://learn.unity.com/tutorial/introduction-to-asset-bundles#6028bab6edbc2a750bf5b8a7
- Unity WebGL Memory Optimization: Part Deux https://blog.kongregate.com/unity-webgl-memory-optimization-part-deux/
- Understanding Memory in Unity WebGL https://blog.unity.com/technology/understanding-memory-in-unity-webgl
- AssetBundle API https://docs.unity3d.com/2019.4/Documentation/ScriptReference/AssetBundle.html