Important: This is documentation for the legacy version of the Vivox Unity SDK. This documentation will be removed after July 2025. Refer to the v16 documentation for the new version of the SDK.
Participant events
The Vivox SDK posts information about individual participants in a channel that is visible to all other participants. This includes the following information:
- When a user joins a channel
- When a user leaves a channel
- When there is an important change in user state, such as whether the user is speaking or typing
Handling participant events is optional. If there is no visualization of user state (for example, displaying who has voice enabled), then the game can ignore these events.
To provide a visualization of user state information, a game must handle the following messages:
IChannelSession.Participants.AfterKeyAdded
IChannelSession.Participants.BeforeKeyRemoved
IChannelSession.Participants.AfterValueUpdated
The following code is an example of how to subscribe to these messages:
private void BindChannelSessionHandlers(bool doBind, IChannelSession channelSession)
{
//Subscribing to the events
if (doBind)
{
// Participants
channelSession.Participants.AfterKeyAdded += OnParticipantAdded;
channelSession.Participants.BeforeKeyRemoved += OnParticipantRemoved;
channelSession.Participants.AfterValueUpdated += OnParticipantValueUpdated;
//Messaging
channelSession.MessageLog.AfterItemAdded += OnChannelMessageReceived;
}
//Unsubscribing to the events
else
{
// Participants
channelSession.Participants.AfterKeyAdded -= OnParticipantAdded;
channelSession.Participants.BeforeKeyRemoved -= OnParticipantRemoved;
channelSession.Participants.AfterValueUpdated -= OnParticipantValueUpdated;
//Messaging
channelSession.MessageLog.AfterItemAdded -= OnChannelMessageReceived;
}
}
Monitoring subscribed events
The following sections provide information about monitoring specific events that you are subscribed to.
Note: To distinguish between events that pertain to you from events that pertain to other users, use the Participant.IsSelf
query.
IChannelSession.Participants.AfterKeyAdded
private void OnParticipantAdded(object sender, KeyEventArg<string> keyEventArg)
{
ValidateArgs(new object[] { sender, keyEventArg });
var source = (VivoxUnity.IReadOnlyDictionary<string, IParticipant>)sender;
var participant = source[keyEventArg.Key];
var username = participant.Account.Name;
var channel = participant.ParentChannelSession.Key;
var channelSession = participant.ParentChannelSession;
//Do what you want with the information
}
private static void ValidateArgs(object[] objs)
{
foreach (var obj in objs)
{
if (obj == null)
throw new ArgumentNullException(obj.GetType().ToString(), "Specify a non-null/non-empty argument.");
}
}
IChannelSession.Participants.BeforeKeyRemoved
private void OnParticipantRemoved(object sender, KeyEventArg<string> keyEventArg)
{
ValidateArgs(new object[] { sender, keyEventArg });
var source = (VivoxUnity.IReadOnlyDictionary<string, IParticipant>)sender;
var participant = source[keyEventArg.Key];
var username = participant.Account.Name;
var channel = participant.ParentChannelSession.Key;
var channelSession = participant.ParentChannelSession;
uIManager.DeleteUserMuteObjectUI(username);
if (participant.IsSelf)
{
BindChannelSessionHandlers(false, channelSession); //Unsubscribe from events here
currentChannelID = null;
var user = client.GetLoginSession(accountId);
user.DeleteChannelSession(channelSession.Channel);
}
}
IChannelSession.Participants.AfterValueUpdated
private void OnParticipantValueUpdated(object sender, ValueEventArg<string, IParticipant> valueEventArg)
{
ValidateArgs(new object[] { sender, valueEventArg }); //see code from earlier in post
var source = (VivoxUnity.IReadOnlyDictionary<string, IParticipant>)sender;
var participant = source[valueEventArg.Key];
string username = valueEventArg.Value.Account.Name;
ChannelId channel = valueEventArg.Value.ParentChannelSession.Key;
string property = valueEventArg.PropertyName;
switch (property)
{
case "LocalMute":
{
if (username != accountId.Name) //can't local mute yourself, so don't check for it
{
//update their muted image
}
break;
}
case "SpeechDetected":
{
//update speaking indicator image
break;
}
default:
break;
}
}