关于 setup-vivox-voice-chat
面向 Unity 开发的 Vivox 编码技能,指导使用 v16+ SDK 实现语音和文字聊天。重点涵盖当前 API、初始化与事件处理顺序,以及避免旧版 v4 用法。
主要功能
- 01Vivox v16+ API 指引
- 02语音与文字频道设置
- 03频道及定向消息
- 04事件订阅与清理
- 05故障排查与平台说明
适用场景
- 01为 Unity 游戏添加语音聊天
- 02实现空间音频或群组频道
- 03构建频道或定向文字聊天
- 04检查 Vivox 集成中的常见错误
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ unity-technologies/ skills --skill setup-vivox-voice-chat安装后在 Claude Code 中输入/setup-vivox-voice-chat确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/events-and-participants.mdinit-and-login.mdtext-chat.mdtroubleshooting.mdvoice-channels.md详细介绍
Unity Vivox — 语音与文字聊天
命名空间:Unity.Services.Vivox | 软件包:com.unity.services.vivox
配套软件包:Unity.Services.Core、Unity.Services.Authentication
Vivox v16+ 用单一静态入口 VivoxService.Instance 取代了 v4 的 Client / ILoginSession / IChannelSession 模型。所有操作——初始化、登录、加入频道、消息收发和静音——都通过该入口进行。请勿使用 v4 模式(Client.Instance、AccountId、ChannelId、ILoginSession、UnityPurchasing.* 等);这些模式在 v16 中已被移除。
文档导航
如果具体信息存在差异,请以 Unity Vivox 精选文档导航为准,而不要依赖记忆;其中包含主题、API 和错误代码的权威信息。本技能及其参考资料定义了如何应用 SDK;该资源定义了有哪些文档。绝不要向用户提及 llms.txt 文件名。如果无法访问该资源,请以本技能的参考资料及工作区中已安装的软件包(Package Manager / 源代码)为准。
详细参考资料
按需阅读——仅在需要了解本文未涵盖的签名、事件详情或平台注意事项时阅读。
- 初始化、登录和访问令牌: references/init-and-login.md
- 语音频道(位置相关和非位置相关): references/voice-channels.md
- 文字聊天(频道消息和定向消息): references/text-chat.md
- 事件、参与者和清理: references/events-and-participants.md
- 故障排除和平台注意事项: references/troubleshooting.md
初始化顺序(请勿跳过步骤)
正确顺序是 UGS Core → Authentication 登录 → Vivox 初始化 → Vivox 登录。跳过步骤或调整顺序可能导致静默失败或抛出难以理解的错误。
using Unity.Services.Core;
using Unity.Services.Authentication;
using Unity.Services.Vivox;
async void Start()
{
await UnityServices.InitializeAsync();
await AuthenticationService.Instance.SignInAnonymouslyAsync();
await VivoxService.Instance.InitializeAsync();
// subscribe to events (see table below) BEFORE calling LoginAsync
await VivoxService.Instance.LoginAsync(new LoginOptions { DisplayName = "Bob" });
}
- 调用两次
VivoxService.Instance.InitializeAsync()会抛出5041 VxErrorAlreadyInitialized。请防止场景重新加载时重复初始化。 - 如果未使用 Unity Authentication(
AuthenticationService),玩家身份会回退为按会话生成的 GUID——显示名称仍可正常使用,但无法跨会话识别身份。有关 Vivox Access Token (VAT) 替代方案,请参阅 references/init-and-login.md。
加入频道
Vivox 有三种加入方法,分别对应三种频道类型。这些方法均为异步操作,但加入操作通过 ChannelJoined 事件完成,而不是通过等待调用完成——请先订阅事件,再调用方法。
| 方法 | 用途 |
|---|---|
VivoxService.Instance.JoinGroupChannelAsync(name, ChatCapability, ChannelOptions?) | 非位置相关(派对、团队、大厅、公会) |
VivoxService.Instance.JoinEchoChannelAsync(name, ChatCapability, ChannelOptions?) | 测试频道,会将你自己的音频回传 |
VivoxService.Instance.JoinPositionalChannelAsync(name, ChatCapability, Channel3DProperties, ChannelOptions?) | 由变换位置驱动的 3D 空间音频 |
ChatCapability 值:TextOnly、AudioOnly、TextAndAudio。
限制: 每位用户最多可加入 10 个非位置相关频道;每个频道最多可有 200 位参与者。超过任一限制都会因 20502 VxXmppServerErrorServiceUnavailable 而失败。若位置相关频道需要支持超过 200 位参与者,请使用企业设置中的 Large 3D channels。
使用 VivoxService.Instance.LeaveChannelAsync(channelName) 或 LeaveAllChannelsAsync() 离开频道。有关 Channel3DProperties 字段以及 Android/iOS 上的麦克风权限处理,请参阅 references/voice-channels.md。
文本消息
频道消息(通过 TextOnly 或 TextAndAudio 广播给频道中的所有参与者):
- 发送:
VivoxService.Instance.SendChannelTextMessageAsync(string channelName, string message) - 接收:订阅
VivoxService.Instance.ChannelMessageReceived(Action<VivoxMessage>)
定向消息(点对点,无需频道):
- 发送:
VivoxService.Instance.SendDirectTextMessageAsync(string playerId, string message) - 接收:订阅
VivoxService.Instance.DirectedMessageReceived(Action<VivoxMessage>)
常见幻觉:发送方法是 SendDirectTextMessageAsync,不是 SendDirectedTextMessageAsync。不过,事件确实是 DirectedMessageReceived。请注意两者的不对称。
VivoxMessage 字段:ChannelName(定向消息时为 null)、SenderDisplayName、SenderPlayerId、MessageText、ReceivedTime、Language、FromSelf、MessageId。
编辑/删除 API(EditChannelTextMessageAsync、DeleteChannelTextMessageAsync、EditDirectTextMessageAsync、DeleteDirectTextMessageAsync)和历史记录(GetChannelTextMessageHistoryAsync、GetDirectTextMessageHistoryAsync)详见 references/text-chat.md。聊天历史记录默认保留 7 天。
必需的事件订阅
在调用相应的异步方法之前订阅事件。重新连接时,LoggedIn 可能会立即触发;ChannelJoined 会在加入完成时触发。
| 调用 | 成功事件 | 失败 / 对应事件 |
|---|---|---|
LoginAsync() | LoggedIn | LoggedOut |
JoinGroupChannelAsync() / JoinEchoChannelAsync() / JoinPositionalChannelAsync() | ChannelJoined(string channelName) | ChannelLeft(string channelName) |
| —(任意已加入的频道) | ParticipantAddedToChannel(VivoxParticipant) | ParticipantRemovedFromChannel(VivoxParticipant) |
SendChannelTextMessageAsync()(远程接收) | ChannelMessageReceived(VivoxMessage) | — |
SendDirectTextMessageAsync()(远程接收) | DirectedMessageReceived(VivoxMessage) | — |
务必在 OnDestroy / OnDisable 中取消订阅。VivoxService.Instance 是一个持久化单例——已销毁的 MonoBehaviour 上的事件处理程序会重复触发,并在场景重新加载时导致 NRE。
各参与者的事件(ParticipantMuteStateChanged、ParticipantSpeechDetected、ParticipantAudioEnergyChanged)属于从 ParticipantAddedToChannel 收到的 VivoxParticipant 实例,而非 VivoxService.Instance。请参阅 references/events-and-participants.md。
访问令牌(简述)
默认流程使用 UGS Authentication——AuthenticationService.Instance.SignInAnonymouslyAsync()(或其他登录方法)完成后,Vivox 会根据你的 UGS 项目自动生成访问令牌。标准流程无需手动编写令牌代码。
只有在使用非 UGS 身份系统,或需要频道范围的特权令牌(踢出、全体静音、转录)时,才需要在服务器端生成 Vivox 访问令牌(VAT)。语言专属的服务器示例请参阅文档索引中的“Access Token Developer Guide”部分。不要将 HMAC 签名密钥嵌入客户端。
验证
使用此包编写代码后:
- 确认项目编译时没有错误,并且
using Unity.Services.Vivox;可以正常解析。 - 确认初始化顺序:
UnityServices.InitializeAsync→AuthenticationService.Instance.SignInAnonymouslyAsync→VivoxService.Instance.InitializeAsync→VivoxService.Instance.LoginAsync。 - 不使用任何 v4 旧模式:不得使用
Client.Instance、AccountId、ChannelId、ILoginSession或IChannelSession。所有访问都通过VivoxService.Instance进行。 - 代码使用的所有事件,都必须在触发这些事件的异步调用之前订阅,并在
OnDestroy中取消订阅。 - 加入频道的代码不得通过
await等待加入调用完成。应订阅ChannelJoined,并在该事件中作出响应。 - 定向消息发送使用
SendDirectTextMessageAsync(而不是SendDirectedTextMessageAsync)。定向消息接收使用DirectedMessageReceived。 - Android 构建在加入音频频道前,应在运行时请求
RECORD_AUDIO权限;iOS 构建的 plist 中应包含NSMicrophoneUsageDescription。 - 客户端代码中不得嵌入 HMAC 签名密钥或 Vivox
SECRET/APP_ID。基于 VAT 的流程虽有文档说明,但应委托给服务端处理。