Vivox Unity SDK 16.0.0 升级指南
注意:如果要从 Vivox Unity 版本 15.1.x 或更低版本进行升级,请遵循本指南。
本指南详细介绍如何升级到 Vivox Unity SDK 版本 16.0.0,并重点讨论两个 SDK 版本之间的差异。
版本 16.0.0 推出了简化的功能,并在以下相关方面也进行了更改:
- SDK 初始化
- 登录/注销
- 屏蔽玩家
- 连接到频道
- 频道参与者管理
- 音频设备管理
- 设置活动设备
- 设置设备增益/音量
- 设备静音
SDK 设置和初始化
将 using VivoxUnity;
替换为 using Unity.Services.Vivox;
以访问 Vivox API。
VivoxUnity 命名空间不再存在。
此外,客户端(用于初始化 SDK 的原始方式)已不复存在。
使用 Authentication
注意:如果您使用的是 Vivox 开发者门户中的凭据,请跳过此部分并跳转到“Vivox 开发者门户凭据”部分。
如果您使用的是 Unity Authentication 包,请依次调用 await UnityServices.InitializeAsync()
、await AuthenticationService.Instance.SignInAnonymously()
、await VivoxService.Instance.InitializeAsync()
,如以下示例所示:
async void InitializeAsync()
{
await UnityServices.InitializeAsync();
await AuthenticationService.Instance.SignInAnonymouslyAsync();
await VivoxService.Instance.InitializeAsync();
}
还可以使用 AuthenticationService.Instance
提供的任何其他登录选项。
如果项目使用 Unity Dashboard(Unity 后台)凭据但未使用 AuthenticationService 包,则可以启用测试模式并省略 AuthenticationService
登录调用。要打开测试模式,请在 Unity 编辑器中转到 Project Settings > Services > Vivox 并选中标有 Test Mode 的框。
注意:启用测试模式会在客户端上缓存项目的令牌签名密钥,只能用于测试目的。一旦配置了可以向游戏客户端供应 Vivox 访问令牌的安全服务器,就应关闭测试模式。禁用测试模式将从项目中移除令牌签名密钥。
以下示例显示了未使用 AuthenticationService 包但启用了测试模式的初始化设置:
async void InitializeAsync()
{
await UnityServices.InitializeAsync();
await VivoxService.Instance.InitializeAsync();
}
使用 Vivox 开发者门户凭据
如果您有旧版 Vivox 开发者门户凭据,请通过 InitializationOptions
向 VivoxService.Instance.InitializeAsync
提供这些凭据。这些凭据可以包含用于测试目的的签名密钥。
以下示例显示了使用 Vivox 开发者门户凭据的初始化设置:
async void InitializeAsync()
{
InitializationOptions options = new InitalizationOptions();
// _key can be excluded from SetVivoxCredentials if an implementation of IVivoxTokenProvider has been provided to the SDK.
options.SetVivoxCredentials(_server, _domain, _issuer, _key);
await UnityServices.InitializeAsync(options);
await VivoxService.Instance.InitializeAsync();
}
注意:在发布应用程序之前,请从 options.SetVivoxCredentials(...)
调用中移除签名密钥(上述示例中的“_key”)。此处还假设已经预配了能够向游戏客户端供应 Vivox 访问令牌的服务器。
登录生命周期更改
ILoginSession.BeginLogin
已替换为 VivoxService.Instance.LoginAsync(LoginOptions options = null)
用于登录 Vivox 服务。
LoginOptions
包含以下各项的属性:
- DisplayName
- 启用文本转语音
- 加入新频道时禁用自动频道传输交换
- 缓存登录时要为当前玩家屏蔽(交叉静音)的 PlayerID 列表
- 设置 SDK 接收参与者更新事件的速率
async void LoginToVivoxAsync(List<string> blockedList, string displayName)
{
LoginOptions options = new LoginOptions();
options.DisplayName = displayName;
options.BlockedUserList = blockedList;
await VivoxService.Instance.LoginAsync(options);
}
ILoginSession.Logout()
已替换为 VivoxService.Instance.LogoutAsync
用于注销 Vivox 服务。
将任何绑定到 LoginSession.PropertyChanged
事件的逻辑(其 PropertyName 为“State”)和 LoginState.LoggedIn
或 LoginState.LoggedOut
都移动到其他函数。拆分 login 和 logout 的逻辑以分别在 VivoxService.Instance.LoggedIn
和 VivoxService.Instance.LoggedOut
上触发,如以下示例所示。
void Start()
{
VivoxService.Instance.LoggedIn += OnUserLoggedIn;
VivoxService.Instance.LoggedOut += OnUserLoggedOut;
}
void OnDestroy()
{
//Cleanup events if the GameObject is destroyed to prevent unexpected behavior.
VivoxService.Instance.LoggedIn -= OnUserLoggedIn;
VivoxService.Instance.LoggedOut -= OnUserLoggedOut;
}
void OnUserLoggedIn()
{
Debug.Log("The user has successfully logged in");
// Other logic such as attempting a default channel join or changing the state of voice UIs to indicate the character is logged in can be done here.
}
void OnUserLoggedOut()
{
Debug.Log("The user has logged out");
// The LoggedOut event will fire after a VivoxService.Instance.LogoutAsync call has been completed successfully
// or after an internet disruption has caused Automatic Connection Recovery to declare the attempted recovery a failure.
}
屏蔽玩家
ILoginSession.SetCrossMutedCommunications
已被 VivoxServince.Instance.BlockPlayerAsync(string playerId)
和 VivoxService.Instance.UnblockPlayerAsync(string playerId)
取代,后两者现在需要 playerId
而不是 AccountId
作为输入。
频道生命周期更改
加入和离开频道
所有与 ChannelSession.BeginConnect
相关的逻辑都已替换为以下方法:
JoinGroupChannelAsync(string channelName, ChatCapability chatCapability, ChannelOptions channelOptions = null);
JoinPositionalChannelAsync(string channelName, ChatCapability chatCapability, Channel3DProperties positionalChannelProperties, ChannelOptions channelOptions = null);
JoinEchoChannelAsync(string channelName, ChatCapability chatCapability, ChannelOptions channelOptions = null);
注意:根据频道通信能力,将 ChatCapability 设置为 Text、Audio 或 TextandAudio。
ChannelSession.Disconnect()
已替换为:
VivoxService.Instance.LeaveChannelAsync(string channelName)
,用于离开特定频道。VivoxService.Instance.LeaveAllChannelsAsync()
,用于离开所有活动频道。如果任何时候只加入一个频道,我们建议使用此方法。
ILoginSession.ChannelSessions
功能被替换为 VivoxService.Instance.ActiveChannels
。
VivoxService.Instance.ActiveChannels
是一个字典,其中所有当前活动频道作为键,所有频道的列表 VivoxParticipants
作为值。
以前在实现中依赖 AudioState
和 TextState
来确定用户是否已连接到频道。现在已将跟踪这两个属性的状态更改的事件替换为与 VivoxService.Instance.ChannelJoined
和 VivoxService.Instance.ChannelLeft
相关的函数。
VivoxService.Instance.ChannelJoined
和 VivoxService.Instance.ChannelLeft
将向绑定到事件的任何回调提供加入或离开的频道的频道名称。
以下代码示例是这些更改的示例:
void BindToChannelActions()
{
//Connecting/Disconnecting channel actions can be done upon VivoxService.Instance.LoggedIn and LoggedOut events being fired, respectively,
//for basic lifecycle control
VivoxService.Instance.ChannelJoined += OnChannelJoined;
VivoxService.Instance.ChannelLeft += OnChannelLeft;
}
void UnbindChannelActions()
{
VivoxService.Instance.ChannelJoined -= OnChannelJoined;
VivoxService.Instance.ChannelLeft -= OnChannelLeft;
}
void OnChannelJoined(string channelName)
{
//The channel with name channelName has been successfully joined, and any UI updates should be done for it
//Additionally, if multiple channels are being handled, keeping track of the channelName and knowing which channel is for which purpose should be done
//on the side of the implementation based on this event.
}
void OnChannelLeft(string channelName)
{
//The channel with name channelName has been successfully left, and any UI updates should be done for it
//This also means that the channelName can likely be safely lost, although if the channelName is specific and might be rejoined,
//it should be held on to by the implementation.
}
频道传输
默认情况下,频道传输(语音进入的频道)切换到最近加入的频道。若要禁用此功能,可在使用该 LoginOptions 对象作为输入调用 VivoxService.Instance.LoginAsync
之前将 LoginOptions.DisableAutomaticChannelTransmissionSwap
设置为 true。
可以使用 VivoxService.Instance.SetChannelTransmissionModeAsync(TransmissionMode transmissionMode, string channelName = null)
方法手动更改频道传输模式。
此 API 可以根据该方法的输入,将传输频道设置为特定频道、所有频道或无任何传输频道。
频道参与者管理
VivoxParticipant 已取代 ChannelParticipant。
如果使用了正确的键(频道名称),可以通过从 VivoxService.Instance.ActiveChannels
索引中获取值来访问每个活动频道的 VivoxParticipant 集合。
使用 VivoxService.Instance.ParticipantAddedToChannel
和 VivoxServince.Instance.ParticipantRemovedFromChannel
可以了解何时在频道中添加或移除了 VivoxParticipant。
这些事件将提供相关的 VivoxParticipant 作为绑定到这些事件的任何回调的输入。VivoxParticipant 对象包含参与者的 PlayerId、参与者加入或离开的频道名称以及其他有价值的信息,包括参与者是否为本地玩家或玩家的显示名称。以下示例显示了这些类型的事件:
void BindToParticipantEvents()
{
//These events can be connected at the same time as the channel events from the previous sections for convenience purposes
VivoxService.Instance.ParticipantAddedToChannel += OnParticipantAdded;
VivoxService.Instance.ParticipantRemovedFromChannel += OnParticipantRemoved;
}
void UnbindParticipantEvents()
{
VivoxService.Instance.ParticipantAddedToChannel -= OnParticipantAdded;
VivoxService.Instance.ParticipantRemovedFromChannel -=OnParticipantRemoved;
}
void OnParticipantAdded(VivoxParticipant participant)
{
// Use VivoxParticipant to establish some UI element tied to that specific VivoxParticipant, which can then be used to control things such as muting
// volume, and blocking, along with UI that can track certain states - such as whether the player is currently muted or is currently speaking.
}
void OnParticipantRemoved(VivoxParticipant participant)
{
// At this point, any UI created to display information about this VivoxParticipant can be safely disposed of.
}
VivoxParticipant 对象
VivoxParticipant
包含有关参与者当前状态的信息,例如:
VivoxParticipant.IsSelf
,指明参与者是否代表本地玩家。VivoxParticipant.SpeechDetected
,指明参与者的音频能量是否超过了 Vivox SDK 将音频视为语音的阈值。
VivoxParticipant 还包含以下事件:
ParticipantMuteStateChanged
ParticipantSpeechDetected
ParticipantAudioEnergyChanged
这些事件可用于创建功能音量单位 (VU) 计量表或语音指示器。请在每个参与者的单个 UI 级别连接这些事件。
注意:这些事件所属的对象应具有对所表示的参与者的引用,以便轻松更新 UI。
以下示例类是 ChatChannelSample 中的 RosterItem 的简化版本:
public class RosterItem : MonoBehaviour
{
public VivoxParticipant Participant;
public Text PlayerNameText;
public void SetupRosterItem(VivoxParticipant participant)
{
Participant = participant;
PlayerNameText.text = Participant.DisplayName;
Participant.ParticipantMuteStateChanged += OnMuteStateChanged;
Participant.ParticipantSpeechDetected += OnSpeechDetected;
}
void OnMuteStateChanged()
{
if(Participant.IsMuted)
{
//Participant has been muted
}
else
{
//Participant has been unmuted
}
}
void OnSpeechDetected()
{
//Participant AudioEnergy has exceeded the value required to be considered speech
}
}
将频道参与者静音
VivoxParticipant.MutePlayerLocally()
和 VivoxParticipant.UnmutePlayerLocally()
可用于将频道中的特定参与者静音/取消静音。
注意:这些 VivoxParticipant 静音/取消静音 API 不会影响本地玩家。
音频设备管理
设备管理不再通过利用 Client 对象来实现。现在可以进行任何设备调整,例如静音、更改音量或使用 VivoxService.Instance
切换活动设备。
将本地玩家静音
本地玩家静音已更改为使用 VivoxService.Instance.MuteInputDevice()
和 VivoxService.Instance.UnmuteInputDevice()
函数,而不必通过 IAudioDevice 对象上的 API 或将频道传输切换为 none 来实现此目的。这些 API 会将本地用户的输入设备静音或取消静音。
调节输入/输出设备音量
现在可以使用 VivoxService.Instance.SetInputDeviceVolume(int value)
和 VivoxService.Instance.SetOutputDeviceVolume(int value)
来调整设备音量。
更改活动输入/输出设备
可以通过调用 VivoxService.Instance.SetActiveOutputDeviceAsync(VivoxOutputDevice device)
或 VivoxService.Instance.SetActiveInputDeviceAsync(VivoxInputDevice device)
来调整活动输入/输出设备。
可以通过访问属性 VivoxService.Instance.AvailableInputDevices
和 VivoxService.Instance.AvailableOututDevices
来获取 VivoxInputDevices
和 VivoxOutputDevices
的集合。
以下示例演示如何使用 Vivox SDK 音频设备 API 来填充输入设备的下拉列表,而该列表可用于更改活动输入设备。
using System.Linq;
using Unity.Services.Vivox;
using UnityEngine;
using UnityEngine.UI;
public class AudioDeviceSettings : MonoBehaviour
{
public Dropdown InputDeviceDropdown;
private void Start()
{
VivoxService.Instance.AvailableInputDevicesChanged += RefreshInputDeviceList;
InputDeviceDropdown.onValueChanged.AddListener((i) =>
{
InputDeviceValueChanged(i);
});
}
void OnEnable()
{
RefreshInputDeviceList();
}
void OnDestroy()
{
// Unbind all UI actions
InputDeviceDropdown.onValueChanged.RemoveAllListeners();
VivoxService.Instance.AvailableInputDevicesChanged -= RefreshInputDeviceList;
}
private void RefreshInputDeviceList()
{
InputDeviceDropdown.Hide();
InputDeviceDropdown.ClearOptions();
InputDeviceDropdown.options.AddRange(VivoxService.Instance.AvailableInputDevices.Select(v => new Dropdown.OptionData() { text = v.DeviceName }));
InputDeviceDropdown.SetValueWithoutNotify(InputDeviceDropdown.options.FindIndex(option => option.text == VivoxService.Instance.ActiveInputDevice.DeviceName));
InputDeviceDropdown.RefreshShownValue();
}
void InputDeviceValueChanged(int index)
{
VivoxService.Instance.SetActiveInputDeviceAsync(VivoxService.Instance.AvailableInputDevices.Where(device => device.DeviceName == InputDeviceDropdown.options[index].text).First());
}
}
注意:这是 ChatChannelSample 示例中使用的 AudioDeviceSettings 类的简化版本,演示了如何更改活动输入/输出设备、调节输入/输出设备音量以及对设备列表更改做出反应。