此页面描述了 AssetBundles 中支持的压缩一种减少数据存储空间的方法。请参阅纹理压缩、动画压缩、音频压缩、构建压缩。
请参阅术语表选项,以及这对内置 AssetBundle 缓存支持的影响。
AssetBundle 文件是一种存档格式,它包含一个小的头部数据结构,后跟一个包含其虚拟文件的內容部分。头部部分永远不会被压缩,而內容部分可以选择性地进行压缩。默认情况下,Unity 使用全文件压缩 (LZMA) 压缩內容部分,并使用分块压缩 (LZ4) 缓存 AssetBundles。
当使用LZMA
压缩时,AssetBundle 文件的整个內容部分将作为一个流进行压缩。这种全內容方法产生的文件大小比分块压缩的文件大小更小。这是从内容交付网络 (CDN) 下载的 AssetBundles 的首选格式。缺点是您必须将整个文件解压缩到 RAM 中才能读取这些存档中的资源。当 AssetBundle 包含的资源使得使用其中一个资源就意味着所有资源都将被加载时,这将是最佳选择。打包角色或场景场景包含游戏中的环境和菜单。可以将每个唯一的场景文件视为一个唯一的关卡。在每个场景中,您可以放置环境、障碍物和装饰,本质上是分段设计和构建游戏。 更多信息
请参阅术语表的所有资源是一些可能使用此格式的示例。这是在不指定特定压缩的情况下(例如BuildAssetBundleOptions.None
)调用BuildPipeline.BuildAssetBundles
时使用的格式。
AssetBundles 也可以以完全未压缩的方式构建。未压缩的缺点是文件下载大小更大,因为某些类型的內容在 AssetBundle 内部可以高度压缩。但是,下载后的加载时间可能会快得多,因为不需要进行解压缩。当仅从较大的 AssetBundle 中加载少数对象时,这尤其有用。未压缩的 AssetBundles 是 16 字节对齐的。此格式可以通过在调用 BuildPipeline.BuildAssetBundles 时指定标志BuildAssetBundleOptions.UncompressedAssetBundle
来使用。
LZ4
使用一种基于分块的算法,允许 AssetBundle 分块或“分段”解压缩。在写入 AssetBundle 时,每个 128KB 的內容块在保存之前都会被压缩。由于每个块都是单独压缩的,因此总体文件大小大于使用 LZMA 压缩的 AssetBundles。但是,这种方法使得可以有选择地检索和加载请求对象所需的块,而不是解压缩整个 AssetBundle。LZ4 的加载时间与未压缩的捆绑包相当,并且具有磁盘占用空间减少的额外优势。这是 AssetBundle 缓存(如下所述)的首选格式,对于作为安装的一部分或在大小不是首要考虑因素的其他情况下分发的 AssetBundles 来说,它也是一个不错的选择。此格式可以通过在调用 BuildPipeline.BuildAssetBundles 时指定标志BuildAssetBundleOptions.ChunkBasedCompression
来使用。
由于不同的数据压缩会产生不同程度的大小节省,因此尝试使用每个受支持的选项重新构建项目并测量实际的大小差异可能是有意义的。结果可以帮助指导有关使用哪种格式的决策。
如果您使用自定义缓存解决方案下载和存储数据,则可以使用AssetBundle.RecompressAssetBundleAsync更改压缩,例如在下载后将 LZMA 格式的 AssetBundles 转换为未压缩或 LZ4 格式。
注意:Web 平台不支持 AssetBundles 的 LZMA 压缩。对于 Web 平台,请使用 LZ4 压缩 AssetBundles。有关更多信息,请参阅Web 中的 AssetBundles。
当 AssetBundles 从 Web 服务下载时,您需要考虑缓存,以便设备不必每次播放器运行时都下载相同的內容。由于 AssetBundles 可能会重建,因此拥有一个用更新版本替换本地缓存的 AssetBundle 的机制也很重要。
Unity 提供了一个基于磁盘的内置缓存来存储通过UnityWebRequestAssetBundle下载的 AssetBundles。要启用缓存,您必须在调用UnityWebRequestAssetBundle.GetAssetBundle
时指定版本整数或版本哈希参数。默认情况下,添加到磁盘缓存的任何 AssetBundle 都将转换为 LZ4 压缩。因此,最初下载和加载 LZMA AssetBundles 需要更长的时间,因为会发生重新压缩,但后续加载将使用缓存版本并快速运行。如果Caching.compressionEnabled为 false,则 Unity 将 AssetBundles 以未压缩格式写入磁盘缓存。
通过互联网下载 AssetBundles 时,务必采取措施确保不会将损坏或篡改的文件內容接受到缓存中。您应该在调用UnityWebRequestAssetBundle.GetAssetBundle
时指定预期的 CRC,以便 Unity 可以将此值与下载的內容进行比较,同时将其添加到缓存中。CRC 检查可以在将 LZMA AssetBundles 转换为 LZ4 的过程中以较低的成本执行。一旦经过验证的文件到达缓存,就不需要再次重复 CRC 检查。另请参阅AssetBundle 下载完整性和安全性。
Caching类可用于管理内置的 AssetBundle 缓存,例如清除其內容或检查 AssetBundle 是否已缓存。
出于性能考虑,Unity 在加载基于分块或未压缩的 AssetBundle 时会在内存中保留一些未压缩的数据。但是,此缓存的大小是固定的,无论底层 AssetBundle 文件有多大。
要加载 AssetBundle,Unity 需要随机访问其內容,无论是通过磁盘上的文件、内存中的文件还是 C# FileStream。它还需要 AssetBundle 未压缩或使用基于分块的压缩 (LZ4)。为了建立可加载的 AssetBundle,Unity 有时需要创建一个临时的内存中 AssetBundle。这并不总是坏事,因为 AssetBundle 內容一旦在内存中就可以快速加载。但在许多情况下,最好尝试将文件表示在磁盘上,作为本地 AssetBundle 或缓存下载,以便最大程度地减少 RAM 使用量,并且即时压缩转换不会减慢加载时间。
将在以下情况下创建临时的内存中 AssetBundles
当所有读取完成后并调用 AssetBundle.Unload 时,将释放临时文件使用的内存。
注意:在支持基于磁盘的 AssetBundle 缓存的平台上,Caching.compressionEnabled设置将影响用于临时内存中 AssetBundles 的格式。默认情况下,它是 true,并且内存中 AssetBundles 使用 LZ4。当 Caching.compressionEnabled 为 false 时,这些内存中文件将未压缩,因此可能占用大量 RAM。在不支持缓存的平台上,内存中格式始终为 LZ4。如果输入是其他格式,则会执行即时转换,这可能会增加加载时间。
注意:在调用 AssetBundle.LoadFromFile、AssetBundle.LoadFromFileAsync、AssetBundle.LoadFromStream 或 AssetBundle.LoadFromStreamAsync 以读取基于分块的文件时执行 CRC 检查将强制完全读取和解压缩文件的每个块。此计算逐块进行,而不是将整个文件加载到 RAM 中,因此这不是内存问题,但它可能会减慢加载时间。对于 LZMA 格式的 AssetBundle,执行 CRC 检查没有明显的额外成本,因为加载它始终会读取和解压缩所有內容。
内存分析器一个帮助您优化游戏的窗口。它显示在游戏各个领域花费了多少时间。例如,它可以报告渲染、动画或游戏逻辑中花费的时间百分比。 更多信息
请参阅术语表工具(例如内存分析器软件包)可以用于检查加载的 AssetBundles 使用了多少内存。