Skip to main content

Unity Room Operations

Build a Unity room scene with com.mediasfu.unity 0.1.0-preview.2. The MediaSfuClient gives your scene room state, participant events, media connection, local and remote track operations, screen sharing, participant leave, and a host end-room request.

Before you start

  • Use Unity 2022.3 and install both com.mediasfu.unity and its required com.mediasfu.mediasoup-client-unity package.
  • Attach the native WebRTC device and your scene's local/remote media bridges before you try to capture or render media.
  • Configure microphone, camera, screen-capture, and platform privacy settings for every desktop, mobile, or console target you ship.
  • Decide who can create a room, join, produce media, and end the session in your authenticated application backend.

Keep room authority off the game client

Your distributed Unity player is not a safe place for a reusable MediaSFU API credential. Send the player's room intent to your authenticated application backend instead:

public interface IAuthorizedRoomGateway
{
Task<AuthorizedRoomHandoff> CreateAsync(RoomIntent intent, CancellationToken cancellationToken);
Task<AuthorizedRoomHandoff> JoinAsync(RoomIntent intent, CancellationToken cancellationToken);
}

The current preview package's direct MediaSfuClient startup contract uses MediaSfuClientOptions.Credentials. It does not publish a backend-authorized handoff or adapter constructor. Therefore this guide does not give a direct client create/join setup snippet, and you must not place credentials in a scene, prefab, ScriptableObject, player preference, build setting, or source file. A secure distributed-game create/join integration needs a package-level backend-authorized handoff contract before it can be documented here.

Your backend remains responsible for player authentication, role policy, capacity, rate limits, room creation, and revoking any unused authority.

Work with the active room

After your approved room startup establishes an active MediaSfuClient, attach room-state events once and remove them when the scene closes.

client.ParticipantJoined += OnParticipantJoined;
client.ParticipantLeft += OnParticipantLeft;

var participants = client.CurrentRoom?.Participants;

void OnParticipantJoined(MediaSfuParticipantEvent change)
{
RefreshParticipantList();
}

void OnParticipantLeft(MediaSfuParticipantEvent change)
{
RefreshParticipantList();
}

CurrentRoom.Participants is the current membership snapshot. It confirms who is in the room, not that a remote video texture or audio output is working.

Connect media in a deliberate order

Use the following operations after a room exists:

var connected = await client.ConnectMediaAsync();
if (!connected.Success)
{
ShowRoomError(connected.Error);
return;
}

var permission = await client.RequestMediaPermissionAsync(MediaSfuTrackKind.Video);
if (!permission.Success)
{
ShowPermissionState(permission.Error);
return;
}

ConnectMediaAsync establishes the signaling and room validation path. RequestMediaPermissionAsync requests host approval when the room policy requires it. Neither result proves that a camera has started; check the local media backend and confirm playback in another Unity player.

For a custom WebRTC workflow, the exact track operations are:

MediaSfuOperationResult<MediaSfuProduceResponse> produced =
await client.ProduceMediaTrackAsync(produceRequest);

MediaSfuOperationResult<MediaSfuConsumeResponse> consumed =
await client.ConsumeMediaTrackAsync(consumeRequest);

Build produceRequest and consumeRequest from the active transport and attached WebRTC device. Do not invent IDs or reuse a request from an earlier room. A successful producer result means the client accepted that operation; verify the actual remote track in a second player.

Screen share, leave, and host end

var share = await client.SetScreenShareEnabledAsync(true);
if (!share.Success)
ShowRoomError(share.Error);

var leaveAndKeepOpen = await client.LeaveRoomAsync(endRoomOnHostExit: false);
if (!leaveAndKeepOpen.Success)
ShowRoomError(leaveAndKeepOpen.Error);

var ended = await client.EndMeetingAsync();
if (!ended.Success)
ShowRoomError(ended.Error);

SetScreenShareEnabledAsync(true) requires a supported local capture backend, the required platform permission, and any room approval. Call it with false when sharing ends.

LeaveRoomAsync() retains its historical endRoomOnHostExit: true default. Passing false lets a host leave while the room and remaining participants continue. EndMeetingAsync is the explicit host-only end-room request; it requires an active socket and a local host role. After any exit call, stop app-owned local tracks, remove event subscriptions, clear scene state, and only then navigate away from the room scene.

Handle failures without guessing

ResultWhat to do
Room request is deniedExplain that the player is not allowed to enter or create this room; do not retry with a client secret.
ConnectMediaAsync failsKeep the player on a recoverable connection screen and offer a bounded retry after checking network access.
Permission request is deniedExplain which capability is unavailable and keep the player in control of device settings.
Produce, consume, or screen share failsPreserve the room UI, stop any partial app-owned capture, and show the operation result message.
Host end is deniedKeep the room running and show that only the current host with an active connection can end it.

Release checklist

  1. Test authenticated create and join policy through your application backend.
  2. Test participant joins and leaves with two Unity players.
  3. Test microphone, camera, remote audio/video, and permission denial on each supported platform.
  4. Test screen-share start, stop, denial, and cleanup where the platform supports capture.
  5. Test participant leave and host end separately, including stale event subscription and local-track cleanup.
  6. Do not log room authority, player identity tokens, or media metadata.

Compile and test the application for every target player. Then repeat the release checklist in the Unity Editor and on real target hardware; an Editor or managed-code test cannot prove native capture, rendering, audio routing, or screen sharing.