Wwise SDK 2019.1.11
|
在决定如何管理游戏中的 SoundBank 之前,强烈建议您仔细阅读以下文档。
为了尽可能灵活满足广大游戏类型的需求,Wwise 引进了一种新方法来管理游戏中的 SoundBank。此新方法与传统方法并不抵触,只是更加可控和灵活,让您能更好地满足游戏的需求。
此新方法与现有传统方法相比有三项重大改进:
此新方法的主要优势是可以将媒体内容拆分到载入内存的多个 SoundBank 中去。 例如,假设整个游戏的音乐是用单一事件来启动的。在使用传统方法时,您将向 SoundBank 中添加一个事件,该事件会自动添加所有相应内存内声音和预读媒体,包括预读只在游戏结束时播放的歌曲。把整个游戏的全部媒体都存储到内存里似乎极其低效。而使用新方法则可以更好的管理内存,您可以把音乐媒体分到多个 SoundBank 中,只在可能需要播放声音时才加载相应声音。
通过把媒体分到多个 SoundBank 中,您还可以对要加载的媒体优先排序。例如,在内存有限的环境中,您只需要加载最重要的媒体。可以把非关键的媒体存储在单独的 SoundBank 中,只在空间够用时才载入内存。在传统方法中,关键的和非关键的媒体文件全都包含在同一个 SoundBank 中。如果 SoundBank 太大,无法载入内存,则里面的声音都不会播放,包括关键声音。
以下各节介绍可用于生成 SoundBank 并把 SoundBank 集成到游戏中的不同方法。您可以在同一款游戏中使用其中一种方法或者多种方法的组合。由于每款游戏各不相同,因此您选择的方法将取决于游戏的具体需要。
在创建 SoundBank 时您所做的选择会极大影响到音频素材管理所需的工作量,并且对游戏性能有直接影响。强烈建议声音设计师和程序员仔细阅读本文档,以便充分了解各种可能性。声音设计师和程序员应该携手找出满足游戏具体需求的策略。记住,所有解决方案都可行,但您在选择时应考虑到内存占用、I/O 以及集成到游戏中的便利度。每种方法各有长短,因此主要问题是平衡内存占用和集成便利度的问题。
使用此方法时,所有事件内容、声音结构数据和媒体文件全部存储在一个 SoundBank 中,一次性载入内存。
适用此方法的情况如下:
当然,大多数游戏的内存很紧张,但此方法的主要优点是使用和维护都非常简单。采用此方法的主要理由是用极少的时间就能把整个 Wwise 工程集成到游戏中去。
操作方法:
在 Wwise 中
备注: 默认情况下,Events、Structures 和 Media 列下的复选框会全部选中。此方法的好处在于,我们可在 SoundBank 中加入所需的一切内容。 |
技巧: 向 SoundBank 中添加完整工作单元而非单个工程元素的优势是,您后续不必重新编辑 SoundBank ,工作单元的内容变化可以直接生效。这是因为 Wwise 会维护 SoundBank 元素与工程元素之间的链接。如果更改工程中的工作单元, 则 SoundBank 会自动更新。如果使用此方法,只需单击 Generate 按钮便可生成一套新的 SoundBank。 |
备注: 在新工程中,只有默认工作单元可用。如果创建了更多的工作单元,则这些工作单元也应按照需要添加到 SoundBank 中。 |
在游戏中
由于此游戏只有一个 SoundBank,因此您只需在初始化游戏时加载它。当然,第一步是必须正确初始化声音引擎。
有关此方法的更多说明
优点:
缺点:
技巧: 虽然此方法可以快速、轻松地把音频集成到游戏中去,但是不要等到项目结束时再换方法来改进内存占用。 |
适用此方法的情况如下:
此方法非常适用于单人游戏。在单人游戏中,玩家的当前位置决定要用到什么声音。通过把音频内容分到多个 SoundBank 中,内存管理比第一种方法更高效,同时把音频集成到游戏中仍然比较容易。
操作方法:
首先,您必须确定如何拆分 SoundBank。 例如,您可以按以下方式来拆分:
在 Wwise 中
在游戏中
在游戏中,只需在正确的时间加载正确的 SoundBank 即可。例如,游戏可以在开始时加载通用 SoundBank ,然后根据游戏中玩家的实际位置加载其它 SoundBank 。注意,某些游戏需要有足够的内存才可以一次加载多个“关卡”的 SoundBank,实现各关卡之间的过渡。
有关此方法的更多说明
优点:
缺点:
适用此方法的情况如下:
操作方法:
有的游戏非常复杂,可能要按多种因素来触发声音,这些因素包括游戏纹理、时辰、游戏对象的运动,在多人在线游戏中,还可能包括其它玩家的操作。例如在基于事件或对象的环境中,可根据声音与其它游戏对象的距离来决定把声音载入内存。每个游戏对象视情况都可能有一系列必须加载的 SoundBank,这可能是当游戏对象位于一定距离内时要加载的内容,也可能是只要这些对象存在就得加载的内容。
另外,切换开关和状态可决定播放的具体声音。当播放这些声音的事件添加到 SoundBank 时,所有可能用到的媒体也会自动添加到 SoundBank 中。例如,您可能有一个叫“Play_Footstep”的事件。此事件将根据地面的当前纹理播放相应的声音,要播放的具体声音通过切换开关来指定。虽然此方法效果很好,但当游戏场景发生在伦敦的一栋建筑物内时,在内存中一直保留声音“footstep_sand.wav”或“footstep_winter.wav”是浪费内存。
为了避免浪费内存,您可以向 SoundBank 中添加事件或声音结构,然后指定 SoundBank 中启用哪些相应的声音。举例而言,如何我们对不同的纹理使用不同的脚步声,则可创建以下 SoundBank :
在 Wwise 中
重建上一示例的方法:
假设您的游戏中有三种不同的纹理(雪地、沙地和混凝土地)。在 Wwise 中,有一个切换容器根据切换开关“ground_texture”来播放三个随机容器中的一个。三个随机容器中的每一个针对给定的纹理都有四种版本的脚步声。
备注: 如果我们不采取拖放随机容器,而是分别拖放每个声音,也同样可行。 使用容器的优点是,当容器中的内容发生变化时,容器中的所有声音将自动添加到 SoundBank 中,而无需手动完成所有更改。 |
到现在,我们有四个 SoundBank了。一个 SoundBank 中包含与要播放的音频相关的事件和结构数据,而其它三个 SoundBank 中仅包含与特定地面纹理相关的媒体。
在游戏中
有关此方法的更多说明
此示例只是此方法能做到的众多操作之一。由于可以根据声音和事件逐一决定各个 SoundBank 中要启用的内容,因此您可以全面控制 SoundBank 的内容。虽然您可以为游戏中的各个声音创建单独的 SoundBank ,但维护起来非常困难,因为新声音都需要新代码,才能在游戏的正确位置加载 SoundBank 。每款游戏的目标是尝试在控制粒度和集成到游戏中的便利度之间找到良好的平衡。
技巧: 如果您对分别加载声音的方案感兴趣,可考虑使用 PrepareEvent API、PinEventInStreamCache API 或 SetMedia API,而非 LoadBank。 |
优点:
缺点:
适用此方法的情况如下:
确切地说,什么是采用 Prepare 方式的事件?在调用 PrepareEvent 功能时,系统分析事件,确保与此事件相关的所有结构和媒体都载入了内存。否则,系统将自动从磁盘中传输缺少的信息。在显式撤消 Prepare 之前,事件会一直处于准备就绪状态。
操作方法:
此方法要求您显式地把媒体从包含元数据(结构和事件)的 SoundBank 中排除。如果需要,这些结构可以是单独 SoundBank 的一部分。然而,结构的最小加载粒度是一个 SoundBank,因此通常合理的做法是把结构和所在事件装在同一个 SoundBank 中。
在创建使用 PrepareEvent 机制的 SoundBank 时,所需事件和结构必须位于至少一个 SoundBank 中,而且媒体必须作为文件系统中的松散文件来访问。如果 SoundBank 引用的媒体不包含在任何其它 SoundBank 中,CopyStreamedFiles 工具将假定它搭配 PrepareEvent API 使用,并把此松散文件复制到输出目录下。
在对一个事件做 Prepare 之前,事件本身必须已从一个 SoundBank 加到内存中(使用 LoadBank())。这个操作是必需的,因为事件中包含要对事件做 Prepare 操作所需的依赖关系信息。
在 Wwise 中
备注: 单一 SoundBank 中所包含的结构数据不可在运行时拆分。因此,如果使用 AK::SoundEngine::PrepareEvent,并且需要另一 SoundBank 中的结构数据,则将一次性加载该 SoundBank 中的所有结构。为此,您可能需要把工程中的结构内容拆分为多个 SoundBank,从而最大限度地避免把不必要的信息载入内存中。 |
在游戏中
有关此方法的更多说明
记住,必须把调用 AK::SoundEngine::PrepareEvent 视为调用 I/O 函数。在上例中,我们使用了阻塞函数。您可以使用 AK::SoundEngine::PrepareEvent 函数的其它重载来实现非阻塞调用,然后用另一个回调来响应加载完成的通知。
优点:
缺点:
适用此方法的情况如下:
此方法与上一方法(方法 4:准备事件 )基本相同,不同的是在 Prepare 事件时能更好地控制要加载的媒体。使用此方法时,内存中只加载与采用 Prepare 方式的事件和当前活跃的游戏同步器均相关的媒体。
假设有一个简单的工程,里面有两个事件:“Play_Maincharacter_FootSteps”和“Play_Monster_Footsteps”。各个事件播放不同的切换容器。切换容器根据主人公脚下的地面纹理播放不同的随机声音。切换开关组名称是“GroundTexture”,有三个可能的状态:“Snow”、“Concrete”和“Sand”。
Wwise 中的切换容器层级结构如下所示:
Switch_Container_Footstep_Main_Character
以及
Switch_Container_Footstep_Monster
在本例中,我们有 18 个声音(6 组声音,3 个声音一组)可能会载入内存。
您可以使用方法 方法 4:准备事件 ,但粒度级别不会比根据事件载入内存的 6 个声音低。您可以使用 方法 3:微管理媒体 来获得更好的粒度级别,但您必须为此简单项目创建 6 个不同的 SoundBank (每个工程中的 SoundBank 数量快速增加)。然后,当怪兽出现时,您必须查看可能的纹理,然后加载相应的 SoundBank 。
使用当前方法时,您只需指定可能的事件和游戏同步器,然后加载相应媒体即可。和 PrepareEvent 一样,所有的媒体必须作为文件系统中的松散文件可被访问。
操作方法:
在 Wwise 中
在游戏中
备注: 单一 SoundBank 中所包含的结构数据不可在运行时拆分。因此,如果使用 AK::SoundEngine::PrepareEvent,并且需要另一 SoundBank 中的结构数据,则将一次性加载该 SoundBank 中的所有结构。为此,您可能需要把工程中的结构内容拆分为多个 SoundBank,从而最大限度地避免把不必要的信息载入内存中。 |
备注: 您调用 AK::SoundEngine::PrpareEvent 和 AK::SoundEngine::PrepareGameSync 的顺序不重要。当状态改变时,每次都会通过交叉匹配事件和游戏同步器来更新媒体池。 |
有关此方法的更多说明
优点:
缺点: