Voice

// Config: Engine - [], Toolkit - [v1.0.0]

Discord Social gives a lobby a voice call. The Toolkit can play the other people either straight through the system’s output device, or through Unity AudioSources so a voice can come from a position in the world.

Two ways to hear people #

Device (default)UnityAudio
What happensDiscord plays everyone through the output device, like a normal callEach person plays through an AudioSource you choose
Positional soundNoYes, with the AudioSource’s own 3D settings
Unity AudioMixer, filters, reverb zonesNoYes
SetupNoneA DiscordVoiceSource on each person’s GameObject, bound to that person
ChosenDiscordLobbySession.VoiceOutput, before Join voicethe same

The choice applies to the next call. Change it before joining, not during a call. DiscordVoiceOutputToggle is a ready-made switch, and it is disabled while you are in voice.

Joining and leaving #

DiscordLobbySession.JoinVoice() joins the current lobby’s call, and LeaveVoice() leaves it. InVoice and OnVoiceChanged report the state. Leaving the lobby also ends the call. DiscordVoiceBar puts join or leave, mute and deafen on three buttons.

Voice from a character (3D voice) #

  1. Set the lobby session’s voice output to Unity Audio (the Inspector field, the toggle, or session.VoiceOutput = DiscordVoiceOutput.UnityAudio).
  2. On each player’s pawn or avatar prefab add an AudioSource and a DiscordVoiceSource. On the AudioSource set Spatial Blend to 1 and choose the rolloff, minimum distance and maximum distance as for any other sound.
  3. When you spawn a pawn for a player, call voiceSource.Bind(userData) with that player’s Discord user. In the Demo Game, DemoSessionStage does this for every lobby member.
  4. Skip the local player. You do not receive your own voice, so your own pawn needs no source.

Then press Join voice. Each remote player’s voice plays from their pawn, and gets quieter and pans as they move.

What you hear if you skip a step #

  • A person with no bound DiscordVoiceSource is still heard through the output device. Set DiscordVoiceRouter.MuteUnrouted = true to silence them instead.
  • A person bound to a source is muted on the device, so nobody is heard twice.
  • If the lobby session is on Device, sources stay silent and everyone plays through the device.

How it works #

DiscordLobbySession starts the call with DiscordSocialApp.StartCallWithAudio, which hands the game each participant’s audio as 16 bit samples on the SDK’s audio thread. DiscordVoiceRouter.OnAudioReceived mixes the audio down to mono, queues it in a small buffer per person, and sets the callback’s mute flag for people it will play. A DiscordVoiceSource creates a streaming AudioClip at the incoming sample rate (Discord uses 48 kHz) and plays it on its AudioSource, reading from that buffer.

The buffer holds about 60 ms before it starts and at most half a second. If the speaker’s audio arrives faster than it plays, the oldest audio is dropped so the voice does not fall behind. If it runs dry, the source plays silence and rebuffers.

Code #

// 3D voice for a spawned pawn
var source = pawn.GetComponentInChildren<DiscordVoiceSource>();
source.Bind(new UserData(discordUserId));   // or source.Bind(userData)

// Choose the output before joining
session.VoiceOutput = DiscordVoiceOutput.UnityAudio;
session.JoinVoice();

DiscordSocialApp.StartCallWithAudio(lobbyId, received, captured) in Foundation for Discord Social is the underlying call if you want the audio for something else. Its handlers run on the audio thread: do not touch Unity objects from them, and copy the samples if you keep them, because the array is reused. captured receives your own microphone audio before it is processed.

The other voice components #

ComponentDoes
DiscordVoiceBarJoin or leave voice, mute and deafen buttons whose labels show the next action
DiscordVoiceParticipantList, DiscordVoiceParticipantRowEveryone in the call: a speaking light, a muted marker, a local mute toggle and a volume slider
DiscordVoiceSettingsPanelMicrophone and speaker pickers, volumes, input mode, noise suppression, echo cancellation, automatic gain and Krisp noise cancellation
DiscordPushToTalkButtonOpens the microphone while held. For a key, call DiscordSocialApp.SetPushToTalkActive from your own input handling

Platform notes #

  • macOS: set the NSMicrophoneUsageDescription key in the app’s Info.plist.
  • iOS: enable the background audio mode in the Info.plist. Discord’s own Unity sample has a post-build processor that does this.
  • Android: the app needs the RECORD_AUDIO permission.
  • Flatpak Discord on Linux: the SDK does not find the desktop client’s IPC socket there. Sign in, calls and voice still work, but the noise, echo and gain switches cannot show their current state.

Verified and not verified #

Run against live Discord on one account: joining and leaving a lobby call, the participant list, mute, deafen, volumes, input mode, push to talk state, the device lists, and the microphone audio callback delivering 48 kHz mono audio. The buffer and router logic has unit tests. Not yet run: playing another person’s voice through an AudioSource (positional playback), the speaking light, and device switching during a call. Those need a second account.

Rate This Article!