Wwise SDK 2018.1.11
关于降低内存占用的技巧

削减内存池大小来满足内存限定的需求可能会非常不容易。以下是帮助降低内存占用的几个技巧:

Deafult 池的内存

Default 池的内存直接受到内存中加载的声音和事件数量(而非媒体,仅结构)以及游戏对象数量的影响。它包含工程中用于实现声音设计的行为所必需的对象的所有属性。它还包含所有游戏对象及其相关信息(游戏同步器值、位置、朝向等)。加载的 SoundBank 越多,此池就需要越大。所需的大小完全取决于在一个场景、关卡、地图、游戏区域等中可能播放的声音数量。以下经验做法有助于降低内存需求:

  • 将装有大量声音结构和事件的大型 SoundBank 分割成小型 SoundBank。作为参照指南,您可以检查 Advanced Profiler 的 SoundBank 选项卡,在 Default Pool 列中查看各个 SoundBank 占用了默认池的多大内存。然后您可以根据需要动态地加载和卸载 SoundBank。要做策略性地来考虑如何划分 SoundBank。例如,在划分对白 SoundBank 时,要避免创建的 SoundBank 中只包含属于单个角色的对白。相反,应根据环境将对白分组。
  • 使用 AK::SoundEngine::ExecuteActionOnEvent API 来减少事件的数量。Play/Stop(播放/停止)这对事件可以替换成一个播放事件外加调用一次 ExecuteActionOnEvent API 来执行 Stop 动作;Pause/Resume(暂停/续播)也可以用和 Play 事件相同的手法来处理。
  • 严格地管理 Game Object。它们的任务一旦完成,则应立即注销它们。避免保留大量未使用的游戏对象而不注销;这样做毫无益处,只会消耗内存。例如,假想有一个 NPC(非玩家角色)死了,则应注销它的 Game Object;不要将它复用于其他角色。需要时再注册一个全新的角色。一般来说,如果您有数千个游戏对象在活动,则这样的数量实在是太多了。
  • 不要只使用 Actor-Mixer 来组织声音。文件夹和 Work Unit(工作单元)不会占用内存,但 Actor-Mixer(角色混音器)会。除非您想让多个对象共享相似的属性值,且这些值不是默认的属性值,否则仅仅为了编组对象而使用 Actor-Mixer 将浪费内存。当然,这还取决于是否有事件引用 Actor-Mixer(例如通过 SetVolume或 SetPitch 动作)。
  • 尽量降低大型层级结构的大小和复杂性。大型层级结构的常见例子有表现“撞击”或“脚步”的层级结构。由于有大量的变量,因此层级结构可能会很大,并占用大量的内存来容纳结构。以下是减少此类层级结构的几种方法:
    • 如果采用 Switch 切换造成的唯一变化是一个简单属性(样本素材相同,只是音量/音高/随机化器等不同),则应换用 RTPC。
    • 将 Switch Container 层级结构分到多个 SoundBank中去。在 SoundBank Manager 中,当您包含某个 Switch Container 时,还会包含它的所有子分支。然而,您可以在 SoundBank Editor 视图中的 Game Sync 选项卡或 Edit 选项卡中手动排除某些分支。例如,在“脚步”层级结构中,第一个 Switch 变量可以是 Surface Type(地表类型)。然后您可以把多个 Switch 分散放在不同的 SoundBank 中,并根据环境加载这些 SoundBank。您可以创建一个主要的“脚步” SoundBank,让它包含在整个游戏中将遇到的地表类型(城市环境中的混凝土和金属台阶),再创建其它环境相关的 SoundBank 用来装特定的地表类型,例如仅在游戏某一个场景/部分中使用的泥土地。
  • 对于不太需要用 Wwise 的 Actor-Mixer 层级结构来控制的声音,可以使用“External Source”来减少声音的开销。这通常适用于语音素材。

底层引擎内存池

Lower Engine Pool 中的内存用于播放声音。它包含用于解压缩、应用效果器和对音频源做混音的缓冲区。它直接受到同时播放的声音数量的影响。它还受到同时使用的效果器数量和类型的影响。为了节省内存,您需要考虑想同时听到多少声音。某些游戏中很少有超过10种声音的场景,而别的游戏的场景中则可能有数百个声音。您需要考虑最坏的情况。

作为参照指南,我们对一些游戏执行了性能分析(在Xbox One 上),并获得了以下数据:

  • 1 MB 可让您播放大约 42 个声部
  • 2 MB可让您播放大约 96 个声部 虽然这个性能指标几乎是按线性来伸缩的,但真正还取决于使用的编解码器、效果器数量和其他一些因素。例如,使用 Vorbis 编解码器时,根据质量设置,各个声部将多占用大约 50% 的内存。假想同时播放 170 个声音:这样做可能很难让人听清楚各个声音,因此是无用的。然而,需要实验一下才能为您的游戏找到理想数量的声部。使用性能分析器的 Memory 选项卡,对游戏中的多个场景进行性能分析,并记下资源中使用了多少内存。

为了减少底层引擎池中使用的内存,您需要减少同时播放的声部数量。通过以下方式可以做到这一点:

  • Playback Limits(Advanced Settings),高级设置中的播放限制。例如,您真的需要听到 50 种子弹飞啸声吗?如果不是,则可将这些声音的个数限制在例如 15 个以内。
    Note: 您还可以对总线也设置限制。
  • Priority(Advanced Settings),高级设置中的优先级。例如,子弹可能没有对白重要。这意味着如果声音太多,首先被踢出的应该是子弹。将优先级与播放限制结合使用。
  • 基于距离的优先级偏置 (Advanced Settings)。距离远的对象通常没有距离近的对象重要。再以子弹为例,如果有 15 个子弹声音距离小于 10 米,则我们不需要听到 10 米以外的子弹声。
  • 内存阈值(代码)。这里有一个被称为内存阈值的功能。在初始化声音引擎池时,您可以指定一个内存池大小比例,内存池占用超过这个比例后将开始根据优先级来终止声部。这将为内存加上一个硬性限制,几乎所有"Out of Memory"(内存不足)的状况都可以用这种可控的方式来避免。注意,由于存在碎片,内存永远都无法被全部使用。较好的初始值为 0.9(90)。
  • Below Threshold Behavior(高级设置)。性能最优的选择(针对 CPU 和内存而言)是“Kill Voice”,这对非循环的声音非常有用。性能上的次优选择是“Send To Virtual”“Play from beginning”,再次是“Send To Virtual”“Resume”,最后是“Send To Virtual”“Play from elapsed time”。“Continue to play”和“Play from elapsed time”是性能上最昂贵的选择,Wwise 的默认值是“Continue To Play”。
  • Volume Threshold(Project Settings),工程设置中的音量阈值。这有助于终结声音太小而听不清的声音。此选项结合 Below Threshold Behavior 和 Attenuation 设置(离得越远通常意味着越听不清)一起使用。
    Note: 您可以在运行时以编程的方式更改音量阈值。您可以在游戏中 CPU 运算更繁重的位置使用此设置,以将更多的声部发送到“低于音量阈值”的状态。
  • 更改已经使用的编解码设置(Conversion Settings)。Vorbis 需要额外的内存来解压缩音频。不同的参数可以提高或降低内存需求量。然而,请认真权衡:使用不同的编解码器或较小的压缩比可减轻底层引擎内存池的内存负担,但代价是如果它们以 SoundBank 的形式加载,则将因加载了更大的数据文件而消耗更多的内存。在某些情况下,最好为此池多分配 500 KB 空间,以节省数 MB 的音频数据空间,并因此降低总体音频预算。
  • 更小或更低的品质。某些效果器运算需要大量的内存。一个常见的内存消耗大户是混响效果器,无论采用什么类型的混响,都会消耗大量的内存。实际上,您的游戏不应有很多并发运行的混响。我们一般建议少于 4 个。另外降低混响的品质或长度也会有用。

媒体内存( SoundBank )

SoundBank 占用的内存量几乎都取决于 SoundBank 中的声音数据。控制媒体所占用的内存量可通过以下方式来做到:

  • 将装有大量声音结构和事件的大型 SoundBank 分割成小一些的 SoundBank。根据需要动态加载和卸载。
  • 让更多声音采用从磁盘中流播放(通过声音属性来指定)。对延迟敏感的声音可使用可采用预读媒体来预先加载,或者使用 PinEventInStreamCache API 来按需流到缓存中去。
  • 使用 PrepareEvent() API。
  • 提高对音频的压缩(通过 Conversion Settings、编解码器等)。
  • 使用更低的采样率。另请查看 Conversion Settings 中的 Automatic Sample Rate(自动采样率检测)功能。
  • 将撞击类型的声音替换成等效的 SoundSeed Impact 插件。非常适用于将 Random Container 替换成它里面的多个版本。
    Note: 有时候非撞击类型的声音也可以获得可以接受的结果。
  • 将风声类型的声音替换成 SoundSeed Wind/Woosh 插件产生的等效声音。风声往往有较长的循环,可能会占用大量的媒体空间。锋刃的嗖嗖声、螺旋桨声、风通过打开的车窗刮起的呼呼声、通风噪声等都可使用此插件建模。另外也可以考虑非风声应用:可为任何嘈杂的声音建模。示例: 海浪的声音和远处高速公路上传来的声音。