Table of Contents

Wwise和Unity一起使用

这里的方案使用了AddressableAsset进行资源管理,支持热更新音频资源和音频逻辑

后记:

  1. 代码实现的时候,参考了官方插件的写法(将EventID等存储在Asset资源中,先加载资源再触发事件)。但实际上我们通过解析Sound Bank的json(或者XML)已经得到了Event的信息,完全可以不走资源加载(或者在Runtime构建资源,也就是目前我们的代码中的做法)的一步,还会更加方便一些(感觉Wwise官方的插件,完全没有为程序员考虑,默认提供的功能都是在场景中编辑事件的触发逻辑…)
  2. Init Bank是必需的,而且必须第一个加载,在Init Bank加载完成之前几乎不能执行Wwise的任何功能。另一方面,Init Bank中不会包含资源,体积不会很大,也不会随着项目规模的增大而有很大的增长。还有,Init Bank只需要加载一次,在整个游戏运行过程中不会卸载。所以,直接走同步加载即可,不必非要走异步,同步加载没有什么代价,但是换来的是,在整个游戏的几乎任何位置,都可以不考虑Init Bank是否已经加载,直接使用Wwise的功能,节省了很多的处理异步的工作量(少点异步操作就是少点bug啊…)

参考代码:https://github.com/GZhonghui/UnityTools/tree/master/Wwise


实现目标

  1. Unity集成Wwise
  2. 使用Addressable管理资源(热更新)
  3. 自行解析Wwise输出的文件
  4. PlayMode和EditMode都支持Event(播放/停止)/Switch/State

集成操作

创建空的Wwise工程,在Launcher中安装并关联到Unity工程中去,注意:

  1. Unity的版本号后面不能带c,带c是中国版,和正常版路径不同,Wwise找不到。
  2. 集成的时候选择对应的Wwise版本,Wwise不会自动为你选择已安装的版本,而是默认选择最新版,如果你安装的不是最新版的Wwise,那么集成到Unity的界面大概率是一片红色的报错。
  3. 集成的时候,Windows和Mac平台必选,建议再选上Android和iOS。

在Wwise中先生成一下SoundBank。打开Unity做一些设置:

  1. 删掉WwiseGlobal并关闭自动生成
  2. 删掉MainCamera上的Listener并关闭自动挂载WwiseListener

然后检查运行是否有问题

安装Wwise的Addressable插件,参考:
https://www.audiokinetic.com/zh/library/edge/?source=Unity&id=pg_addressables_setup.html
Unity中需要先安装好Addressable(注意版本),然后安装Wwise的AA插件,在Package Manager中安装:
https://github.com/audiokinetic/WwiseUnityAddressables.git
安装完成后,在Unity中打开Wwise的设置

  1. 开启Use Sample Metadata Preserver,设置好路径
  2. 修改Bank的生成位置,回到Wwise,重新加载工程

在Unity中序列化保存一次Wwise分组的信息,之后可以看到:

  1. Addressable中多了对应的Bank分组
  2. Meta文件夹和Bank文件夹中都生成了对应的内容

创建Wwise的Addressable Builder,建议就放在默认位置DataBuilders,在Addressable的Setting中把新Builder脚本挂上去,现在检查Addressable的Build选项,已经有了Wwise的Build。然后就可以使用Addressable管理音频资源了,根据需求修改音频资源的构建位置、加载位置即可。

回到Wwise,修改生成SoundBank的设置

  1. 需要生成头文件
  2. 需要生成Bank的Json信息
  3. 需要包含Guid

关闭Unity,把安装的WwiseAddressable插件从Library/PackageCache移动到Packages。然后修改manifest.json,把WwiseAddressable的一行移除。这是为了我们以后可以修改这个Package的代码。

回到Unity,检查是否正常运行。后续就要修改Wwise的代码了。

代码修改

Assets\Wwise\API\Runtime\WwiseTypes\WwiseObjects\WwiseObjectReference.cs
我们要在游戏的运行时,按照数据构建Wwise Object Reference,而不是通过加载Script Object进行读取,这个类有3个private成员变量,唯一能创建这个类的函数在UnityEditor内部,也就是Wwise禁止在运行时创建Wwise Object Reference,但这样满足不了我们的需求。所以我们写3个public接口,允许我们设置3个private成员变量。数据的话,我们不从Script Object读取,而是自己通过解析Wwise输出的Json文件得到,自己维护。

Assets\Wwise\API\Runtime\WwiseTypes\WwiseTypes\AkWwiseEvent.cs
在事件触发的时候

  1. 增加选项控制是否需要保存延迟的事件(Bank加载完成后再播放)
  2. 增加选项控制是否需要跳过加载的时间

修改WwiseAddressable
Packages\com.audiokinetic.wwise.addressables@90e4ec2288\Runtime\AkAddressableBankManager.cs
增加一个注册Action的方法,注册的Action会在Bank加载完成的时候调用,通知我们Bank加载完成。我们需要知道Wwise Bank的加载状态,用于做一些延迟的操作。

Assets\Wwise\API\Editor\WwiseMenu\Common\AkWwiseIdConverter.cs
Assets\Wwise\Tools\WwiseIDConverter.py
修改为不需要手动选择C++头文件,直接从默认位置读取,保存到默认位置,简化操作。

准备Python3环境,建议3.10,记得加到系统的PATH里面。

系统设计

Assets\WwiseData\Editor\ParseWwiseJson.cs
Assets\WwiseData\Tool\ParseWwiseJson.py
解析Wwise输出的Json文件

MarkWwiseAddressable.cs
自动整理Wwise资源的AA分组

Assets\Script\CSharp\Wwise\AD_WwiseManager.cs
使用的接口都封装在这里,需要一次全局初始化,在GameMain里面执行

Assets\Script\CSharp\Wwise\AD_WwiseBank.cs
Assets\Script\CSharp\Wwise\AD_WwiseEvent.cs
可以挂在场景中的组件,用于加载Bank或者发出Event

其他问题

Wwise在EditMode下播放没有声音的问题
在EditMode下也是可以加载Bank,发送Event的,但是打开新的场景/代码修改有热重载后,就会出现声音消失的情况,根据输出的Log来看,事件是发送成功了的,但就是没有声音,怀疑是Wwise的Bug,因为在空工程里面,没有对Wwise进行任何修改的情况下,使用Wwise提供的Mono Behaviour,也会出现同样的情况。
我们现在的解决方法是,切换场景/热重载后,Reset一遍Wwise引擎,这个操作也并不费时,所以效率上也没什么问题。另外,在Runtime并不会出现这个问题,也不会在切换场景的时候Reset。

#if Art_Editor
    [UnityEditor.MenuItem("Wwise/Init Wwise", false, (int)1)]
    [UnityEditor.Callbacks.DidReloadScripts] // Unity Hot Reload
#endif
    public static void DoInitWwise()

在EditMode下加载Bank慢的问题
我们使用了Addressable来管理Wwise的资源,所以在EditMode下播放时,也是使用Addressable来加载Bank的,然而在EditMode下,Unity并不会像在Runtime一样一直刷新,导致Addressable加载资源会比较慢。
我们现在的解决方法是,加载的时候,启动一个Keeper,让Unity保持刷新,加载完成后,再停掉这个Keeper。
https://forum.unity.com/threads/how-to-use-addressable-system-in-editor-script.715163/#post-7906237

或者参考这里:在EditMode中保持Update

零散

  1. AkInitializer:此组件用于初始化 Wwise 声音引擎并更新音频帧。它被标记为 DontDestroyOnLoad ,因此在整个游戏当中都会始终保持有效,并非只作用于一个场景。
  2. [存疑]在EditMode中,好像设定的Listener无效,物体使用的Listener都是自己本身?

问题和想法

  1. Wwise Addressable中的build script做了哪些工作,有哪些部分是可以自定义控制的?

外链资料

官方资料:

一份比较完整的工作流程(不是使用Addressable进行热更):

  1. Unity集成Wwise并进行开发的全流程教程(一)准备工作 https://blog.csdn.net/sinat_34870723/article/details/89387926 归档
  2. Unity集成Wwise并进行开发的全流程教程(二)Wwise项目 https://blog.csdn.net/sinat_34870723/article/details/89458824 归档
  3. Unity集成Wwise并进行开发的全流程教程(三)脚本接入Unity https://blog.csdn.net/sinat_34870723/article/details/89506079 归档