# 使用 Wwise 插件实现空间音频 (/zh-CN/solutions/game-voice/build/spatial-audio-wwise)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

<_PlatformTabsGroup>
<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="unity" platform="unity" />
声网支持你通过 SDK 或 Wwise 插件实现空间音效，两种方案的选型详见[适用场景](/zh-CN/solutions/game-voice#适用场景)。本文介绍如何通过声网 Wwise 插件在你的 Unity 项目中实现空间音频，增强游戏体验。在多人在线语音视频聊天场景中，空间音效可以实现多人语音的空间感及后期效果处理，大大增强产品的竞争力。

## 插件概述 [#插件概述]

声网提供的 Wwise 插件主要用于数据流传输，可与声网 RTC SDK 结合使用，增强 RTC SDK 使用时的灵活性。

| 声网插件名称 | 插件类别 | 插件用途 |
| ------------------------- | ----------------- | -------------------------------------- |
| AgoraAudioInputSource | Wwise Source 插件 | 将 RTC SDK 采集的本地用户音频数据传输给 Wwise |
| AgoraReceiveSource | Wwise Source 插件 | 将 RTC SDK 接收到的远端用户音频数据传输给 Wwise |
| AgoraSendEffect | Wwise Effect 插件 | 将用户音频数据发送给声网服务器 |
| AgoraAudioSessionEffect | Wwise Effect 插件 | 用于在总线上获取参考信号以进行回声消除 |

声网 Wwise 插件当前支持如下架构：

- Android：arm64-v8a、armeabi-v7a、x86、x86_64
- iOS
- macOS
- Windows：vc160、vc170

## 前提条件 [#前提条件]

开始前，请确保你的本地有一个 Unity 项目。相关步骤可以参考 [RTC 快速开始](/zh-CN/realtime-media/rtc/get-started/quick-start)。

## 准备开发环境 [#准备开发环境]

### 下载 Wwise 编辑器 [#下载-wwise-编辑器]

1. 下载 [Audiokinetic Launcher](https://www.audiokinetic.com/zh/download)（也被称为 Wwise Launcher）。
2. 在 Audiokinetic Launcher 中安装 Wwise 编辑器 2023.1.6.8555。

<DocsImage alt="安装指定版本的 Wwise" src="https://web-cdn.agora.io/docs-portal/img/game-voice/wwise-2023.1.6.png" displayWidth="70%" />

### 下载 SDK 与插件 [#下载-sdk-与插件]

声网 Unity 平台 Wwise 解决方案由 Wwise 编辑器插件、RTC Unity SDK 和 Wwise Plugin SDK 共同搭建实现，对各模块的兼容版本号有明确要求。在准备开发环境时，请确保下载并安装指定版本的 SDK 和插件：

- 点击下载[声网 Wwise 编辑器插件 2023.1.6.8555](https://download.agora.io/sdk/release/AG_Plugin_FULL_2023.1.6.8555_20241030_0242.zip)。该插件兼容 Wwise 编辑器 2023.1.6.8555。
- 下载[声网 RTC Unity SDK v4.3.2.14](https://download.agora.io/sdk/release/Agora_Unity_RTC_SDK_v4.3.2.14_VOICE_20250304_399.zip)。
- 下载 [声网 Wwise Plugin SDK 2023.1.6.8555_v4.3.2.14](https://download.agora.io/sdk/release/Agora-Wwise-Plugin_2023.1.6.8555_v4.3.2.14_20250304_1110.zip)。

:::warning[注意]
声网 Wwise Plugin SDK 目前仅适配 Wwise 插件 2023.3.6.8555 和 RTC SDK 4.3.2.14。如果你有其他版本的适配需求，可以[联系技术支持](https://ticket.shengwang.cn)。
:::

### 导入 SDK [#导入-sdk]

1. 将下载下来的 RTC SDK 添加到你的 Unity 项目中。
2. 解压下载后的 Agora-Wwise-Plugin 插件，将解压后的 Agora-Wwise-Plugin 文件夹拷贝到你的 Unity 项目的 Assets 文件夹下。
3. 解压下载后的 Wwise 编辑器插件，会得到一个 AG_Plugin_FULL 文件。在 Wwise Launcher 中，点击左侧的 **Plug-ins**，然后点击 **Add from directory**。选中 AG_Plugin_FULL 进行添加。安装完成后，你会在 **Plug-ins** 界面的 INSTALLED PLUG-INS 区域内看到安装完成的 AgoraWwiseRTCSDK：

![安装完成插件](https://web-cdn.agora.io/docs-portal/img/game-voice/installed-plugins.png)

### 集成 Wwise 插件至 Unity 项目 [#集成-wwise-插件至-unity-项目]

1. 在 **Wwise Launcher** 中，点击左侧的 **Unity**，你应该能看到你创建的 Unity 项目名称，例如 **My Project**：

![添加我的项目](https://web-cdn.agora.io/docs-portal/img/game-voice/my-project.png)

2. 点击项目名右侧的 **Integrate Wwise in Project**，然后根据屏幕指引，勾选你想要下载包、部署平台，然后点击 **Integrate**，开始集成。

   :::warning[注意]
   确保你在该步骤中将 **Integration version** 设置为 2023.1.6.8555。
   :::

集成成功后，根据你勾选的部署平台，你应当在你的 Unity 项目路径下找到如下文件。如果没有找到，可以参考[手动拷贝 Wwise 插件文件](#手动拷贝-wwise-插件文件)。

<Accordions>
<Accordion title="Android">

- /Assets/Wwise/API/Runtime/Plugins/Android/arm64-v8a/DSP/libAgoraWwiseRTCSDK.so
- /Assets/Wwise/API/Runtime/Plugins/Android/armeabi-v7a/DSP/libAgoraWwiseRTCSDK.so
- /Assets/Wwise/API/Runtime/Plugins/Android/x86/DSP/libAgoraWwiseRTCSDK.so
- /Assets/Wwise/API/Runtime/Plugins/Android/x86_64/DSP/libAgoraWwiseRTCSDK.so

</Accordion>

<Accordion title="iOS">

- /Assets/Wwise/API/Runtime/Plugins/iOS/iphoneos/DSP/AgoraWwiseRTCSDKSourceFactory.h
- /Assets/Wwise/API/Runtime/Plugins/iOS/iphoneos/DSP/libAgoraWwiseRTCSDKSource.a
- /Assets/Wwise/API/Runtime/Plugins/iOS/iphonesimulator/DSP/AgoraWwiseRTCSDKSourceFactory.h
- /Assets/Wwise/API/Runtime/Plugins/iOS/iphonesimulator/DSP/libAgoraWwiseRTCSDKSource.a

</Accordion>

<Accordion title="macOS">

- /Assets/Wwise/API/Runtime/Plugins/Mac/DSP/libAgoraWwiseRTCSDK.bundle

</Accordion>

<Accordion title="Windows">

- /Assets/Wwise/API/Runtime/Plugins/Windows/x86/DSP/AgoraWwiseRTCSDK.dll
- /Assets/Wwise/API/Runtime/Plugins/Windows/x86_64/DSP/AgoraWwiseRTCSDK.dll

</Accordion>
</Accordions>

### 在 Wwise 中配置插件 [#在-wwise-中配置插件]

1. 在 Wwise 中打开你的 Unity 项目。你可以直接从 Wwise Launcher 中 Unity 项目右侧的 **Open in Wwise** 按钮打开。

![打开项目](https://web-cdn.agora.io/docs-portal/img/game-voice/open-project.png)

2. 在 **Actor-Mixer Hierarchy** 下的任意节点单击右键，选择 **New Child** > **AgoraAudioInputSource**，创建一个新的 Sound SFX，用于将本地用户音频数据传输给 Wwise。将其重命名，例如 AudioInputSource。

![在 Wwise 中创建 AgoraAudioInputSource](https://web-cdn.agora.io/docs-portal/img/game-voice/unity-wwise-1.png)

3. 点击刚刚创建好的 AudioInputSource，在 **Effects** 面板上点击 **+** 按钮，新增 **AgoraSendEffect**，用于将用户音频数据发送给声网服务器。

![为 AudioInputSource 添加 AgoraSendEffect](https://web-cdn.agora.io/docs-portal/img/game-voice/unity-wwise-2.png)

4. 在 **Actor-Mixer Hierarchy** 下的任意节点单击右键，选择 **New Child** > **AgoraReceiveSource**，创建一个新的 SoundSFX，用于将远端用户音频数据传输给 Wwise。这里我们可以命名为 AgoraRecevieSource。

![在 Wwise 中创建 AgoraReceiveSource](https://web-cdn.agora.io/docs-portal/img/game-voice/unity-wwise-3.png)

5. 在 **Master-Mixer Hierarchy** > **Default Work Unit** > **Master Audio Bus** 的 **Effects** 面板下添加 **AgoraAudioSessionEffect**，用于将本地用户音频数据传输给 Wwise。

![为 Master Audio Bus 添加 AgoraAudioSessionEffect](https://web-cdn.agora.io/docs-portal/img/game-voice/unity-wwise-4.png)

6. 为刚刚创建的 AgoraInputSource 和 AgoraReceiveSource 分别添加 **Play** 和 **Stop** 事件。

![为 AgoraAudioInputSource 和 AgoraReceiveSource 添加 Play 和 Stop 事件](https://web-cdn.agora.io/docs-portal/img/game-voice/unity-wwise-5.png)

   所有事件创建完成后，效果如下图：

<DocsImage alt="Wwise 中已创建完成的事件和对象示例" src="https://web-cdn.agora.io/docs-portal/img/game-voice/unity-wwise-6.png" displayWidth="40%" />

7. 将刚才创建的所有 Event，Sound SFX 和 Master Audio Bus 加入到 SoundBank 中，并 Generate SoundBank。

## 在 Unity 项目中使用插件 [#在-unity-项目中使用插件]

### 初始化设置 [#初始化设置]

你需要在该步骤中初始化 `RtcEngine` 和 Agora Wwise Plugin，并参考如下代码设置相关的私有参数：

```csharp
using Agora.Rtc;
 
private IRtcEngineEx _rtcEngineEx = null;
private int _sendTrackId = 0;
 
 
// 初始化 RtcEngine
_rtcEngineEx = RtcEngine.CreateAgoraRtcEngineEx();
RtcEngineContext rtcEngineContext = new RtcEngineContext();
rtcEngineContext.appId = appId;
rtcEngineContext.areaCode = AREA_CODE.AREA_CODE_GLOB;
var nRet = _rtcEngineEx.Initialize(rtcEngineContext);
_rtcEngineEx.SetClientRole(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
Debug.Log("RtcEngine Initialize: " + nRet);
_rtcEngineEx.InitEventHandler(new RtcEngineEventHandler());
_rtcEngineEx.EnableAudio();
_rtcEngineEx.DisableVideo();
           
 
// 初始化 Agora-Wwise-Plugin
IntPtr nativeHandler = IntPtr.Zero;
_rtcEngineEx.GetNativeHandler(ref nativeHandler);
AgoraWwiseWrapper.InitAgoraWwisePlugin(nativeHandler, ref _sendTrackId);
Debug.Log("_sendTrackId :" + _sendTrackId);
 
// 设置私参
_rtcEngineEx.SetParameters("{\"che.audio.mute_playout_signal\":true}");
 
// Audio Profile
_rtcEngineEx.SetParameters("{\"che.audio.custom_payload_type\":122}");
_rtcEngineEx.SetParameters("{\"che.audio.custom_bitrate\":24000}");
_rtcEngineEx.SetParameters("{\"che.audio.bitrate_level\":1}");
_rtcEngineEx.SetParameters("{\"che.audio.force_bluetooth_a2dp\":true}");
_rtcEngineEx.SetParameters("{\"che.audio.opensl.sync_downlink_process\":false}");
 
// Module Related
_rtcEngineEx.SetParameters("{\"che.audio.use_media_volume_in_headset\":1}");
_rtcEngineEx.SetParameters("{\"che.audio.use_media_volume_in_bluetooth\":1}");
_rtcEngineEx.SetParameters("{\"che.audio.ans.noise_gate\":200}");
_rtcEngineEx.SetAudioScenario(AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_GAME_STREAMING);
 
#if UNITY_IPHONE
_rtcEngineEx.SetParameters("{\"che.audio.keep.audiosession\":true}");
#endif
 
_rtcEngineEx.SetParameters("{\"che.audio.ps.mode\":0}");
_rtcEngineEx.SetParameters("{\"che.audio.sf.statNsFastNsSpeechTrigThreshold\":0}");
```

### 加入频道并收、发流 [#加入频道并收发流]

调用 RTC SDK 的 `JoinChannel` 方法加入 RTC 频道，并设置订阅和发布选项。

然后将我们在 Wwise 编辑器中创建的 SoungSFX 绑定到用于发流或者收流的 `GameObject`，实现 RTC SDK 和 Wwise 之间的音频传输。完整的实现逻辑和示例代码如下：

```csharp
// 加入频道
var options = new ChannelMediaOptions();
options.publishCameraTrack.SetValue(true);
options.publishMicrophoneTrack.SetValue(true);
options.autoSubscribeAudio.SetValue(true);
options.autoSubscribeVideo.SetValue(true);
options.publishCustomAudioTrack.SetValue(true);
options.publishCustomAudioTrackId.SetValue(_sendTrackId);
_rtcEngineEx.JoinChannel("", channelId, uint.Parse(userId), options);
 
// 想要正常发流，必须在场景内创建一个用于发流的 GameObject（比如 3D游戏中常见的小人，或者是一个麦克风都可以)
// 并且在这个 GameObject 上绑定一个组件，在组件内填写如下代码
public void Start()
{
    // 这段代码用于在我们当前的 GameObject 添加一个我们在 Wwise 编辑器里创建的 Sound SFX
    // 该 Sound SFX 会持续的从 RTC SDK 中传输麦克风音频到 Wwise 中
    this.gameObject.AddComponent<AkGameObj>();
    AkSoundEngine.PostEvent("Play_AudioInputSource", this.gameObject);
}
 
 
private void OnDestroy()
{  
    AkSoundEngine.PostEvent("Stop_AudioInputSource", this.gameObject);
}
 
 
// 当远端用户加入 RTC 频道后，需要在当前场景内创建一个用于收流的 GameObject，并且在这个 GameObject 上绑定一个组件，在组件内填写如下代码
public void Start()
{
    // remoteUid: 远端用户的 UID
    // channelId: RTC 频道的 ID
    this.gameObject.AddComponent<AkGameObj>();
    ulong gameObjId = AkSoundEngine.GetAkGameObjectID(this.gameObject);
    Agora.Rtc.AgoraWwiseWrapper.SetUidToGameObjectIDMapping(gameObjId, channelId, remoteUid);
    AkSoundEngine.PostEvent("Play_AgoraReceiveSource", this.gameObject);
}

// 在远端用户离开房间后，需要销毁 GameObject 并且触发其 OnDestroy 方法
private void OnDestroy()
{
    AkSoundEngine.PostEvent("Stop_AgoraReceiveSource", this.gameObject);
    Agora.Rtc.AgoraWwiseWrapper.ClearReceiveOpenID(channelId, remoteUid);
}
 
// 在频道里下麦
public void MuteLocal()
{
    var options = new ChannelMediaOptions();
    options.publishCameraTrack.SetValue(false);
    options.publishMicrophoneTrack.SetValue(false);
    options.autoSubscribeAudio.SetValue(true);
    options.autoSubscribeVideo.SetValue(true);
    options.publishCustomAudioTrack.SetValue(false);
    options.publishCustomAudioTrackId.SetValue(_sendTrackId);
    _rtcEngineEx.UpdateChannelMediaOptions(options);
}
 
// 在频道上麦
public void UnmuteLocal()
{
    var options = new ChannelMediaOptions();
    options.publishCameraTrack.SetValue(true);
    options.publishMicrophoneTrack.SetValue(true);
    options.autoSubscribeAudio.SetValue(true);
    options.autoSubscribeVideo.SetValue(true);
    options.publishCustomAudioTrack.SetValue(true);
    options.publishCustomAudioTrackId.SetValue(_sendTrackId);
    _rtcEngineEx.UpdateChannelMediaOptions(options);
}
```

### 离开频道 [#离开频道]

```csharp
_rtcEngineEx.LeaveChannel();
```

:::warning[注意]
如果你的游戏逻辑中存在 `JoinChannel`、`LeavelChannel` 这种反复的操作，请确保在每次 `LeaveChannel` 之后，调用 `Agora.Rtc.AgoraWwiseWrapper.ClearReceiveOpenID(channelId, remoteUid);` 清除掉旧频道中已经过期的远端用户绑定。
:::

### 销毁资源 [#销毁资源]

```csharp
Agora.Rtc.AgoraWwiseWrapper.UninitAgoraWwisePlugin();
_rtcEngineEx.LeaveChannel();
_rtcEngineEx.Dispose();
_rtcEngineEx = null;
```

:::warning[注意]
请确保在 `Agora.Rtc.AgoraWwiseWrapper.UninitAgoraWwisePlugin();` 之前，调用了 `Agora.Rtc.AgoraWwiseWrapper.ClearReceiveOpenID(channelId, remoteUid);` 来清除之前调用 `Agora.Rtc.AgoraWwiseWrapper.SetUidToGameObjectIDMapping();` 所绑定的 `uid` 和 `channelId`。
:::

## 参考信息 [#参考信息]

### 构建 App 注意事项 [#构建-app-注意事项]

导出 iOS 工程时，控制台会报错，提示 `AgoraWwiseRTCSDKFX.a` 找不到。此时需要打开你生成的 SoundBanks。默认情况下，SoundBanks 文件位于 Wwise 编辑器工程 `/GeneratedSoundBanks/iOS` 文件夹下。如果你设置了其他路径，请打开对应的目录。然后打开 `PluginInfo.xml` 文件，查找如下关键字：

```xml
StaticLib="AgoraWwiseRTCSDKFX"
```

应该可以在文件内查找到如下两处：

![PluginInfo.xml 中的 StaticLib 配置示例](https://web-cdn.agora.io/docs-portal/img/game-voice/trouble-shoot.png)

将其中的 `StaticLib="AgoraWwiseRTCSDKFX"` 修改为：

```xml
StaticLib="AgoraWwiseRTCSDKSource"
```

修改后如下所示，保存文件：

![将 StaticLib 修改为 AgoraWwiseRTCSDKSource 后的示例](https://web-cdn.agora.io/docs-portal/img/game-voice/trouble-shoot-2.png)

接着，我们在 Unity Editor 里导出 iOS 工程并用 Xcode 打开之后，可以在 `Libraries/Wwise/API/Runtime/Plugins/iOS/iphoneos/DSP` 文件下，看到如下三个文件，和 `include "AgoraWwiseRTCSDKSourceFactory.h"` 这句代码：

![iOS 工程中 AgoraWwiseRTCSDKSource 相关文件示例](https://web-cdn.agora.io/docs-portal/img/game-voice/trouble-shoot-3.png)

至此，iOS 的 App 构建得以顺利完成。

如果在 Xcode 目录下并没有 `AkiOSPlugins` 文件，请检查 `Data/Raw/Audio/GeneratedSoundBanks/iOS/PluginInfo.xml` 文件中内容是否为被修改后的内容：

![检查 PluginInfo.xml 修改结果的示例](https://web-cdn.agora.io/docs-portal/img/game-voice/trouble-shoot-4.png)

如果发现该文件内的内容又恢复到了 `StaticLib="AgoraWwiseRTCSDKFX"`，则说明在构建过程中 SoundBanks 被重新生成了，导致之前的文本修改被重新覆盖。此时可以检查是否在 Unity Editor 里勾选了 **Generate SoundBanks at pre-Build step**：

![Unity Editor 中 Generate SoundBanks at pre-Build step 选项示例](https://web-cdn.agora.io/docs-portal/img/game-voice/trouble-shoot-5.png)

### 手动拷贝 Wwise 插件文件 [#手动拷贝-wwise-插件文件]

在集成 Wwise 到 Unity 项目中之后，如果你发现缺失了上文中列出的部分的文件，可以手动将这些文件拷贝进入 Unity 项目中：

<Accordions>
<Accordion title="Android">

| 源文件 | 拷贝到 Unity 项目目录 |
| --- | --- |
| [spatial-audio-wwise-unity-markdown-1-1-0 details](#table-slot-spatial-audio-wwise-unity-markdown-1-1-0) | [spatial-audio-wwise-unity-markdown-1-1-1 details](#table-slot-spatial-audio-wwise-unity-markdown-1-1-1) |
| [spatial-audio-wwise-unity-markdown-1-2-0 details](#table-slot-spatial-audio-wwise-unity-markdown-1-2-0) | [spatial-audio-wwise-unity-markdown-1-2-1 details](#table-slot-spatial-audio-wwise-unity-markdown-1-2-1) |
| [spatial-audio-wwise-unity-markdown-1-3-0 details](#table-slot-spatial-audio-wwise-unity-markdown-1-3-0) | [spatial-audio-wwise-unity-markdown-1-3-1 details](#table-slot-spatial-audio-wwise-unity-markdown-1-3-1) |
| [spatial-audio-wwise-unity-markdown-1-4-0 details](#table-slot-spatial-audio-wwise-unity-markdown-1-4-0) | [spatial-audio-wwise-unity-markdown-1-4-1 details](#table-slot-spatial-audio-wwise-unity-markdown-1-4-1) |

<a id="table-slot-spatial-audio-wwise-unity-markdown-1-1-0"></a>

**spatial-audio-wwise-unity-markdown-1-1-0 details**

/Wwise2023.1.6.8555/SDK/Android_arm64-v8a
/Release/bin/libAgoraWwiseRTCSDK.so

<a id="table-slot-spatial-audio-wwise-unity-markdown-1-1-1"></a>

**spatial-audio-wwise-unity-markdown-1-1-1 details**

/Assets/Wwise/API/Runtime/Plugins/Android/arm64-v8a
/DSP/libAgoraWwiseRTCSDK.so

<a id="table-slot-spatial-audio-wwise-unity-markdown-1-2-0"></a>

**spatial-audio-wwise-unity-markdown-1-2-0 details**

/Wwise2023.1.6.8555/SDK/Android_armeabi-v7a
/Release/bin/libAgoraWwiseRTCSDK.so

<a id="table-slot-spatial-audio-wwise-unity-markdown-1-2-1"></a>

**spatial-audio-wwise-unity-markdown-1-2-1 details**

/Assets/Wwise/API/Runtime/Plugins/Android/armeabi-v7a
/DSP/libAgoraWwiseRTCSDK.so

<a id="table-slot-spatial-audio-wwise-unity-markdown-1-3-0"></a>

**spatial-audio-wwise-unity-markdown-1-3-0 details**

/Wwise2023.1.6.8555/SDK/Android_x86
/Release/bin/libAgoraWwiseRTCSDK.so

<a id="table-slot-spatial-audio-wwise-unity-markdown-1-3-1"></a>

**spatial-audio-wwise-unity-markdown-1-3-1 details**

/Assets/Wwise/API/Runtime/Plugins/Android/x86
/DSP/libAgoraWwiseRTCSDK.so

<a id="table-slot-spatial-audio-wwise-unity-markdown-1-4-0"></a>

**spatial-audio-wwise-unity-markdown-1-4-0 details**

/Wwise2023.1.6.8555/SDK/Android_x86_64
/Release/bin/libAgoraWwiseRTCSDK.so

<a id="table-slot-spatial-audio-wwise-unity-markdown-1-4-1"></a>

**spatial-audio-wwise-unity-markdown-1-4-1 details**

/Assets/Wwise/API/Runtime/Plugins/Android/x86_64
/DSP/libAgoraWwiseRTCSDK.so

</Accordion>

<Accordion title="iOS">

| 源文件 | 拷贝到 Unity 项目目录 |
| --- | --- |
| [spatial-audio-wwise-unity-markdown-2-1-0 details](#table-slot-spatial-audio-wwise-unity-markdown-2-1-0) | [spatial-audio-wwise-unity-markdown-2-1-1 details](#table-slot-spatial-audio-wwise-unity-markdown-2-1-1) |
| [spatial-audio-wwise-unity-markdown-2-2-0 details](#table-slot-spatial-audio-wwise-unity-markdown-2-2-0) | [spatial-audio-wwise-unity-markdown-2-2-1 details](#table-slot-spatial-audio-wwise-unity-markdown-2-2-1) |
| [spatial-audio-wwise-unity-markdown-2-3-0 details](#table-slot-spatial-audio-wwise-unity-markdown-2-3-0) | [spatial-audio-wwise-unity-markdown-2-3-1 details](#table-slot-spatial-audio-wwise-unity-markdown-2-3-1) |
| [spatial-audio-wwise-unity-markdown-2-4-0 details](#table-slot-spatial-audio-wwise-unity-markdown-2-4-0) | [spatial-audio-wwise-unity-markdown-2-4-1 details](#table-slot-spatial-audio-wwise-unity-markdown-2-4-1) |

<a id="table-slot-spatial-audio-wwise-unity-markdown-2-1-0"></a>

**spatial-audio-wwise-unity-markdown-2-1-0 details**

/Wwise2023.1.6.8555/SDK/iOS_Xcode1500
/Release-iphoneos/lib/libAgoraWwiseRTCSDKSource.a

<a id="table-slot-spatial-audio-wwise-unity-markdown-2-1-1"></a>

**spatial-audio-wwise-unity-markdown-2-1-1 details**

/Assets/Wwise/API/Runtime/Plugins/iOS
/iphoneos/DSP/libAgoraWwiseRTCSDKSource.a

<a id="table-slot-spatial-audio-wwise-unity-markdown-2-2-0"></a>

**spatial-audio-wwise-unity-markdown-2-2-0 details**

/Wwise2023.1.6.8555/SDK/include/AK
/Plugin/AgoraWwiseRTCSDKSourceFactory.h

<a id="table-slot-spatial-audio-wwise-unity-markdown-2-2-1"></a>

**spatial-audio-wwise-unity-markdown-2-2-1 details**

Assets/Wwise/API/Runtime/Plugins/iOS
/iphoneos/DSP/AgoraWwiseRTCSDKSourceFactory.h

<a id="table-slot-spatial-audio-wwise-unity-markdown-2-3-0"></a>

**spatial-audio-wwise-unity-markdown-2-3-0 details**

/Wwise2023.1.6.8555/SDK/iOS_Xcode1500
/Release-iphonesimulator/lib/libAgoraWwiseRTCSDKSource.a

<a id="table-slot-spatial-audio-wwise-unity-markdown-2-3-1"></a>

**spatial-audio-wwise-unity-markdown-2-3-1 details**

/Assets/Wwise/API/Runtime/Plugins/iOS
/iphonesimulator/DSP/libAgoraWwiseRTCSDKSource.a

<a id="table-slot-spatial-audio-wwise-unity-markdown-2-4-0"></a>

**spatial-audio-wwise-unity-markdown-2-4-0 details**

/Wwise2023.1.6.8555/SDK/include/AK
/Plugin/AgoraWwiseRTCSDKSourceFactory.h

<a id="table-slot-spatial-audio-wwise-unity-markdown-2-4-1"></a>

**spatial-audio-wwise-unity-markdown-2-4-1 details**

/Assets/Wwise/API/Runtime/Plugins/iOS
/iphonesimulator/DSP/AgoraWwiseRTCSDKSourceFactory.h

</Accordion>

<Accordion title="macOS">

| 源文件 | 拷贝到 Unity 项目目录 |
| --- | --- |
| [spatial-audio-wwise-unity-markdown-3-1-0 details](#table-slot-spatial-audio-wwise-unity-markdown-3-1-0) | [spatial-audio-wwise-unity-markdown-3-1-1 details](#table-slot-spatial-audio-wwise-unity-markdown-3-1-1) |

<a id="table-slot-spatial-audio-wwise-unity-markdown-3-1-0"></a>

**spatial-audio-wwise-unity-markdown-3-1-0 details**

/Wwise2023.1.6.8555/SDK/Mac_Xcode1500
/Release/bin/libAgoraWwiseRTCSDK.dylib

<a id="table-slot-spatial-audio-wwise-unity-markdown-3-1-1"></a>

**spatial-audio-wwise-unity-markdown-3-1-1 details**

/Assets/Wwise/API/Runtime/Plugins/Mac
/DSP/libAgoraWwiseRTCSDK.bundle

:::warning[注意]
将文件拷贝过去后需要将文件后缀名从 `.dylib` 修改为 `.bundle`。
:::

</Accordion>

<Accordion title="Windows">

| 源文件 | 拷贝到 Unity 项目目录 |
| --- | --- |
| [spatial-audio-wwise-unity-markdown-4-1-0 details](#table-slot-spatial-audio-wwise-unity-markdown-4-1-0) | [spatial-audio-wwise-unity-markdown-4-1-1 details](#table-slot-spatial-audio-wwise-unity-markdown-4-1-1) |
| [spatial-audio-wwise-unity-markdown-4-2-0 details](#table-slot-spatial-audio-wwise-unity-markdown-4-2-0) | [spatial-audio-wwise-unity-markdown-4-2-1 details](#table-slot-spatial-audio-wwise-unity-markdown-4-2-1) |

<a id="table-slot-spatial-audio-wwise-unity-markdown-4-1-0"></a>

**spatial-audio-wwise-unity-markdown-4-1-0 details**

/Wwise2023.1.6.8555/SDK/Win32_vc160
/Release/bin/AgoraWwiseRTCSDK.dll

<a id="table-slot-spatial-audio-wwise-unity-markdown-4-1-1"></a>

**spatial-audio-wwise-unity-markdown-4-1-1 details**

/Assets/Wwise/API/Runtime/Plugins/Windows/x86
/DSP/AgoraWwiseRTCSDK.dll

<a id="table-slot-spatial-audio-wwise-unity-markdown-4-2-0"></a>

**spatial-audio-wwise-unity-markdown-4-2-0 details**

/Wwise2023.1.6.8555/SDK/x64_vc160
/Release/bin/AgoraWwiseRTCSDK.dll

<a id="table-slot-spatial-audio-wwise-unity-markdown-4-2-1"></a>

**spatial-audio-wwise-unity-markdown-4-2-1 details**

/Assets/Wwise/API/Runtime/Plugins/Windows/x86_64
/DSP/AgoraWwiseRTCSDK.dll

</Accordion>
</Accordions>
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="unity" platform="unreal" />
声网支持你通过 SDK 或 Wwise 插件实现空间音效，两种方案的选型详见[适用场景](/zh-CN/solutions/game-voice#适用场景)。本文介绍如何通过声网 Wwise 插件在你的 Unreal Engine 项目中实现空间音频。

## Wwise 插件概述 [#wwise-插件概述]

声网提供的 Wwise 插件主要用于数据流传输，可与声网 RTC SDK 结合使用，增强 RTC SDK 使用时的灵活性。

| 声网插件名称 | 插件类别 | 插件用途 |
| ------------------------- | ----------------- | ----------------------------------------------- |
| AgoraAudioInputSource | Wwise Source 插件 | 将 RTC SDK 采集的本地用户音频数据传输给 Wwise |
| AgoraReceiveSource | Wwise Source 插件 | 将 RTC SDK 接收到的远端用户音频数据传输给 Wwise |
| AgoraSendEffect | Wwise Effect 插件 | 将用户音频数据发送给声网服务器 |
| AgoraAudioSessionEffect | Wwise Effect 插件 | 用于在总线上获取参考信号以进行回声消除 |

声网 Wwise 插件当前支持如下架构：

- Android：arm64-v8a、armeabi-v7a、x86、x86_64
- iOS
- macOS
- Windows：vc160、vc170

声网 Wwise 插件里已经注册了音频观测器对象（`IAudioObserverObserver`），因此使用该插件后，你将无法再注册额外的音频观测器对象。

## 1. 准备 Wwise 环境 [#1-准备-wwise-环境]

1. 下载 [Audiokinetic Launcher](https://www.audiokinetic.com/zh/download)（也被称为 Wwise Launcher）。

2. 在 Audiokinetic Launcher 中安装 Wwise，版本号为 2021.1.14.8108。如果你需要使用其他版本，可以[联系技术支持](https://ticket.shengwang.cn/)。

## 2. 安装 Wwise 插件 [#2-安装-wwise-插件]

1. [下载](https://download.agora.io/sdk/release/AgoraAuthoringPlugin_Wwise2021_Win.zip)声网的 Wwise 插件。解压后会出现 `AgoraAuthoringPlugin_Win` 文件夹。
2. 打开 Audiokinetic Launcher 软件，在 **Plug-ins** 页面，点击 **Add from archive**，选择 `AgoraAuthoringPlugin` 文件夹，点击 **Install** 完成安装。

![安装插件](https://web-cdn.agora.io/docs-portal/img/game-voice/install-plugin.png)

安装完成后，你会在 **Plug-ins** 页面看到 **AgoraWwiseRTCSDK** 插件。

![复制 RTC SDK](https://web-cdn.agora.io/docs-portal/img/game-voice/wwise-copy-sdk.png)

## 3. 集成 Wwise 至 UE 项目 [#3-集成-wwise-至-ue-项目]

打开 Audiokinetic Launcher 软件，在 **Unreal-Engine** 页面，集成 Wwise 到你的 Unreal Engine 项目。

<Accordions>
<Accordion title="集成具体步骤">

1. 点击 **Integrate Wwise in Project...** 按钮。

![Integrate Wwise in Project](https://web-cdn.agora.io/docs-portal/img/game-voice/add-ue-to-wwise-1.png)

2. 设置如下选项，再点击 **Integrate** 按钮：

    - **Integration version**：选择 All，版本为 2021.1.14.8108。
    - **Wwise SDK**：选择 SDK（版本号为 2021.1.14.8108）的安装路径。
    - **Wwise Project**：选择 Wwise 项目文件的安装路径。

![Integration Options](https://web-cdn.agora.io/docs-portal/img/game-voice/add-ue-to-wwise-2.png)

</Accordion>
</Accordions>

## 4. 在 Wwise 项目中配置插件 [#4-在-wwise-项目中配置插件]

参考本节在 Wwise 项目中配置插件：

1. 打开你[已安装的 Wwise 软件](#1-准备-wwise-环境)并进入你的 Wwise 项目。

2. 在 **Master Audio Bus** 中添加 AgoraAudioSessionEffect 插件，用于获取参考信号以进行回声消除。

![添加 AgoraAudioSessionEffect 步骤 1](https://web-cdn.agora.io/docs-portal/img/game-voice/add-session-effect-1.png)

3. 在 **Actor-Mixer Hierarchy** 下的 **Default Work Unit** 中添加 AgoraAudioInputSource 插件，用于将本地用户音频数据传输给 Wwise。

![添加 AgoraAudioInputSource 步骤 1](https://web-cdn.agora.io/docs-portal/img/game-voice/add-audio-input-1.png)

    添加后，**Default Work Unit** 下会出现一个名为 **New Sound SFX** 的节点。为方便后续使用，建议节点改名，例如改成 Audio Input Source。

4. 在 **Actor-Mixer Hierarchy** 下的 **Default Work Unit** 中添加 AgoraReceiveSource 插件，用于将远端用户音频数据传输给 Wwise。

![添加 AgoraReceiveSource 步骤 1](https://web-cdn.agora.io/docs-portal/img/game-voice/add-audio-receive-1.png)

    添加后，**Default Work Unit** 下会出现一个名为 **New Sound SFX** 的节点。为方便后续使用，建议节点改名，例如改成 Audio Receive Source。

5. 在第 3 步添加的 **Audio Input Source** 节点中，添加 AgoraSendEffect 插件，用于将用户音频数据发送给声网服务器。

![添加 AgoraSendEffect 步骤 1](https://web-cdn.agora.io/docs-portal/img/game-voice/add-send-effect-1.png)

6. 为第 3、4 步添加的 Audio Input Source 和 Audio Receive Source 创建 Event，例如播放（Play）和停止（Stop）事件。

<Accordions type="multiple">
<Accordion title="以创建 Audio Input Source 的播放事件为例">

![Input Source 的播放事件](https://web-cdn.agora.io/docs-portal/img/game-voice/add-play-event-to-input-source.png)

</Accordion>
</Accordions>

    所有事件创建完成后，效果如下图：

![所有事件](https://web-cdn.agora.io/docs-portal/img/game-voice/all-event.png)

配置插件后，请注意当前插件暂不支持你在 Wwise 软件中进行音频调试播放。

## 5. 在 UE 项目中使用插件 [#5-在-ue-项目中使用插件]

本节介绍如何在 Unreal Engine 项目中使用 Wwise 插件。

### 修改 UE 项目 [#修改-ue-项目]

参考如下步骤修改你的 Unreal Engine 项目：

1. 将项目中集成的声网 Unreal SDK 替换成[带 Wwise 模块的 Unreal SDK](https://download.agora.io/sdk/release/AgoraPlugin.zip)。Wwise 模块对应 SDK 中的 `AgoraWwiseCommHandler` 和 `WwiseHeaderFiles` 文件夹。

| 替换前 | 替换后 |
| --- | --- |
| [spatial-audio-wwise-651-2-0 details](#table-slot-spatial-audio-wwise-651-2-0) | [spatial-audio-wwise-651-2-1 details](#table-slot-spatial-audio-wwise-651-2-1) |

<a id="table-slot-spatial-audio-wwise-651-2-0"></a>

**spatial-audio-wwise-651-2-0 details**

- SDK 来源：从[下载页](/zh-CN/solutions/game-voice/reference/downloads)获取
- SDK 文件夹名称：AgoraPlugin
- SDK 区别：不含 Wwise 模块

<a id="table-slot-spatial-audio-wwise-651-2-1"></a>

**spatial-audio-wwise-651-2-1 details**

- SDK 来源：从本节获取
- SDK 文件夹名称：AgoraPlugin
- SDK 区别：含有 Wwise 模块

2. 打开 Unreal Engine 项目，对 API 进行如下修改：

    - 在初始化的步骤中，需要**添加**如下代码，以创建并初始化声网 RTC 引擎，以及初始化声网 Wwise 插件。

        ```cpp
        // 创建并初始化 RtcEngineProxy
        RtcEngineProxy = agora::rtc::ue::createAgoraRtcEngineEx();
        int ret = RtcEngineProxy->initialize(RtcEngineContext);

        // 初始化 Wwise 插件
        // 将 RtcEngineProxy 的指针传给 AgoraWwiseCommHandler
        // 创建并指定你的 Track ID，可以将 ID 填写为类似于 0、1、2 这样的整数
        FAgoraWwiseCommHandlerAgoraInterface::InitAgoraWwisePlugin(RtcEngineProxy, m_SendTrackId);
        ```

    - 在销毁的步骤中，需要**添加**如下代码，以释放卸载声网 Wwise 插件并释放 RTC 引擎资源。

        ```cpp
        // 卸载 Wwise 插件
        FAgoraWwiseCommHandlerAgoraInterface::UninitAgoraWwisePlugin();

        if (RtcEngineProxy != nullptr) {
            // 离开频道
            RtcEngineProxy->leaveChannel();
            // 注销事件
            RtcEngineProxy->unregisterEventHandler(UserRtcEventHandlerEx.Get());
            // 释放 RTC 引擎资源
            RtcEngineProxy->release();
            // 将 RtcEngineProxy 的指针设为空
            RtcEngineProxy = nullptr;
        }
        ```

    - **修改**加入频道的代码为如下：

        ```cpp
        RtcEngineProxy->setClientRole(CLIENT_ROLE_BROADCASTER);
        RtcEngineProxy->enableAudio();

        agora::rtc::ChannelMediaOptions ChannelMediaOptions;
        ChannelMediaOptions.publishMicrophoneTrack = true;
        ChannelMediaOptions.autoSubscribeAudio = true;
        ChannelMediaOptions.autoSubscribeVideo = true;
        ChannelMediaOptions.clientRoleType = CLIENT_ROLE_TYPE::CLIENT_ROLE_BROADCASTER;
        ChannelMediaOptions.publishCustomAudioTrack = true;
        ChannelMediaOptions.publishCustomAudioTrackId = m_SendTrackId;

        LocalUID = GenLocalUID();

        // 加入频道
        int ret = RtcEngineProxy->joinChannel(TCHAR_TO_UTF8(*Token), TCHAR_TO_UTF8(*ChannelNameVal),
                                              LocalUID, ChannelMediaOptions);
        ```

    - 在开麦（即频道内发布用户音频流）的步骤中，修改代码为如下：

        ```cpp
        FString ChannelName = "ChannelId";
        agora::rtc::uid_t uid = 123;

        // 开启本地音频模块
        RtcEngineProxy->enableLocalAudio(true);

        agora::rtc::ChannelMediaOptions Options;
        // 发布麦克风采集到的音频
        Options.publishMicrophoneTrack = true;
        // 发布自定义音频
        Options.publishCustomAudioTrack = true;
        Options.publishCustomAudioTrackId = m_SendTrackId;
        // 设置用户为主播角色，主播才有发布音频流的权限
        Options.clientRoleType = CLIENT_ROLE_TYPE::CLIENT_ROLE_BROADCASTER;

        agora::rtc::RtcConnection Connection;
        std::string StdStrChannelName = TCHAR_TO_UTF8(*ChannelName);
        Connection.channelId = StdStrChannelName.c_str();
        Connection.localUid = uid;

        // 频道内更新媒体选项
        int ret = RtcEngineProxy->updateChannelMediaOptionsEx(Options, Connection);
        ```

    - 在闭麦（即频道内停止发布用户音频流）的步骤中，修改代码为如下：

        ```cpp
        FString ChannelName = "ChannelId";
        agora::rtc::uid_t uid = 123;

        // 关闭本地音频模块
        RtcEngineProxy->enableLocalAudio(false);

        agora::rtc::ChannelMediaOptions Options;
        // 禁止发布麦克风采集到的音频
        Options.publishMicrophoneTrack = false;
        // 禁止发布自定义音频
        Options.publishCustomAudioTrack = false;
        Options.publishCustomAudioTrackId = m_SendTrackId;
        Options.clientRoleType = CLIENT_ROLE_TYPE::CLIENT_ROLE_BROADCASTER;

        agora::rtc::RtcConnection Connection;
        std::string StdStrChannelName = TCHAR_TO_UTF8(*ChannelName);
        Connection.channelId = StdStrChannelName.c_str();
        Connection.localUid = uid;

        // 频道内更新媒体选项
        int ret = RtcEngineProxy->updateChannelMediaOptionsEx(Options, Connection);
        ```

### 插件使用注意事项 [#插件使用注意事项]

如果你的 UE 项目会编译运行到如下平台，使用 Wwise 插件时你需注意如下：

| 运行平台 | 注意事项 |
| --- | --- |
| iOS | [spatial-audio-wwise-unreal-cpp-html-1-1-1 details](#table-slot-spatial-audio-wwise-unreal-cpp-html-1-1-1) |
| Windows | 声网 Unreal SDK 中 ThirdParty 目录下的 `AgoraWwiseRTCSDK.dll` 和 `AgoraWwiseRTCSDK.lib` 文件会复制到你的 UE 项目中 Wwise 的 ThirdParty 目录下。最终 SDK 和 UE 项目都会依赖 Wwise 的 ThirdParty 目录下这两个文件。 |

<a id="table-slot-spatial-audio-wwise-unreal-cpp-html-1-1-1"></a>

**spatial-audio-wwise-unreal-cpp-html-1-1-1 details**

确保完成如下步骤，如果系统已自动完成，请跳过：

1. 将 Unreal SDK 中 `AgoraPlugin/Resources/WwiseHeaderFiles/*.h` 文件复制到 UE 项目中 `<project_name>/Plugins/Wwise/ThirdParty/include/AK/Plugin/*.h` 文件。

2. 打开 UE 项目中 `<project_name>/Plugins/Wwise/Source/WwiseSoundEngine/Public/Generated/AkiOSPlugins.h` 文件，添加对 `AgoraWwiseRTCSDKSourceFactory.h` 的引用，示例代码如下：

    ```cpp
    #if PLATFORM_IOS
    #include <AK/Plugin/AkToneSourceFactory.h>
    ...
    // highlight-start
    #include <AK/Plugin/AgoraWwiseRTCSDKSourceFactory.h>
    // highlight-end
    #endif
    ```

### 插件日志路径 [#插件日志路径]

- Android：`/storage/emulated/0/AgoraAudio/agora_wwise_log.txt`
- iOS：`App Sandbox/agora_wwise_log.txt`
- Windows：`C:\Users\<user_name>\AppData\Local\Agora\agora_wwise_log.txt`。如果你使用 UE4 和低于 C++17 的 C++ 语言开发，那么当前日志路径依赖于 Windows 的函数。如果遇到路径冲突或编译错误，你可以在 `AgoraCommLog.cpp` 文件中手动修改日志路径。

### API 参考 [#api-参考]

Unreal SDK 中 Wwise 模块提供如下 API，你可以按需调用：

```cpp
// 获取 Wwise 插件版本号
static std::string GetAgoraWwiseVersion();

// 初始化 Wwise 插件
static int InitAgoraWwisePlugin(agora::rtc::IRtcEngine* AgoraRtcEngineInstance,
                                int& OutDefaultCustomAudioTrackId);

// 卸载 Wwise 插件
static int UninitAgoraWwisePlugin();

// 设置 ID 之间的映射关系
// 将 Unreal SDK 中的频道 ID 和用户 ID 映射到 Wwise 的 Game Object ID
static void AWPlugin_Receive_SetUidToGameObjectIDMapping(AkGameObjectID gameObjectID,
                                                         const std::string& channelID,
                                                         const rtc::uid_t& userID);

// 获取 ID 之间的映射关系
static bool AWPlugin_Receive_GetUidByGameObjectID(AkGameObjectID gameObjectID,
                                                  std::string& channelID, rtc::uid_t& userID);

// 清除 ID 之间的映射关系
static bool AWPlugin_Receive_ClearReceiveOpenID(const std::string& channelID,
                                                const rtc::uid_t& userID);
```

- `GetAgoraWwiseVersion`：获取 Wwise 插件版本号。
- `InitAgoraWwisePlugin`：初始化 Wwise 插件。
- `UninitAgoraWwisePlugin`：卸载 Wwise 插件。
- `AWPlugin_Receive_SetUidToGameObjectIDMapping`：设置 ID 之间的映射关系。
- `AWPlugin_Receive_GetUidByGameObjectID`：获取 ID 之间的映射关系。
- `AWPlugin_Receive_ClearReceiveOpenID`：清除 ID 之间的映射关系。

ID 之间的映射关系指将 Unreal SDK 中频道 ID、用户 ID 映射到 Wwise 的 Game Object ID 的关系。开发过程中，你无需管理 Unreal SDK 与 Wwise 之间的 ID 关系，因此不推荐你调用这些方法。你只需要将 SDK 中频道 ID、用户 ID 与 UE 项目中 **Actor** 进行绑定。绑定示例如下：

<DocsImage alt="绑定 ID" src="https://web-cdn.agora.io/docs-portal/img/game-voice/id-mapping.png" displayWidth="50%" />

## 6. 实现空间音频 [#6-实现空间音频]

完成上述步骤后，你可以利用 Wwise 的基础功能构建空间音频效果，详见 [Wwise 官方社区博文](https://blog.audiokinetic.com/zh/building-spatial-audio-effects-using-wwise/)。
<_PlatformProcessedMarker close="true" />
</_PlatformTabsGroup>
