此方法适用于以下情形:
要保持较低的内存占用,需要媒体具有很小的粒度级别。
不用为管理哪些媒体素材必须指派给哪个 SoundBank 而烦恼。
什么是准备就绪的Action Event(动作事件)?在调用 PrepareEvent()
函数时,系统将分析Action Event(动作事件),确保与此 Event 相关的所有结构和媒体都已加载到内存中。否则,系统会自动从磁盘流式传入缺失的信息。在明确撤消以前,Event 一直处于 Prepare 状态。
备注 | |
---|---|
只有动作 Event 可事先 Prepare。“PrepareEvent()”方法不适用于对话事件。 |
此方法要求创建至少一个 SoundBank,然而结构部件可以位于与 Event 所在的同一个 SoundBank 中,也可处于完全独立的一个 SoundBank 中。
在构建使用 PrepareEvent 机制的 SoundBank 时,条件是至少在一个 SoundBank 中能够找到所需的所有 Event 和结构,而且文件系统必须能够访问这些松散媒体素材。记住,将结构划分到多个 SoundBank 中可以提高内存的管理效率。
在 Prepare 动作 Event 前,Event 本身必须(使用 LoadBank())从一个 SoundBank 加载到内存中。由于 Event 中包含在 Prepare Event 时所需的依赖项的信息,因此必须首先加载 Event 所在的 SoundBank。
备注 | |
---|---|
另外还可结合 AK::SoundEngine::PrepareBank 来 Prepare Event。使用 PrepareBank 机制的主要优势是无需将 SoundBank 划分为“Event 库”和“媒体库”。在这种方法下,所有内容包含在同一个 SoundBank 中,但是在调用 AK::SoundEngine::PrepareBank 时,只有 SoundBank 的元数据内容加载到内存。当游戏需要媒体时,您可以使用 PrepareEvent 加载媒体。 |
在 Prepare Event 时在 Wwise 中设置 SoundBank 的方法是:
创建一个名为“Event”的 SoundBank,并加载到 SoundBank Editor 中。
把工程中的一些动作事件添加到“Events” SoundBank 中,或仅添加事件工作单元。
禁用 Media 复选框,只将 Events 和 Structures 复选框保留为启用状态。在使用 PrepareEvent() 时,媒体不得位于 SoundBank 内,但可以作为松散文件直接从磁盘中加载。
备注 | |
---|---|
在本例中,所有 Event 和结构包含在一个 SoundBank 中。虽然对于小型工程,这是可以接受的,但您很可能会需要将内容拆分到多个 SoundBank。另外还可以创建独立的“Structures”SoundBank,它无需从 SDK 命令行进行显式加载或 Prepare,因为各个 Event 都包含对需要加载的其它 SoundBank 的引用。 |
生成 SoundBank,并将生成的 SoundBank 文件夹复制到游戏应用程序。
备注 | |
---|---|
单个 SoundBank 中包含的结构数据不可在运行时拆分。因此,如果您使用了 AK::SoundEngine::PrepareEvent(),并且需要来自独立 SoundBank 的结构数据,则该 SoundBank 中的所有结构将一次性加载。为此,您可能会需要将工程中的结构内容拆分到多个 SoundBank,最大限度地减少加载到内存中的非必需信息量。 |
在游戏中 Prepare Event 的方法是:
在游戏中,先在游戏开始时加载 Event 的 SoundBank,然后再在游戏中需要时来 Prepare Event。相应的结构和媒体将自动加载。
下面的代码示例可以让您了解在游戏中如何Prepare Event。
// 对声音引擎初始化。 AkInitSettings initSettings; AkPlatformInitSettings platformInitSettings; AK::SoundEngine::GetDefaultInitSettings( initSettings ): AK::SoundEngine::GetDefaultPlatformInitSettings( platformInitSettings ): // 设置必需的设置。 ... // 设置 PrepareEvent 相关设置。 initSettings.bEnableGameSyncPreparation = false; // 当前示例中没有使用。 // (可选)分配内存池来载入已 Prepare 的媒体。 // 如果未分配,则将直接在默认的内存池中分配内存。 { initSettings.uPrepareEventMemoryPoolID = AK.MemoryMgr.CreatePool( NULL, 4*1024*1024, 1024, AkMalloc ); // (可选)为内存池指定名称。这在性能分析时非常有用。 AK::MemoryMgr::SetPoolName( initSettings.uPrepareEventMemoryPoolID, L"PrepareEventPool" ); } AKRESULT eResult = AK.SoundEngine.Init( initSettings, platformInitSettings ); if( eResult != AK_Success ) { // 处理错误。 } // 加载初始化库和事件/结构库。 AkBankID bankID; // 本示例中没有使用。 AKRESULT eResult = AK::SoundEngine::LoadBank( L"Init.bnk", AK_DEFAULT_POOL_ID, bankID ); if( eResult == AK_Success ) { eResult = AK::SoundEngine::LoadBank( L"Events.bnk", AK_DEFAULT_POOL_ID, bankID ); } ... // 然后,在代码的各个点: AkLpCtstr pEventsNameArray[1] = { L"My_Event_Name" }; // Prepare 事件: eResult = AK::SoundEngine::PrepareEvent( Preparation_Load, pEventsNameArray, 1 ); // 1 是数组大小。 // 解除对事件的 Prepare 操作: eResult = AK::SoundEngine::PrepareEvent( Preparation_Unload, pEventsNameArray, 1 ); // 1 是数组大小。
记住,对 AK::SoundEngine::PrepareEvent()
的调用必须视为 I/O 函数调用。在上例中,我们使用了阻塞函数。您可以使用 AK::SoundEngine::PrepareEvent()
函数的其它重载来实现非阻塞调用,然后用另一个回调来响应加载完成的通知。
下表列举了对 Action Event(动作事件)做 Prepare 的优点和缺点。
优点 |
缺点 |
---|---|
生成 SoundBank 的过程很简单。 媒体的粒度级别非常小。 内存占用总体保持在低水平。 过程自动化非常容易。 |
当逐一加载媒体素材时,可能增加磁盘上的读取和寻址次数。 对总体内存占用量的控制力减弱。 使用交互式音乐时将变得复杂。 |