[Unity workflows] Unity Addressables:压缩方式的基准测试

11 篇文章 0 订阅
9 篇文章 0 订阅

英文原文:https://thegamedev.guru/unity-addressables/compression-benchmark/

  今天我将向您展示如何为您的资产包选择最佳的 Unity Addressable 压缩方法。

在这篇文章中,您将了解到:

  • 如何减少资产包大小
  • 如何减少向贪婪的 CDN 支付的费用
  • 您应该使用未压缩的、LZ4 还是 LZMA?

  因此,如果您想充分利用 Unity 可寻址资产,您会发现这篇文章很有用。

  让我们开始吧。

  前段时间,我的目标是优化我的游戏的内存使用。

  我的内容太多,无法放入 RAM。

  因此,自然而然的方法是可寻址路线。

  在投入大量精力学习该系统后,我得到了一个坚如磐石的系统并开始运行。 结果是减少了 50% 的内存使用量。 不错。

  但我只是勉强触及了 Addressables 的皮毛。 我错过了太多功能。

  所以我浏览了所有我能找到的可寻址设置。

  一个立即引起了我的注意:资产包压缩模式。

  有趣的是,这将被证明是有用的,我对自己说。

  在那里我清楚地看到了 Unity 给我的机会。 Unity 为我提供了一个强大的工具,我可以使用它来处理两个关键变量:存储大小和 CPU 性能。

  Unity 为您提供的三种压缩模式是:Uncompressed、LZ4 和 LZMA。

  我很好奇。 我真的很想看看每种模式在现实生活中有什么不同。

  然而,与此同时,我不停地问自己……关注这个真的值得我花时间吗?

  当然,Unity 方面缺少 Addressables 文档是可以预料的。 忙碌的开发者,忙碌的时代。 因此,正如 Addressables 经常发生的那样,我不能指望它们。

  但尽管投入了时间,但还是要达成协议:我决定让这项研究变得有价值。 我决定制定一个基准来了解 Unity 可寻址压缩模式在现实世界中的影响。

  今天我将与大家分享我的调查结果和我对这个问题的看法。

内容

  • 第 1 章:什么是可寻址对象?
  • 第 2 章:什么是可寻址压缩?
  • 第 3 章:基准可寻址压缩
    - 基准设置
    - 基准视频
    - 基准音频
    - 基准纹理
    - 基准文本
  • 第 4 章:结论

第 1 章:什么是可寻址对象?

  在 Unity 中使用资产的默认方式是使用直接引用您的内容。 直接引用会自动为您将所有资产加载到内存中。 这很舒服,但通常会导致内存消耗激增。 而且,我的朋友,我们想要战斗。

  Unity Addressables 是游戏开发者急需使用间接引用的一项技术。

  间接引用让您决定何时将内容加载到内存中和从内存中卸载。 这使您可以极大地控制内存。

  当我们使用 Addressables 时,我们的目标是优化内存使用。

  但这还不是全部。 优化内存有许多次要好处,例如减少加载时间、减少崩溃和更好的用户评论,即更多现金到您的口袋。

  通过可寻址,我们围绕资产组组织所有内容……

  可寻址组是以非常特定的方式包含我们资产的数据桶。

  在每家超市,你都会看到成吨的资产:(热)汽水、面包、多汁的水果等……这些资产的包装各不相同。 你不想把一些可乐倒进你放面包的纸袋里。 每种包装都非常适合某些类型的商品。

  嗯,可口可乐、芬达、水、面包、米饭是你的资产。 您将资产放入的不同包装就是您的组。 组决定了您存储和交付资产的方式,包括压缩设置(更松或更紧的纸板箱)。

如下所示,将资产分配给组很容易。

在这里插入图片描述

第 2 章:什么是可寻址压缩?

  您的游戏可能有成千上万的资产。 正如我们所见,不同的内容类型需要不同的包装(组)。

  压缩是组参数之一,它将决定 Unity 存储和加载资产的效率。

  您可以在以下压缩模式之间进行选择:

  • Uncompressed
  • LZ4
  • LZMA

接下来的问题是:如何在游戏中充分利用压缩?

  当您将资产分配给一个组时,您实际上是在将这些资产打包在一起,就像在一个 ZIP 文件中一样。

  您可能还记得使用 WinZIP 及其系列时,您有多个压缩设置。

  最强的压缩级别往往会保存更多的数据,但它们也会窃取更多的资源来压缩和解压缩。

  因此,您和我必须始终寻求在存储空间节省和性能成本之间取得平衡。

  就像使用 WinZIP 一样,您必须将相同的原则应用于 Unity 可寻址压缩设置。

  那么,您有哪些压缩模式?

Uncompressed 意味着:您按原样存储资产数据。 理论上,这不需要进一步处理,只需要 I/O 带宽。

LZ4 是您拥有的第二种压缩模式。 它不是一种超快的压缩算法,它的性能成本达到了很好的比率。 难怪这是新的可寻址组的默认设置。

但有时我们对我们的 Seat 不满意,而是想要一辆 Tesla。 无论成本如何,我们都愿意将大量现金投入到似乎更强大的替代方案中。 这就是 LZMA 为您服务的地方。

LZMA 是一种(理论上)更强大的 Unity 可寻址压缩算法。 使用 LZMA,我们可以通过将更多硬件投入到任务中来潜在地实现更高的压缩比。

  想知道在哪里可以找到这些压缩模式? 看看下面,这就是我通常设置视频组的方式。

在这里插入图片描述
  您可能知道,大多数视频已经使用 H264 进行了大量压缩。 所以一般来说你不必在它们之上重新应用压缩。

  但老实说,视频只是其中的一小部分。

  其余内容类型有什么问题?

  更重要的是……我想要数字!


第 3 章:基准可寻址压缩

  如果您正在阅读本文,可能是因为您想在未来做出明智的决定。

  我将在本章帮助你做到这一点……用数字。

  我花了一些时间来衡量可寻址组压缩级别对两个指标的影响:

  • 生成的资产包存储大小
  • 加载时间

  我用不同的内容类型和几种格式做了这个测试,以包含更多信息:

  • Textures: RGB32, ETC2, ASTC
  • Music: PCM, ADPC, Vorbis
  • Videos: H.264
  • Text: Epic Lorem Ipsum
基准测试设置

是时候得到一些有趣的数字了。 他们经常揭露真相

为了进行基准测试,我将公共领域资产导入到一个新的 Android Unity 项目中。

每个资产都将进入其自己的可寻址组,因此进入其自己的资产包。

为了更好地了解数字,我复制了资产以应用特定设置,例如不同的纹理压缩算法和资产包压缩模式。

请参阅下面我用于此基准的资产组合。

在这里插入图片描述

public class AddressablesGenericContentLoader : MonoBehaviour
{
    [SerializeField] private AssetReference[] assetReferences = null;
    private const float WaitTime = .1f;
    private float _lastTimeMs;
    private string _lastObjectName;
    
    private IEnumerator Start()
    {
        yield return Addressables.InitializeAsync();
        const int repetitions = 5;
        for (var i = 0; i < assetReferences.Length; i++)
        {
            var totalMs = 0f;
            for (var repetition = 0; repetition < repetitions; repetition++)
            {
                yield return new WaitForSeconds(WaitTime + 1f);
                yield return TestLoad<UnityEngine.Object>(assetReferences[i]);
                totalMs += _lastTimeMs;
            }
            Debug.Log($"[TheGamedevGuru] \"{_lastObjectName}\" {totalMs/repetitions}ms");
        }
        Debug.Log($"[TheGamedevGuru] Finished");
    }
    
    private IEnumerator TestLoad<TObject>(AssetReference assetReference)
        where TObject : UnityEngine.Object
    {
        GC.Collect();
        yield return Resources.UnloadUnusedAssets();
        var stopwatch = new Stopwatch();
        stopwatch.Start();
        var loadOperation = assetReference.LoadAssetAsync<TObject>();
        yield return loadOperation;
        stopwatch.Stop();
        _lastObjectName = loadOperation.Result.name;
        _lastTimeMs = stopwatch.ElapsedMilliseconds;
        yield return new WaitForSeconds(WaitTime);
        assetReference.ReleaseAsset();
    }
}

这就是我定义必须创建、存储和加载可寻址组(资产包)的方式。

  我执行基准测试的方法是创建一个脚本,按顺序加载我所有的可寻址资产。 该脚本测量将每个资产加载 15 次所花费的时间并计算平均值。 我使用可能是最准确的 C# API:StopWatch 进行了测量。

这是组件检查器及其代码的屏幕截图。

在这里插入图片描述
想知道它在我的 Mate 20 Pro 中的表现如何?

我想。

因此,让我们跳过这一行,开始对视频可寻址压缩进行测试。


基准测试视频

这是交易。

我有一个全高清 H.264 视频,我复制了它以获得 3 种组合。

第一组将没有应用于它的可寻址压缩。 第二个将使用 LZ4 压缩,第三个将使用 LZMA 压缩。

然后我构建了资产包,将基准部署到 Mate 20 Pro 中并获得了数字……

我不会再让你等了,那太残忍了。 这是你的结果。

在这里插入图片描述
你怎么看?

我认为在任何指标上都没有明显的赢家。

我显然希望存储大小不会随着进一步压缩而变化太大,因为 H.264 是一种高效的视频编解码器。 这就是我一直建议我的游戏性能学生关闭视频压缩的原因。

关于加载时间,正如人们所期望的那样,它会随着压缩而增加。 但是,在这件……硬件中,差异并不明显。

作为旁注,Unity 通过流媒体技术播放视频。 这意味着视频内容并没有完全加载到内存中,而只是一个小窗口。 我没有对此进行测试,但如果通过压缩资产包进行流式传输,我预计会支付更高的 CPU 成本。

基准测试音频

  音频变得更有趣。 为了显示更大的差异,我会选择更长的片段,例如音乐。

  在此基准测试中,我将测试 3×3 变体:vorbis/pcm/adpcm + uncompressed/LZ4/LZMA。 第一个压缩设置是您在 AudioClip 导入设置中设置的音频特定参数,它反映了要使用的音频编解码器。

  我将所有 AudioClip 设置为在加载时解压缩并同步加载。

事不宜迟,以下是供您欣赏的结果。

在这里插入图片描述
LZMA 在压缩比上与 PCM 和 ADPCM 有明显的优势。

但是,我在测试中没有看到加载时间有明显变化。

出于这个原因,如果您使用的是 PCM 或 ADPCM,我绝对可以建议您在项目中测试 LZMA。

基准测试纹理

对于纹理,我遵循了与音频相似的基准测试格式。

我克隆了纹理,这样我就可以应用不同的原生和可寻址压缩设置。

这种基准测试方法给了我 3×3 的组合:RGBA32/ETC2 8-bit/ASTC6x6 + Uncompressed/LZ4/LZMA。

这是结果。
在这里插入图片描述
看起来我们有一些美味的差异,你同意吗?

您可以看到未压缩纹理 (RGB32) 在存储和加载时间方面的最大差异。 如您所料,压缩最适合未压缩的内容。

对于未压缩的内容,Unity 可寻址压缩模式比激光直接指向您的眼睛更明亮。

LZMA 以稍微增加加载时间为代价将未压缩纹理的存储要求减半。 不错。

LZ4 以微不足道的成本做得很好……这总是受欢迎的。 谢谢LZ4。

使用 LZMA 获得的收益仍然存在于 ETC2 中,这很棒。 由于 ETC2 是一种基于块的压缩算法,文件本身仍然可以作为一个整体进行压缩,以获得显着的收益。

使用上一代压缩算法 ASTC,您仍然可以获得一些节省,但您开始看到收益递减。

对于纹理,我建议您明确选择 LZ4,除非您要使用 ASTC 等高效压缩模式。 在最后一种情况下,决定存储大小还是 CPU 时间对您来说更重要,然后选择它。

基准测试文本

我准备的最后一个测试是创建一个巨大的文本文件。

我通过超频在线 lorem ipsum 生成器来填充文件,该生成器使我的浏览器冻结了几分钟。

结果? 一个巨大的 30MB 文本文件,任何引擎都不敢加载。

哎呀,即使是 Visual Code 也不愿意加载它。

无论如何,这就是你得到的:

在这里插入图片描述
哎呀,你看到了吗?

老实说,我期待着巨大的胜利,但 LZMA 在这里的表现确实超出了我的预期。

那不是错字。 LZMA 将 30MB 减少到 23KB。

我不会在这里做推荐。


第 4 章:结论

我们做到了!

现在我们有一些有趣的数字来判断每种压缩方法的实用性。

让我们根据这些变量对三种压缩方法进行公平试验:

  • 存储空间
  • 加载时间
  • 内容导入设置本机压缩

如果您再次查看这些数字,您可能会发现一个规律。

原始内容压缩得越多,通过应用基于 Unity 可寻址的压缩获得的回报就越差。

也就是说,去 LZ4 不会有错。 这是一种非常快速的算法,可以为您在大多数内容类型上带来显着的节省。

所以这里是我总结我的建议的地方,我猜?

是的,让我们这样做:

  • 视频:未压缩
  • 纹理:LZMA 用于老一代格式,LZ4/LZMA 用于 ASTC 和更新版本
  • 音频:用于 PCM/ADPCM 的 LZMA,用于 Vorbis 的 uncompressed
  • 文字:LZMA
  • 混合内容(预制件、网格等):LZ4(用于 CPU 性能)或 LZMA(用于减少存储大小)

我鼓励您在您的项目中测试和衡量我的指南并分享您的发现。 我很好奇你的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值