Use case: Manage voice chat
You can use the Vivox voice chat service to integrate voice channels in your rooms and facilitate collaboration between participants.
Before you start
Before you manage your voice chat, make sure you configured Vivox. Then make sure you manage your room.
How do I...?
Instantiate the Vivox voice chat service
To instantiate the Vivox service, see the following steps:
- Go to your
PlatformServices
script in yourAssets/Scripts
directory. - In your
PlatformServices
script file, update thePlatformServices
class with a public reference toIVoiceService
,IPresenceVivoxServiceComponents
, and a private reference toPresenceVivoxService
.
static VivoxService s_VivoxService;
public static IVoiceService VoiceService => s_VivoxService;
public static IPresenceVivoxServiceComponents PresenceVivoxServiceComponents => s_VivoxService;
- Initialize the services in the
InitializeAsync
method. The variables provided in the constructor are defined in get started and in the Identity authentication guide.
public static async Task InitializeAsync()
{
// ...
s_VivoxService = new PresenceVivoxService(s_ServiceHttpClient, s_PresenceManager, s_ServiceHostResolver);
// ...
}
- Initialize the UnityServices at the application level in the
InitializeUnityServices
method before doing any call to the IVoiceService.
async Task InitializeUnityServices()
{
if (UnityServices.State != ServicesInitializationState.Uninitialized)
return;
var vivoxInitializationOptions = new InitializationOptions();
vivoxInitializationOptions.SetVivoxCredentials(PresenceVivoxServiceComponents.VivoxServer, PresenceVivoxServiceComponents.VivoxDomain, PresenceVivoxServiceComponents.VivoxIssuer);
await UnityServices.InitializeAsync(vivoxInitializationOptions);
VivoxService.Instance.SetTokenProvider(PresenceVivoxServiceComponents.VivoxTokenProvider);
await VivoxService.Instance.InitializeAsync();
}
- Shut down the services in the
Shutdown
method.
public static void Shutdown()
{
// ...
s_VivoxService.Dispose();
s_VivoxService = null;
// ...
}
Join and leave voice channels
To join or leave a voice channel, see the following steps:
- In your scene, create Join Voice and Leave Voice buttons.
- Go to GameObject > Create Empty and name the new game object VoiceManager.
- In your
Assets/Scripts
directory, create a new script and name itVoiceManager
. - Attach the
VoiceManager
script to your VoiceManager game object. - In your
PresentationManager
script file, use thePresentationManager
class to do the following:- Reference an
IVoiceService
and anISessionProvider
- Reference the join and leave buttons
- Store the current session
- Describe whether the participant has joined the voice channel
- Reference an
public class VoiceManager : MonoBehaviour
{
[SerializeField]
Button m_JoinButton;
[SerializeField]
Button m_LeaveButton;
ISessionProvider m_SessionProvider;
IVoiceService m_VoiceService;
ISession m_CurrentSession;
bool m_HasJoined;
}
- Use the
Awake
method to retrieve services from PlatformServices and to subscribe to theSessionChanged
event and the button clicks. Use theOnDestroy
method to unsubscribe from the events. Requesting the appropriate microphone permissions for the given platform should also be performed onAwake
.
void Awake()
{
m_SessionProvider = PlatformServices.SessionProvider;
m_VoiceService = PlatformServices.VoiceService;
m_SessionProvider.SessionChanged += OnSessionChanged;
m_JoinButton.onClick.AddListener(new UnityEngine.Events.UnityAction(OnJoinClicked));
m_LeaveButton.onClick.AddListener(new UnityEngine.Events.UnityAction(OnLeaveClicked));
StartCoroutine(VerifyMicrophoneAuthorization());
}
void OnDestroy()
{
m_SessionProvider.SessionChanged -= OnSessionChanged;
m_JoinButton.onClick.RemoveAllListeners();
m_LeaveButton.onClick.RemoveAllListeners();
}
static IEnumerator VerifyMicrophoneAuthorization()
{
if (!Application.HasUserAuthorization(UserAuthorization.Microphone))
{
yield return Application.RequestUserAuthorization(UserAuthorization.Microphone);
if (!Application.HasUserAuthorization(UserAuthorization.Microphone))
Debug.LogError("Microphone access denied. Vivox voice chat will not work.");
}
}
- Use the
OnSessionChanged
method to clean up any previous sessions and to make sure the buttons are displayed correctly.
async void OnSessionChanged(ISession session)
{
m_JoinButton.interactable = false;
m_LeaveButton.interactable = false;
// Clean up any previous session
if (m_CurrentSession != null && m_HasJoined)
{
await m_VoiceService.LeaveAsync();
}
m_CurrentSession = session;
if (session != null)
{
m_JoinButton.interactable = true;
}
}
- Use the
OnJoinClicked
method to implement callbacks for the button clicks.
async void OnJoinClicked()
{
m_JoinButton.interactable = false;
await m_VoiceService.JoinAsync();
m_HasJoined = true;
m_LeaveButton.interactable = true;
}
async void OnLeaveClicked()
{
m_LeaveButton.interactable = false;
await m_VoiceService.LeaveAsync();
m_HasJoined = false;
m_JoinButton.interactable = true;
}
(Optional)Display information about a voice channel
To display information about a voice channel, see the following steps:
- In your scene, create a text field to display information about the voice channel.
- In your
Assets/Scripts
directory, create a new script and name itVoiceTextUpdater
. - Attach the
VoiceTextUpdater
script to your VoiceManager game object. - In your
VoiceTextUpdater
script file, use theVoiceTextUpdater
class to reference anIVoiceService
and your text field.
public class VoiceTextUpdater : MonoBehaviour
{
[SerializeField]
Text m_TextField;
IVoiceService m_VoiceService;
}
- Use the
Awake
method to retrieve services from PlatformServices and to subscribe to theVoiceParticipantUpdated
event. Use theOnDestroy
method to unsubscribe from the event.
void Awake()
{
m_VoiceService = PlatformServices.VoiceService;
m_VoiceService.VoiceParticipantUpdated += ApplyVoiceUpdate;
}
void OnDestroy()
{
m_VoiceService.VoiceParticipantUpdated -= ApplyVoiceUpdate;
}
- Use the
ApplyVoiceUpdate
method to update the text with information about the voice chat.
void ApplyVoiceUpdate(IEnumerable<IVoiceParticipant> voiceParticipants)
{
if (voiceParticipants != null && voiceParticipants.Any())
{
var sb = new StringBuilder();
foreach (var voiceParticipant in voiceParticipants)
{
sb.AppendLine($"{voiceParticipant.DisplayName} : {voiceParticipant.AudioIntensity}");
}
m_TextField.text = sb.ToString();
}
else
{
m_TextField.text = "No voice participant in the room.";
}
}