使用 AssetBundle 进行资源按需加载
一、AssetBundle使用
注意:小游戏环境不支持assetbundle本地加载
1.1 AssetBundle打包参数建议
public static void Build()
{
string dst = Application.streamingAssetsPath + "/AssetBundles";
if (!Directory.Exists(dst))
{
Directory.CreateDirectory(dst);
}
BuildPipeline.BuildAssetBundles(dst, BuildAssetBundleOptions.AppendHashToAssetBundleName | BuildAssetBundleOptions.ChunkBasedCompression | UnityEditor.BuildAssetBundleOptions.DisableWriteTypeTree | BuildAssetBundleOptions.None, BuildTarget.WebGL);
}打包bundle时,请使用如下参数
BuildAssetBundleOptions.AppendHashToAssetBundleName:bundle带上hash。在小游戏底层对bundle做缓存及缓存淘汰时,hash是重要依据,请查阅小游戏资源缓存
BuildAssetBundleOptions.ChunkBasedCompression:LZ4压缩方式,加载速度和包体大小更均衡。
如非需要新老Unity引擎版本兼容,请使用DisableWriteTypeTree提升加载速度与降低内存。
1.2 AssetBundle下载
从服务器下载bundle的方式主要以下两种:
- 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.LoadFromCacheOrDownload或WWW等带cache接口,WebGL模式下将会使用JS模拟文件系统带来额外内存消耗!
二、小游戏与APP的AssetBundle缓存更新流程差异
小游戏因其平台特殊性,需要保证加载速度,因此我们在底层对bundle文件做了缓存,开发者无须自己实现缓存。
游戏逻辑还是按照未缓存需要从网络下载去编写,插件底层会判断是否已有缓存。若未缓存则缓存此bundle;若已缓存,则返回缓存文件,实际不会发起网络请求。
可参见资源缓存与淘汰
资源缓存与更新的不同,会导致APP与小游戏不同的加载流程
常见APP AssetBundle使用方式: 检查更新-->下载更新全量资源-->写入文件系统-->运行时LoadFromFile
在业务侧看来:总是使用异步接口从远程下载并使用,底层资源的缓存与更新已由适配层自动完成,游戏不再直接读写文件系统。
三、AssetBundle内存分析
3.1 切勿使用带Cache能力的线管接口
加载的bundle文件大小为5403162字节
UnityWebRequestAssetBundle.GetAssetBundle/UnityWebRequest/WWW 这三种加载方式加载前后内存无变化
需要注意业务中不要使用已淘汰的WWW类,尤其WWW.LoadFromCacheOrDownload,当bundle数量多时,会浪费不少内存。
3.2 尽可能使用Unload
当bundle从资源服务器下载并使用,会经历多次内存分配: 浏览器HTTP对象-->拷贝到WASM临时内存-->Unity ab内存文件(略大于ab本身体积, 相对于APP常用的LoadFromFile,WebGL这部分开销是额外的)
当HTTP对象dispose之后,Unity ab内存文件
当ab.Unload时,Unity ab内存文件释放
因此,最佳实践是业务应该尽可能早地使用ab.Unload(false),自行维护Asset的引用计数管理资源。
