版本
在学习如何在 Wwise 中创建、填充和生成 SoundBank 之前,要先了解游戏加载和管理 SoundBank 信息的不同方式。最佳方式取决于各种不同的因素,包括开发的游戏类型、运行游戏的平台以及项目团队设定的限制。
为了提高灵活性和满足几乎所有游戏类型的需求,Wwise 提供了多种将音频和振动加载到游戏中的方法,包括以下几种:
加载 SoundBank 的传统方法使用同时包含事件数据、对象结构数据和媒体的 SoundBank。这些 SoundBank 的全部内容在游戏的特定时刻加载和卸载,确保事件数据和相关媒体在被触发时就可以播放。
下图演示在游戏中使用传统方法创建的 SoundBank 如何在玩家从 1 级升级到 2 级时加载到平台内存和从平台内存中卸载。
由于特定 SoundBank 的所有数据和媒体同时加载到内存中,因此这种方法不仅确保所有数据和媒体可以在需要时播放,而且在游戏中需要执行极少的磁盘寻址,从而将磁盘腾出来执行对磁盘需求较大的其它任务。
此方法的主要缺点是在 SoundBank 的整个加载期间将占用大量的内存,使您无法灵活地处理复杂的大型游戏。此方法还显式加载 SoundBank 中的所有内容,而不验证媒体文件是否已经加载到内存。这可能会导致同一媒体文件被多次加载到内存中。尽管此传统方法有上述缺点,但是在许多情况下仍非常有用。例如,用于所有数据和媒体必须随时可用的经典弹珠游戏。
为了克服 LoadBank() 机制的一些缺点,您可以先采用 Prepare 操作来"预备" SoundBank 而不是使用 AkBankContent_All() 加载它们(译注:为了突出 Prepare 是一种 API 调用,文档尽量用英语原文来代表这种预备操作,而不做通篇翻译)。在使用此方法时,SoundBank(音频包)仍可包含所有内容类型(Event、结构数据和媒体文件);不过,此方法不会立即加载媒体文件,而是借助 PrepareEvent() 机制将所有媒体加载到内存中。通过使用此机制加载媒体,Wwise 首先查看媒体文件是否已经存在内存中,然后再加载它。这可以避免内存中出现媒体文件重复,从而将内存占用保持在最低水平。
除了可以节省内存外,此方法还可以保证顺序访问磁盘,这将避免在使用 PrepareEvent() 中一次 Prepare 一个 Event 时可能发生的随机磁盘寻址。
下图演示了"Prepare Bank(All Content)"(预备 SoundBank(全部内容))机制如何将元数据和内容加载到平台内存中。
在加载包含 Vorbis 编码或 WEM Opus 编码媒体的 SoundBank 时,可利用 Preparation_LoadAndDecode 预备类型将这些媒体文件解码为非压缩 PCM 文件。这会使 SoundBank 体积变大,但当事件调用媒体文件时,将立即播放而无需进行解码。
PrepareEvent() 方法只有在绝对需要时才会动态加载媒体。使用此方法时,动作事件元数据必须位于 SoundBank 中,相关媒体文件必须位于文件系统中可访问的位置。相应结构元数据可包含于事件所在的同一 SoundBank 中,也可包含于单独的 SoundBank 中。在使用此方法时,包含动作事件元数据的 SoundBank 使用 LoadBank() 加载并保留在内存中。在动作事件被游戏调用前,声音引擎先 Prepare(预备)这些事件。Prepare 事件时将从文件系统中加载所有被引用的媒体文件,如果所有被引用的结构元数据尚未加载,则还将从 SoundBank 中加载这些结构元数据。当动作事件不再需要时,可将它 Unprepare(解除预备),相应媒体文件于是将从内存中被清除掉。为了将内存占用保持在最低水平并避免内存中出现媒体文件重复,Wwise 在加载媒体文件前会先确认它不存在于内存中。
备注 | |
---|---|
只有动作 Event 可事先 Prepare。"PrepareEvent()"方法不适用于对话事件。 |
下图说明如何事先 Preapre Event,以便只将必需的媒体文件加载到内存中。
当元数据(又称结构)未存储在 Event 所在的同一 SoundBank 时,Wwise 需要一种方法来找到位于另一 SoundBank 中的相应数据。为此,Wwise 加入了对其它 SoundBanks 中存储的相应内容的引用。Wwise 可以使用名称或 ID 来引用其它 SoundBank。若要在声音引擎中使用 SoundBank 名称,则须在 Project Settings(工程设置)对话框的 SoundBanks(音频包)选项卡中选中 Use SoundBank Names(使用音频包名称)选项。要使用 ID,则取消勾选该选项。要了解详细信息,请参阅“SoundBanks 选项卡”一节。
被 SoundBank 引用的媒体必须作为松散文件存储在磁盘中,否则必须能够被底层 IO(Low-Level IO)解析(例如在 File Package 中)。
此方法在内存利用方面总体来说非常高效,但需要额外执行磁盘寻址。在已经通过磁盘流传输大量文件时,这种方法可能不太合适。另外,在游戏使用了 State 和 Switch 的情况下,不需要的媒体文件可能会被白白加载到内存中。例如,您针对游戏中人群的不同情绪或能量级别设置了不同的人群声音,如果游戏的特定区域中只有“愤怒“ Switch 声音有效时,则所有级别的人群声还是都会被加载到内存中来,而这样您是不会愿意的。为了克服这一问题,您还可以 Prepare 特定的 State 或 Switch,只加载与 Prepare 的 State 或 Switch 相关的媒体文件。
下图显示了如何提前 Prepare Switch,以进一步限制在游戏任何特定时刻加载到内存中的媒体量。
虽然提前 Prepare Game Sync 可以优化内存占用,但注意,这也会降低媒体加载到内存中的速度。读取时间延长是因为声音引擎需要搜索磁盘,以查找与 Prepare 的 Game Sync 相对应的声音。
通过动态地只加载必需的音频文件,第二种方法可以为您处理以下情况提供更大的灵活性:处理具有大量声音的超大区域或关卡,或者以非常有限的内存量来存储事件数据、结构数据和媒体。
您可以看到,每种方法各有长短。最佳方式取决于游戏的特定场景、要求和限制。在确定策略后(使用一种方法还是同时使用多种方法),您可以开始相应地填充和优化您的 SoundBank。
备注 | |
---|---|
LoadBank、AkBankContent_All、PrepareEvent、PrepareGameSyncs 和 AkBankContent_StructureOnly 函数均可通过 Wwise API 访问。有关加载 SoundBank 和 Prepare 事件或 Game Sync 的详细信息,请参阅 Wwise SDK 的《集成 SoundBanks》一节。 |
有关可用于管理 SoundBank 的不同方法的详细概述,请参阅“SoundBank 管理策略”一节。