抖音开放平台Logo
开发者文档
控制台

使用 TTAssetBundle 优化内存

收藏
我的收藏

内存问题​

在 Unity WebGL 小游戏环境中处理 AssetBundle 加载时,我们无法利用 App 游戏中常用的 AssetBundle.LoadFromFile() 等依赖本地文件系统的加载方式,而是需要使用 UnityWebRequest 等通过网络的加载接口。​
通过 UnityWebRequest 加载 AssetBundle 时,下载或从本地缓存中读入的 AssetBundle 文件会完整拷贝到 Unity Heap 内存,在 Unload 之前额外占用 Unity Heap。而由于 Unity Heap 一旦超额分配便无法从 JS Heap 中释放,将其控制在更小范围内有利于控制整体进程内存,降低崩溃率。​

解决方案​

TTAssetBundle 接口通过打通 Unity 内存文件系统和小游戏本地缓存文件系统接口,在加载 AssetBundle 时内部使用 LoadFromFile() 仅打开文件流,在 LoadAsset 时通过文件描述符按需读取 AssetBundle 的包内资源,可以节省与 AssetBundle 文件大小相当的内存。​

使用说明​

版本要求​

开发工具:​
    StarkSDK 5.52.10 及以上​
    StarkSDK Unity Tools 3.31.2 及以上​
    Unity 2021.3 及以上​
宿主:​
    抖音/抖音极速版 29.2.0 及以上,暂不支持头条、番茄。​
    不支持的版本/宿主上,会 fallback 为类似原本 UnityWebRequest 加载实现,仍可正常加载到资源。​

构建配置​

要通过 TTAssetBundle 加载的资源,其域名都必须配置在“缓存资源域名列表”中。这一配置是为了 AssetBundle 资源文件能够被正确存入小游戏文件缓存中,供相关接口后续按需读取。​

加载 AssetBundle​

加载 AssetBundle 代码示例:​
using StarkSDKSpace; UnityWebRequest request = TTAssetBundle.GetAssetBundle(url); yield return request.SendWebRequest(); if (request.result != UnityWebRequest.Result.Success) { Debug.Error(request.error); } else { AssetBundle ab = (request.downloadHandler as DownloadHandlerTTAssetBundle)?.assetBundle; ab.TTUnload(true); // 使用 TTAssetBundle 加载的资源,必须调用 TTUnload() 方法才可彻底卸载。 }

使用 Addressables​

如果项目使用 Addressables 管理资源,可以通过替换 Provider 以使用 TTAssetBundle。​
    1.引入适配的 Provider:​
    在 StarkSDK 目录下找到 TTAssetBundleProviders.cs.txt 文件(通常在 Assets/Plugins/ByteGame/com.bytedance.starksdk/WebGL/AssetBundle 目录下)。​
    将其拷贝到工程中,并更名为 TTAssetBundleProviders.cs(移除扩展名 txt)。​
    2.设置 Addressable Asset Group 的 Providers:​
    Asset Provider 设为 Assets from TTBundles Provider​
    AssetBundle Provider 设为 TTAssetBundle Provider​
    Use AssetBundle Cache 设为 False​
    3.重新导出 Addressables 资源、打包小游戏。​

注意事项​

    TTAssetBundle 主要能够节省 Unity Heap 内存的使用,而 Unity Heap 内存通常是预先分配的。建议开发者完成接入后,在打包工具中重新评估(适当降低) Unity Heap 预留内存大小,以取得更好的整体进程内存收益、降低崩溃率。推荐对内存有严格要求的中重度游戏接入使用。​
    加载过程中的 AssetBundle 文件会在 JavaScript 内存中保留一份完整的文件缓存以保证载入性能。内存文件缓存中的文件超过 5s 未被读取或缓存占用超出 128MB 上限时,将按 LRU 清理最久未被读取的 Bundle。被清理的 AssetBundle 下次读取时将重新从磁盘读入,建议开发者及时调用 TTUnload() 卸载不使用的 AssetBundle。自动清理的阈值支持在 StarkBuilderSettings 中配置。​
    Android Native 方案下也可以使用该接口,但内部会 fallback 为使用 AssetBundle.LoadFromMemory() 实现加载,没有任何内存和加载效率上的收益。开发者可以根据需要自行判断是否在 Native 方案下替换加载接口。​