此方法适用于以下情形:
游戏拥有大量驻留内存的媒体素材。
声音设计师很难事先预测媒体需求。
工程使用切换开关和状态来确定将为特定 Event 播放的声音或振动对象。
声音不易于划分成多个确定的部分。
有的游戏非常复杂,可能要按多种因素来触发声音,这些因素包括游戏纹理、时辰、游戏对象的运动,在多人在线游戏中,还可能包括其它玩家的操作。 例如在基于 Event 或对象的环境中,声音可以根据其它一些游戏对象的距离加载到内存中。 各个游戏对象都可能有一列 SoundBanks 必须加载,要么因为这些 SoundBank 对应的声源处于一个给定距离范围内,要么仅仅因为按规则只要这些声音存在就必须使用。
另外,切换开关和状态可以确定播放对象。当将播放这些对象的 Event 添加到 SoundBank 时,所有可能用到的媒体也会自动添加到 SoundBank。例如,您可能有一个被称为“Play_Footstep”的 Event。此 Event 将根据地面的当前纹理播放相应的声音,当前纹理通过更改切换开关来指定。虽然这种方法效果非常好,但是当游戏场景发生在伦敦的一座建筑内时,如果在内存中将声音“footstep_sand.wav”或“footstep_winter.wav”保持随时就绪状态是对内存的一种浪费。
在此情况下,为了避免浪费内存,您可以将 Event 或对象结构添加到 SoundBank,然后指定 SoundBank 中将要包含的相应对象。例如,让我们对不同的纹理使用不同的脚步声。<XXXX CSOFT xxxxx>在此情况下,我们可以创建以下 SoundBank:
“EventBank”,其中包含“Play_Footstep”Event 和结构。
“Winter_Footstep_bank”,其中包含仅在游戏某个部分(冬天)发生的脚步声所对应的媒体。
“Desert_Footstep_bank”,其中包含仅在游戏某个部分(沙漠)发生的脚步声所对应的媒体。
“Common_Footstep_bank”,其中包含可在任何地方(木材、混凝土等)发生的脚步声所对应的媒体。
假设游戏中有三种不同的纹理(雪地、沙地和混凝土地)。在 Wwise 中,有一个切换容器根据切换开关“ground_texture”播放三个随机容器中的一个。三个随机容器中的每一个在给定纹理上均有四种脚步声版本。
在 Wwise 中创建用于微管理媒体的 SoundBank 的方法是:
创建名为“EventBank”的 SoundBank,然后将它加载到 SoundBank Editor。
将“Play_Footstep”Event 拖入 SoundBank Editor 的“Add”选项卡。
取消选择此 Event 的“Media”复选框,但保持选中 Events 和 Structures 复选框。
创建其它三个 SoundBank,每个纹理各一个。
在各个 SoundBank 中,拖动与此纹理相关的随机容器。
备注 | |
---|---|
如果不拖放随机容器,则分别拖放各个声音也同样有效。但是使用容器的优势是,当容器的内容改变时,容器中的所有声音将自动添加到 SoundBank 中,无需手动完成所有更改。 |
取消选择三个纹理 SoundBank 中的每一个所对应的“Event”和“Structure”复选框,仅保持选中 Media 类型。
生成 SoundBank,并将生成的 SoundBank 文件夹复制到游戏应用程序。
此时,我们有四个 SoundBank,一个包含与待播放的音频相关的 Event 和结构数据,另外三个仅包含与特定地面纹理相关的媒体。
使用微管理策略将 SoundBank 集成到游戏中的方法是:
在游戏开始时加载通用 SoundBank,然后在需要时加载其它 SoundBank。例如,游戏可以在开始时加载 Event SoundBank 和通用脚步声 SoundBank,然后根据玩家在游戏中的具体位置加载其它 SoundBank。
以下代码示例可以让您了解到在游戏中如何加载这些 SoundBank。
// 加载初始化库和 Eventbank。 AkBankID bankID; // 本例中没有使用。 AKRESULT eResult = AK::SoundEngine::LoadBank( L"Init.bnk", AK_DEFAUlT_POOL_ID, bankID ); if( eResult == AK_Success ) { eResult = AK::SoundEngine::LoadBank( L"Eventbank.bnk", AK_DEFAUlT_POOL_ID, bankID ); } if( eResult == AK_Success ) { eResult = AK::SoundEngine::LoadBank( L"Common_Footstep_bank.bnk", AK_DEFAULT_POOL_ID, bankID ); } ... // 在代码多处,可能取决于位置: eResult = AK::SoundEngine::LoadBank( L"Winter_Footstep_bank.bnk", AK_DEFAULT_POOL_ID, bankID ); ... eResult = AK::SoundEngine::LoadBank( L"Desert_Footstep_bank.bnk", AK_DEFAULT_POOL_ID, bankID ); ... eResult = AK::SoundEngine::LoadBank( L"Level_3.bnk", AK_DEFAULT_POOL_ID, bankID ); ... eResult = AK::SoundEngine::UnloadBank( L"Winter_Footstep_bank.bnk" ); ... eResult = AK::SoundEngine::UnloadBank( L"Desert_Footstep_bank.bnk" );
这个例子只是使用此技术可以完成的众多任务之一。由于可以按对象和 Event 逐一决定各个 SoundBank 包含的内容,因此您可以全面控制各个 SoundBank 的内容。虽然您可以为游戏中的每个对象创建单独的 SoundBank,但是这样维护起来会非常困难,因为在游戏中每个新音效和振动效果都需要新的代码才能正确加载 SoundBank。每款游戏应该尝试的目标是在粒度和游戏集成便利性之间找到良好的平衡。
备注 | |
---|---|
如果您对声音逐一加载方案感兴趣,则可 Prepare Event,而无需加载整个 SoundBank。有关做 Prepare Event 的详细信息,请参阅方法 4:Prepare 动作事件。 |
下表列出了微管理策略在管理媒体时的优缺点。
优点 |
缺点 |
---|---|
优化内存占用的最佳选择。 您可以充分控制在游戏任意时刻加载哪些媒体。 为您提供 SoundBank 向后兼容性,支持加载较大的媒体 SoundBank。 |
需要声音设计师和游戏程序员密切沟通,共同确定必须加载的 SoundBank 和加载的时机。 |