Vivox Unity SDK 16.0.0 upgrade guide
Note: Follow this guide if you are upgrading from Vivox Unity version 15.1.x or earlier.
This guide provides details on how to upgrade to Vivox Unity SDK version 16.0.0 and highlights the differences between the two SDK versions.
Version 16.0.0 introduces simplified functionalities and requires changes in areas related too:
- SDK Initialization
- Login / Logout
- Blocking Players
- Connecting to Channels
- Channel participant management
- Audio device management
- Setting active device
- Setting device gain/volume
- Device muting
SDK setup and initialization
Replace using VivoxUnity;
with using Unity.Services.Vivox;
to access Vivox APIs.
The VivoxUnity namespace no longer exists.
Additionally, the Client, which was the original way to initialize the SDK, no longer exists.
Using Authentication
Note: If you are using credentials from the Vivox Developer Portal, skip this section and jump to the Vivox Developer Portal Credentials section.
If you are using the Unity Authentication package, await UnityServices.InitializeAsync()
first, followed by an await AuthenticationService.Instance.SignInAnonymously()
, before calling await VivoxService.Instance.InitializeAsync()
, as shown in the following example:
async void InitializeAsync()
{
await UnityServices.InitializeAsync();
await AuthenticationService.Instance.SignInAnonymouslyAsync();
await VivoxService.Instance.InitializeAsync();
}
You can also use any of the other sign in options provided by the AuthenticationService.Instance
as well.
If the project uses Unity Dashboard credentials but does not use the AuthenticationService package, you can enable Test Mode and omit the AuthenticationService
sign-in call.
To turn on Test Mode, in the Unity Editor, you can go to Project Settings > Services > Vivox and check the box labeled Test Mode.
Note: Enabling Test Mode caches the project’s token signing key on the client and should only be used for testing purposes. Test Mode should be toggled off once a secure server that can vend Vivox Access Tokens to the game client has been provisioned. Disabling Test Mode will remove the token signing key from the project.
The following example shows the initialization setup without the AuthenticationService package and with Test Mode enabled:
async void InitializeAsync()
{
await UnityServices.InitializeAsync();
await VivoxService.Instance.InitializeAsync();
}
Using Vivox Developer Portal credentials
If you have legacy Vivox Developer Portal credentials, provide these credentials to VivoxService.Instance.InitializeAsync
through InitializationOptions
. These credentials can include the signing key for testing purposes.
The following example shows the initialization setup with Vivox Developer Portal credentials:
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();
}
Note: Before you release your application, remove the signing key, ‘_key’ in the above example, from your options.SetVivoxCredentials(...)
call. This also assumes that a server capable of vending Vivox Access Tokens to the game client has been provisioned.
Login lifecycle changes
ILoginSession.BeginLogin
has been replaced by VivoxService.Instance.LoginAsync(LoginOptions options = null)
to log in to the Vivox service.
LoginOptions
contains properties for:
- DisplayName
- Enabling text-to-speech
- Disabling automatic channel transmission swapping when joining a new channel
- Caching a list of PlayerIDs to be blocked (cross-muted) for the current player upon logging in
- Setting the rate at which the SDK receives participant update events
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()
has been replaced by VivoxService.Instance.LogoutAsync
for logging out of the Vivox Service.
Move any logic tied to a LoginSession.PropertyChanged
event with the PropertyName "State" and either the LoginState.LoggedIn
or LoginState.LoggedOut
to a different function. Split out the logic for login and logout to trigger on VivoxService.Instance.LoggedIn
and VivoxService.Instance.LoggedOut
separately, as shown in the following example.
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.
}
Blocking players
ILoginSession.SetCrossMutedCommunications
has been replaced by VivoxServince.Instance.BlockPlayerAsync(string playerId)
and VivoxService.Instance.UnblockPlayerAsync(string playerId)
which now require a playerId
instead of an AccountId
as input.
Channel lifecycle changes
Joining and leaving channels
All logic related to ChannelSession.BeginConnect
has been replaced by the following methods:
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);
Note: Set ChatCapability to Text, Audio, or TextandAudio according to channel communication capabilities.
ChannelSession.Disconnect()
has been replaced by:
VivoxService.Instance.LeaveChannelAsync(string channelName)
to leave a specific channel.VivoxService.Instance.LeaveAllChannelsAsync()
to leave all active channels. We recommend using this method if only a single channel is joined at any time.
ILoginSession.ChannelSessions
functionality is replaced by VivoxService.Instance.ActiveChannels
.
VivoxService.Instance.ActiveChannels
is a dictionary with all currently active channels as keys, and the list of all channels VivoxParticipants
as values.
Implementations previously depended on AudioState
and TextState
to determine if the user was connected to the channel. Replace events tracking state changes of those two properties with functions tied to VivoxService.Instance.ChannelJoined
, and VivoxService.Instance.ChannelLeft
.
VivoxService.Instance.ChannelJoined
and VivoxService.Instance.ChannelLeft
will provide the channel name of the channel joined or left to any callbacks bound to the events.
The follow code sample is an example of these changes:
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.
}
Channel transmission
By default, Channel transmission (the channel being spoken into) switches to the most recently joined channel. You can disable this by setting LoginOptions.DisableAutomaticChannelTransmissionSwap
to true before calling VivoxService.Instance.LoginAsync
with that LoginOptions object as input.
You can change the channel transmission mode manually by using the VivoxService.Instance.SetChannelTransmissionModeAsync(TransmissionMode transmissionMode, string channelName = null)
method.
This API can set a specific channel, all channels, or no channels as the transmitting channel(s) based on the method’s input.
Channel participant management
VivoxParticipant has replaced ChannelParticipant.
You can access a collection of each active channel’s VivoxParticipant collection by retrieving the value from a VivoxService.Instance.ActiveChannels
index provided a correct key (channel name) is used.
Use VivoxService.Instance.ParticipantAddedToChannel
and VivoxServince.Instance.ParticipantRemovedFromChannel
to know when a VivoxParticipant was added or removed from a channel.
The events will provide the relevant VivoxParticipant as input to any callbacks bound to them. The VivoxParticipant object contains information about the PlayerId of the participant, the name of the channel the participant joined or left, and other valuable information, including whether the participant is the local player or their display name. These types of events are shown in the following examples:
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 objects
VivoxParticipant
contains information about the current state of the participant, such as:
VivoxParticipant.IsSelf
, which states if the participant represents the local player.VivoxParticipant.SpeechDetected
, which states if the participant's audio energy passed the threshold to be considered speech by the Vivox SDK.
VivoxParticipant also contains the events:
ParticipantMuteStateChanged
ParticipantSpeechDetected
ParticipantAudioEnergyChanged
You can use these events to create a functional volume unit (VU) meter or speech indicator. Connect these events at the individual UI level for each participant.
Note: The object that they are a part of should have a reference to the Participant being represented to easily update the UI.
The following sample class is a simplified version of the RosterItem in the ChatChannelSample:
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
}
}
Muting channel participants
VivoxParticipant.MutePlayerLocally()
and VivoxParticipant.UnmutePlayerLocally()
can be used to mute/unmute a specific participant in a channel.
Note: These VivoxParticipant mute/unmute APIs will not affect the local player.
Audio device management
Device management is no longer achieved by leveraging the Client object. You can now make any device adjustments such as muting, changing the volume, or switching the active device using the VivoxService.Instance
.
Muting the local player
Muting yourself locally has changed to utilize the functions VivoxService.Instance.MuteInputDevice()
and VivoxService.Instance.UnmuteInputDevice()
instead of having to do this through APIs on an IAudioDevice object, or switching the channel transmission to none.
These APIs will mute or unmute the local user’s input device.
Adjusting input/output device volume
You can now adjust device volume by using VivoxService.Instance.SetInputDeviceVolume(int value)
and
VivoxService.Instance.SetOutputDeviceVolume(int value)
.
Changing the active input/output device
Adjusting the active input or output device can be achieved by calling either VivoxService.Instance.SetActiveOutputDeviceAsync(VivoxOutputDevice device)
or
VivoxService.Instance.SetActiveInputDeviceAsync(VivoxInputDevice device)
.
A collection of VivoxInputDevices
and VivoxOutputDevices
can be retrieved by accessing the properties VivoxService.Instance.AvailableInputDevices
and VivoxService.Instance.AvailableOututDevices
.
The following example demonstrates how to use the Vivox SDK audio device APIs to populate a dropdown list of input devices that provides functionality for changing the active input device.
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());
}
}
Note: This is a simplified version of the AudioDeviceSettings class used in our ChatChannelSample sample that demonstrates how to change the active input/output device, adjust input/output device volume, and react to device list changes.