EBP是什么?
前不久Wwise 2019.2版本的UE4 Integration推出了一条新的管线,叫做Event-Based Packaging,简称EBP。相比于传统的SoundBank管线,这条新管线的特点是基于事件打包,也就是每一个事件的资源会被打包成一个SoundBank。
为什么要这么做?原因是在Wwise传统的管线中,如何组织SoundBank是交给用户自己决定的。在规模较大的项目中,这个组织工作往往需要花费大量时间。而且因为是手动组织管理,加载资源时,冗余也在所难免。而新的EBP流程中,每个事件对应的资源都将被自动打包成SoundBank,而且隐藏在事件的.uasset中,无需用户管理。调用事件时,只有包含相应媒体资源会被加载,这样就实现了需要多少资源就加载多少的机制,根本上杜绝了资源冗余的发生。而且由于每个SoundBank中只包含一个事件的资源,因此可以灵活卸载它们,而无需担心其他的事件无法播放。
本文会介绍一些EBP管线中的关键资源及其加载过程,这样能更好地帮助大家理解这条新的管线。
EBP与WAAPI
要实现在UE中基于事件自动打包,就需要获取Event以及Event与声音媒体的对应关系。这个过程中,EBP管线极度依赖WAAPI。WAAPI的全称是Wwise Authoring API,是一套允许外部应用程序跟Wwise创作工具通信的API。用户可以通过调用这些API控制Wwise创作工具,因此也可以把它理解为连接UE4与Wwise创作工具之间的桥梁。
当你在Wwise创作工具内创建了一个Event,UE4通过注册的回调函数接收到该操作指令后,将自动创建对应的事件.uasset。同样,当用户在UE中的WAAPIPicker面板内点击Generate Sound Data按键时,Wwise创作工具中也会执行Generate SoundBanks操作。在EPB流程中,WAAPI可以保证UE与Wwise创作工具始终保持同步。
通过WAAPI连接Wwise以生成SoundBank是首选的方式,但并不是唯一的生成SoundBank的方式。如果项目无法通过WAAPI连接到Wwise Authoring工具,则可以通过单击Wwise Picker窗口中的Generate Sound Data按钮以使用Wwise Console启动生成过程。与WAAPI相比,生成速度较慢,因为它使用更多的系统I/O调用,但是生成的结果是相同的。您还可以点击Build菜单中的Audiokinetic部分进入Generate Sound Data对话框。
UE中的Wwise资源
声音研发过程中,用户可以利用Wwise中的 Event, State, Switch, RTPC, Bank, Auxiliary Bus, Media资源在项目中构建和编织声音世界。在UE中,这些资源均以.uasset的形式存在,默认情况下存储在Content/WwiseAudio/文件夹中。项目的Wwise资源的位置可以在UE4项目设置的Wwise集成设置部分配置,通过修改“Wwise声音数据文件夹”设置。
下面的表格列出了Wwise资源相应的类,以及它们在UE中的保存位置:
Wwise资源的反序列化
上述资源都派生自Uobject类,这些派生类都需要通过反序列化,把自己变为对象。反序列化是指将一个字节流转换为内存中的一个对象的过程。下图是所有的Wwise资源的类图,可以看到所有资源的派生关系:
在游戏中,开发者可以通过资源引用和C++代码加载这些资源。对于在场景中拖放的对象,或通过Component属性来引用的资源,当Compnent所在对象实例化时,其中的Wwise资源也会被加载。此外,也可以通过在UE中调用LoadObject()来加载这些资源。
而在编辑器中,加载派生自UAKAudioType类资源的工作由AkAssetDatabase类来完成,它的构造函数会注册onAssetAdded、onAssetRemoved、onAssetRenamed这三个事件。其中onAssetAdded负责处理所有资源的加载。实际上在打开UE4引擎编辑器时,当前场景中的Wwise资源都会被加载。
媒体.uasset的加载则是随着事件.uasset实例化进行的,后文的加载过程介绍中,我们将会具体探讨。接下来,我们看看最重要的两种资源,也就是事件.uasset和媒体.uasset中到底包含了哪些内容。
事件.uasset中的内容
用户使用最多的资源就是游戏中的各种事件,创作工具中的事件与UE中的事件.uasset资源,是一对一的关系。用户可以使用事件来执行播放、暂停、设置Switch或State等动作。在EBP中,每个事件.uasset都保存了所有平台的事件内容。其中很关键的信息是事件依赖的SoundBank与媒体资源路径。这里的SoundBank中只有Event和Structure,不包含媒体资源本身,因此事件.uasset文件大小只有几KB。媒体资源路径则是寻找并加载媒体资源的依据。
媒体.uasset中的内容
不同的Event中有时会引用相同的音频文件,这种情况很常见,但容易造成资源冗余。为了实现事件.uasset之间共享声音文件,所有的媒体都从SoundBank中剥离了出来,单独保存在Content\WwiseAudio\Media\文件夹下。按照创作工具中的组织方式,事件依赖的每一个Audio Soucre都会对应一个媒体.uasset文件。它和事件.uasset一样,会在一个文件中保存所有平台的内容。当用户添加新的平台,该文件体积将会增大。
媒体资源以ID命名,如果想要查找对应的MediaName,可以在UE的Content Browser中浏览Content\WwiseAudio\Media,并以Columns的方式来显示。
Wwise主要资源的加载过程
现在我们了解了事件.uasset和媒体.uasset这两个最重要的资源的内容,下面就来看看加载它们的步骤。由于SoundBank和媒体已经分开存放,加载资源时就需要先加载SoundBank,再加载它引用的媒体。
加载文件内的Soundbank
使用Wwise时,在PostEvent之前必须加载该事件依赖的SoundBank,EBP中也是如此。事件.uasset加载的过程中,会自动加载其中的SoundBank,也就是所有Event和Structure都会被加载。需要注意的一点是,在EBP中,事件.uasset实例化时,SoundBank已经被加载到内存中,这就意味着加载的SoundBank位于UE的保留内存,而不是Wwise本身的保留内存。声音引擎会通过接受内存地址的AK::SoundEngine::LoadBankMemoryView()函数加载SoundBank。
加载依赖的Media
完成SoundBank加载后,媒体.uasset也将被加载,下一步将会通过保存在事件.uasset内部的媒体资源路径去加载媒体。因此它与SoundBank一样位于UE的保留内存中。
EBP管线没有采用PrepareEvent的方式加载媒体,而是通过调用接受内存地址的SetMedia()函数来获取资源告诉声音引擎该媒体资源所在的内存位置。每个媒体.uasset只会被实例化一次因此无需担心数据会被重复加载。
小结
本文简要介绍了EBP管线中的主要资源内容以及它们的加载过程,希望可以帮助读者理解这条管线的组织方式。EBP管线相对比较新,因此随着后续发布版本不断更新完善,本文所述的内容可能也会发生细节上的变化。但笔者相信,自动化管理SoundBank的方式可以为游戏音频研发流程节省可观的时间成本。期待它在不久的将来能够更加成熟稳定,为更多的游戏研发团队带来效益上的提升。
本文能和读者见面,离不开我在Audiokinetic的同事们的帮助,在此衷心感谢 Guillaume Renaud 和 Julie Delisle 严谨而富有建设性的建议和指正!
评论
ming fang
January 11, 2021 at 10:44 pm
你好,请问基于EPB时,如果单个Event对应的媒体资源很大,但是又不想拆分event时,event需要的媒体资源是否可以进行异步加载呢
ming fang
January 11, 2021 at 10:44 pm
你好,请问基于EPB时,如果单个Event对应的媒体资源很大,但是又不想拆分event时,event需要的媒体资源是否可以进行异步加载呢
ming fang
January 11, 2021 at 10:44 pm
你好,请问基于EPB时,如果单个Event对应的媒体资源很大,但是又不想拆分event时,event需要的媒体资源是否可以进行异步加载呢
ming fang
January 11, 2021 at 10:44 pm
你好,请问基于EPB时,如果单个Event对应的媒体资源很大,但是又不想拆分event时,event需要的媒体资源是否可以进行异步加载呢