Background: how it works

The goal here is to:

record audio from a player’s microphone

synchronise the audio with SpatialOS, so other clients can get it

receive the audio on other clients, and play it

Audio sound is a stream of samples (usually represented as an array of floats). Compressed audio formats (such as MP3)
are more involved, but uncompressed audio can be written as an array of samples. Audio clips also have a frequency parameter,
which controls how many samples should be played within 1 second [Hz]. The audio can be directed to multiple channels (for example,
to achieve stereo sound).

Designing this

It might be intuitive to want to store the audio in a property: but this actually
means synchronising a large amount of data.

A better approach is to send the audio as part of an event. This means that:

the audio data is only sent once

the audio data doesn’t need to be stored

only nearby clients will receive the event

Specifically, only clients that have a player ‘checked out’ will receive the event, which means that players will only
be able to hear other players who are within a certain radius around them.

You also have to pay attention to the location of the scene’s
Audio Listener, which is usually attached to the
Main Camera: it needs to be within the range of the AudioSource to be able to hear it.

In a brand new Starter Project, the Player GameObjects are static at (-9999,-9999,-9999)
(which is the default position for Spatial-instanced GameObjects). This happens because they don’t have a
script that syncs the GameObjects’ position with their entity’s Position component. The location of the
MainCamera is (0,0,0), so you won’t hear the AudioSources unless you move the camera closer to the Player
GameObjects.

What we’ll do

In this tutorial, sending audio is explicitly turned on by the player, rather than sending it all the time. You could use any trigger
you like; in this example, it’s the space bar. Pressing the space bar will trigger a SendAudio event, and releasing it will
trigger a StopSendingAudio event.

void UpdateSoundSamples(SendAudio sound)
{
// Don't do anything if this is on the current player (which we have write access to)
if (AudioTransmissionReader.Authority == Authority.Authoritative)
{
return;
}
// ... CODE ... //

This is an easy way to check if the events are coming from your own player, so you don’t play your own player’s
voice back to them.

Build

Now that’s all done, you can test it out locally to see if it’s working.

Build the project.

Given the changes you’ve made, you’ll need to build prefabs and build worker code for local development.