Photon Fusion Shared Mode: In-Room Lobby System
This page accompanies the Photon Fusion Shared Mode: In-Room Lobby System with Networked Ready Sync video and explains how to build a room-based lobby where connected players can see each other, synchronize their ready status, and wait for the Master Client to start the match.
Use this page when players should connect to a Fusion room before entering gameplay and need a synchronized staging area for ready checks, player customization, team selection, or match configuration.
If you would like to learn more about the INetworkStruct, please take a look here.
Overview
An in-room lobby exists after players have already connected to the same Fusion session.
It is different from a matchmaking lobby or room browser. Photon matchmaking is responsible for finding or creating the room. The in-room lobby manages the players who are already connected to that room.
The system built in this tutorial includes:
- a shared lobby scene;
- a synchronized list of connected players;
- Networked ready-state data;
- dynamically created player UI entries;
- a local ready toggle;
- a Start Game button visible only to the Master Client;
- validation that all players are ready;
- synchronized scene loading;
- player join and leave handling.
The UI itself is local Unity presentation. Only the lobby data and match-start decision need to be synchronized through Fusion.
Video Timeline
| Time | Section |
|---|---|
| 00:00 | Introduction |
| 00:31 | Importing the template |
| 01:07 | Verifying the template |
| 01:33 | Adjusting the StartMenu script |
| 02:37 | Creating and configuring the lobby scene |
| 06:57 | Creating the UILobbyPlayer component |
| 08:59 | Creating LobbySessionController and LobbyPlayerData |
| 09:20 | Implementing the LobbyPlayerData struct |
| 10:12 | Implementing LobbySessionController |
| 26:06 | Connecting Unity references |
| 26:46 | Adding the lobby scene to Build Settings |
| 26:59 | Testing the final result |
In-Room Lobby Architecture
The lobby can be divided into three layers.
| Layer | Responsibility |
|---|---|
| Fusion session | Maintains the room connection and connected PlayerRef values. |
| Networked lobby state | Stores each player’s name, ready status, and optional selections. |
| Unity UI | Displays the synchronized state and sends local player actions. |
A practical script structure includes:
| Script or Type | Responsibility |
|---|---|
StartMenu |
Connects to the Fusion room and opens the lobby instead of immediately entering gameplay. |
LobbyPlayerData |
Network-compatible struct containing one player’s lobby state. |
LobbySessionController |
Owns synchronized lobby data and controls match start. |
UILobbyPlayer |
Displays one player’s name and ready state. |
| Lobby panel controller | Creates, updates, and removes player UI entries. |
The exact script names can vary, but the separation between Networked state and local UI should remain.
Starting from Fusion Asteroids
The tutorial uses the Fusion Asteroids sample as its base project.
Before creating the lobby:
- Import or open the sample.
- Add the project’s App ID from the Photon Dashboard.
- Verify that Fusion connects successfully.
- Run a development build or second instance.
- Confirm that players can join the same room.
- Confirm that the existing gameplay scene loads correctly.
Testing the original template first makes it easier to identify whether later problems come from the lobby implementation or the initial Fusion setup.
Importing UI Assets
The UI can use any Unity-compatible asset package.
The tutorial uses a Kenney space-themed UI pack, but the networking logic does not depend on those assets.
The lobby interface needs:
- a main lobby panel;
- a player-list container;
- a player-row prefab;
- player-name text;
- ready-status text;
- a Toggle Ready button;
- a Start Game button;
- a Leave Room button.
Keep the UI hierarchy independent from the networked controller wherever possible.
Modifying the Connection Flow
The original sample connects to a room and immediately loads gameplay.
For an in-room lobby, the sequence becomes:
- Connect to the Fusion room.
- Load or enable the lobby scene.
- Register connected players.
- Wait for ready-state changes.
- Let the Master Client start the match.
- Load the gameplay scene for all players.
Update StartMenu so that a successful connection no longer bypasses the lobby.
Lobby Scene as the Initial Network Scene
The lobby can be loaded as the initial Fusion scene when the session starts.
Conceptually, the connection arguments reference the lobby scene rather than the gameplay scene:
C#
var startGameArgs = new StartGameArgs
{
GameMode = GameMode.Shared,
SessionName = roomName,
Scene = lobbySceneReference,
SceneManager = networkSceneManager
};
The exact scene-loading API depends on the project’s Fusion setup.
The important point is that all players enter the same synchronized lobby scene before gameplay begins.
Lobby Scene UI Hierarchy
A possible hierarchy is:
LobbyCanvas
└── LobbyPanel
├── Title
├── PlayerList
│ └── PlayerItemContainer
├── ToggleReadyButton
├── StartGameButton
└── LeaveRoomButton
The player-item container receives one instantiated UI row for every connected player.
UILobbyPlayer
UILobbyPlayer represents one player in the visible lobby list.
It is a local UI component, not a NetworkBehaviour.
Its responsibilities are:
- display the player name;
- display whether the player is ready;
- optionally identify the local player;
- optionally display host or Master Client status;
- update colors, labels, or icons.
Example:
C#
using TMPro;
using UnityEngine;
public class UILobbyPlayer : MonoBehaviour
{
[SerializeField]
private TMP_Text _playerNameText;
[SerializeField]
private TMP_Text _readyStatusText;
public void SetPlayerName(string playerName)
{
_playerNameText.text = playerName;
}
public void SetReadyState(bool isReady)
{
_readyStatusText.text =
isReady ? "Ready" : "Not Ready";
}
}
The synchronized lobby controller supplies the values.
Ready-State Presentation
The tutorial visually distinguishes the two ready states.
For example:
| State | Display |
|---|---|
| Ready | White text or a positive icon |
| Not Ready | Red text or a warning icon |
Color is presentation only. The authoritative value remains the Networked ready property.
Creating the Player-Row Prefab
To create the prefab:
- Create a UI GameObject.
- Add text for the player name.
- Add text or an icon for ready status.
- Attach
UILobbyPlayer. - Assign its references.
- Save it as a prefab.
- Remove the temporary scene instance if it is no longer needed.
The lobby panel instantiates this prefab dynamically for each connected player.
LobbyPlayerData
LobbyPlayerData stores the synchronized information for one player.
Because it is stored in Fusion Networked state, it must use Fusion-compatible fields and implement:
C#
INetworkStruct
A possible definition is:
C#
using Fusion;
public struct LobbyPlayerData : INetworkStruct
{
public NetworkString<_32> PlayerName;
public NetworkBool IsReady;
}
Do not use a managed C# string directly inside Networked state.
Use NetworkString<TSize> with a capacity appropriate for the project.
Why Use INetworkStruct?
INetworkStruct allows several related values to be stored as one Fusion-compatible value.
It is useful for player lobby data because one entry can contain:
- display name;
- ready state;
- selected skin;
- team;
- character selection;
- rank or level;
- other compact lobby settings.
The struct must contain only Fusion-supported network types.
Extending LobbyPlayerData
The structure can later be expanded:
C#
public struct LobbyPlayerData : INetworkStruct
{
public NetworkString<_32> PlayerName;
public NetworkBool IsReady;
public byte SelectedSkinIndex;
public byte TeamIndex;
}
Compact integral values are useful for selections that map to project assets or configuration tables.
Avoid synchronizing full Unity asset references or UI objects through the struct.
LobbySessionController
LobbySessionController is the central Networked controller for the room lobby.
It is responsible for:
- registering players;
- removing disconnected players;
- storing lobby data;
- receiving ready-state requests;
- checking whether all players are ready;
- identifying the Master Client;
- starting the gameplay scene;
- notifying local UI when lobby data changes.
It should be attached to a NetworkObject in the lobby scene.
Storing Player Data
One approach is to store the lobby entries in a Networked dictionary:
C#
[Networked, Capacity(16)]
public NetworkDictionary<PlayerRef, LobbyPlayerData>
Players => default;
The key is the Fusion PlayerRef.
The value is the player’s LobbyPlayerData.
The capacity should match the maximum supported room size.
Why Key by PlayerRef?
PlayerRef is Fusion’s network identity for a connected player.
Using it as the key makes it possible to:
- associate data with the correct connection;
- remove data when the player leaves;
- identify the local player;
- determine which UI row to update;
- validate RPC senders;
- map a player to their gameplay object later.
Do not use a player’s display name as the unique network identifier because names may not be unique.
Registering Players
When a player joins, the State Authority of the lobby controller adds a new entry.
Conceptually:
C#
private void RegisterPlayer(PlayerRef player)
{
if (!Object.HasStateAuthority)
{
return;
}
if (Players.ContainsKey(player))
{
return;
}
Players.Add(
player,
new LobbyPlayerData
{
PlayerName = $"Player {player.PlayerId}",
IsReady = false
}
);
}
The actual player name can come from:
- room connection data;
- authentication data;
- a pre-game menu;
- a separate RPC;
- persistent profile data.
Player Join Detection
The project can detect joins through Fusion callbacks or the existing sample’s connection architecture.
The lobby controller should respond when a new PlayerRef appears.
Typical responsibilities include:
- Confirm that the player is not already registered.
- Create default lobby data.
- Set
IsReadyto false. - Add the player to the Networked collection.
- Let every client create the corresponding UI row.
Only the appropriate State Authority should mutate the Networked collection.
Player Leave Detection
When a player disconnects:
- Remove the player from the Networked collection.
- Remove the player’s local UI row.
- Recalculate whether all remaining players are ready.
- Update Master Client controls if authority changed.
Conceptually:
C#
private void UnregisterPlayer(PlayerRef player)
{
if (!Object.HasStateAuthority)
{
return;
}
Players.Remove(player);
}
Always handle disconnection. Do not assume players leave only through the lobby’s Leave Room button.
Local UI Dictionary
The lobby UI controller can maintain a standard local C# dictionary:
C#
private readonly Dictionary<PlayerRef, UILobbyPlayer>
_playerItems = new();
This dictionary is not Networked.
It maps synchronized player identities to local UI instances.
When lobby state changes:
- create missing UI rows;
- update existing rows;
- destroy rows for players who left.
Building the Player List
A refresh method can iterate through the synchronized player collection:
C#
private void RefreshPlayerList()
{
foreach (var pair in LobbyController.Players)
{
PlayerRef player = pair.Key;
LobbyPlayerData data = pair.Value;
if (!_playerItems.TryGetValue(
player,
out UILobbyPlayer item))
{
item = Instantiate(
_playerItemPrefab,
_playerListContainer
);
_playerItems.Add(player, item);
}
item.SetPlayerName(data.PlayerName.ToString());
item.SetReadyState(data.IsReady);
}
}
After updating the current entries, remove UI rows whose players are no longer present.
Detecting Lobby Data Changes
The UI should update when Networked lobby data changes.
Possible approaches include:
- a Fusion Change Detector;
Render()comparisons;OnChangedRenderfor individual properties;- events raised by a network-state wrapper;
- refreshing when player join, leave, or ready actions occur.
For collection-based state, a Change Detector or local snapshot comparison is often useful.
The important rule is that the UI reads synchronized data rather than assuming that a local button press succeeded.
Event-Driven UI Updates
A local event can decouple the networking controller from individual UI rows.
For example:
C#
public event Action<PlayerRef, LobbyPlayerData>
PlayerDataChanged;
When the synchronized value changes, the controller invokes the event.
The UI listens and refreshes the corresponding row.
The C# event itself is local. The data that causes it is Networked.
Toggling the Local Ready State
The local player presses the Toggle Ready button.
That button should request a change through the Fusion network flow.
The UI must not directly edit a Networked collection unless the local peer has the required State Authority.
A common pattern is to send an RPC to the lobby controller’s State Authority.
Ready-State RPC
Conceptually:
C#
[Rpc(RpcSources.All, RpcTargets.StateAuthority)]
private void RPC_SetReady(
NetworkBool isReady,
RpcInfo info = default)
{
PlayerRef player = info.Source;
if (!Players.TryGet(
player,
out LobbyPlayerData data))
{
return;
}
data.IsReady = isReady;
Players.Set(player, data);
}
Using RpcInfo.Source prevents a caller from freely choosing another player’s PlayerRef.
The receiving authority associates the request with the actual sender.
Requesting a Toggle
The local UI reads the current synchronized state and sends the opposite value:
C#
public void ToggleLocalReady()
{
PlayerRef localPlayer = Runner.LocalPlayer;
if (!Players.TryGet(
localPlayer,
out LobbyPlayerData data))
{
return;
}
RPC_SetReady(!data.IsReady);
}
The UI should wait for the Networked value to update before changing its final displayed state.
This avoids showing a state that the authority rejected.
Per-Player NetworkBehaviour Alternative
Another valid architecture is to spawn one lobby-data NetworkObject for every player.
That object can contain:
C#
[Networked]
public NetworkBool IsReady { get; set; }
The local player owns their corresponding object and changes its state.
The central-collection approach is often simpler for:
- a compact lobby;
- centralized validation;
- Master Client-controlled start logic;
- storing all player data in one place.
The per-player-object approach may fit projects that already spawn a persistent network player object before gameplay.
Use one architecture consistently rather than duplicating the same state in both places.
Master Client Start Control
Only the Master Client should be able to start the match.
In Shared Mode, the Master Client normally has State Authority over scene-owned network objects such as the lobby controller.
The UI can therefore use the lobby controller’s authority state to determine whether the Start Game button should be visible.
Conceptually:
C#
_startGameButton.gameObject.SetActive(
LobbyController.Object.HasStateAuthority
);
Do not rely only on button visibility for security. The network-side start method must also verify authority.
Checking Whether Everyone Is Ready
The lobby controller iterates over all registered players:
C#
private bool AreAllPlayersReady()
{
if (Players.Count == 0)
{
return false;
}
foreach (var pair in Players)
{
if (!pair.Value.IsReady)
{
return false;
}
}
return true;
}
The Start Game button becomes interactable only when:
- the local peer controls the lobby controller;
- the lobby contains the required number of players;
- every registered player is ready.
Minimum Player Count
A production lobby may require more than one player.
For example:
C#
private const int MinimumPlayers = 2;
Then:
C#
if (Players.Count < MinimumPlayers)
{
return false;
}
This prevents an empty or incomplete room from satisfying the ready check.
Updating the Start Game Button
The local UI can update the button state from the current Networked collection:
C#
_startGameButton.interactable =
LobbyController.Object.HasStateAuthority &&
LobbyController.AreAllPlayersReady();
Recalculate this when:
- a player joins;
- a player leaves;
- a ready state changes;
- State Authority changes;
- Master Client migration occurs.
Starting the Match
When the Master Client clicks Start Game:
- Verify State Authority.
- Recheck that all players are ready.
- Prevent duplicate start requests.
- Load the gameplay scene through the Fusion runner.
- Let Fusion synchronize the scene transition.
Conceptually:
C#
public void StartMatch()
{
if (!Object.HasStateAuthority)
{
return;
}
if (!AreAllPlayersReady())
{
return;
}
Runner.LoadScene(
gameplaySceneReference
);
}
The exact scene API depends on the project’s network scene manager.
Validate Again on the Network Side
Do not assume the button’s disabled state is sufficient.
A modified client or stale UI could still attempt to invoke the start action.
The authoritative method must verify:
- caller authority;
- player count;
- ready status;
- current lobby state;
- whether the match has already started.
Preventing Duplicate Starts
Store a Networked or authority-owned flag:
C#
[Networked]
private NetworkBool MatchStarting { get; set; }
Before loading:
C#
if (MatchStarting)
{
return;
}
MatchStarting = true;
This prevents repeated clicks from initiating multiple scene-load calls.
Synchronized Scene Loading
Use the active Fusion runner and network scene manager to load the gameplay scene.
Do not use a local-only call such as:
C#
SceneManager.LoadScene(...)
for the authoritative multiplayer transition unless the project’s Fusion architecture explicitly coordinates it.
A local Unity scene load can move only one client and break the shared session flow.
Leaving the Room
The Leave Room button should shut down the local Fusion runner and return the player to the connection menu.
Conceptually:
C#
public async void LeaveRoom()
{
await Runner.Shutdown();
// Re-enable or load the main menu.
}
After leaving:
- remove local lobby UI;
- restore menu controls;
- clear cached room data;
- release runner references where required.
Other clients detect the disconnection and remove the player from the Networked lobby collection.
Setting Up LobbySessionController in Unity
Create a lobby controller GameObject:
LobbySessionController
Add:
NetworkObject;LobbySessionController;- any required Fusion callback component;
- references to the gameplay scene if configured through the Inspector.
Because it is a scene NetworkObject, verify that the object is baked or registered according to the project’s Fusion scene workflow.
Setting Up the Lobby Panel
Create:
InRoomLobbyPanel
Attach the local lobby UI controller.
Assign:
- player-row prefab;
- player-list parent;
- Toggle Ready button;
- Start Game button;
- Leave Room button;
- lobby content root;
LobbySessionControllerreference.
The main UI content can begin inactive and become visible after the room connection succeeds.
Button Bindings
Bind the buttons to local UI or controller methods:
| Button | Method |
|---|---|
| Toggle Ready | ToggleLocalReady() |
| Start Game | StartMatch() |
| Leave Room | LeaveRoom() |
The Start Game button should call an authority-validated network method.
Build Settings
Add both scenes to Unity Build Settings:
- lobby scene;
- gameplay scene.
Ensure that:
- scene references use the correct build indexes or
SceneRefvalues; - every client has the same scene list;
- the network scene manager can resolve both scenes;
- the connection flow starts in the lobby scene.
A scene missing from Build Settings may work in the Editor but fail in a standalone build.
Testing with Multiple Instances
Test with at least two clients.
Suggested workflow:
- Start the first client.
- Create or join the room.
- Confirm that the lobby scene appears.
- Start a second client.
- Join the same room.
- Confirm that both player names appear.
- Toggle ready on Player 1.
- Verify that both clients display the change.
- Toggle ready on Player 2.
- Confirm that the Master Client’s Start Game button becomes active.
- Verify that non-Master clients cannot start.
- Click Start Game.
- Confirm that all clients enter gameplay together.
Testing Player Disconnection
Also test:
- Join with multiple players.
- Set all players to ready.
- Disconnect one player.
- Confirm that their UI entry disappears.
- Confirm that readiness is recalculated.
- Confirm that the remaining Master Client can still control the lobby.
Unexpected disconnections should produce the same cleanup as the Leave Room button.
Testing Master Client Migration
In Shared Mode, the Master Client can leave.
Test this case:
- Start two or more clients.
- Identify the current Master Client.
- Disconnect that client.
- Confirm that Fusion assigns a new Master Client.
- Confirm that the new authority can see and use the Start Game button.
- Confirm that synchronized lobby data remains valid.
Do not cache Master Client status only once when the UI opens.
Late Joiners
Because ready states are stored in Networked data, a player joining later receives the current lobby state.
The late joiner should see:
- all existing players;
- their current names;
- their current ready states;
- current selections;
- whether the match is already starting.
This is one reason Networked properties or collections are preferable to using RPC events alone.
UI Is Not Network State
Do not synchronize instantiated UI objects.
Each client creates its own local UI based on the same Networked lobby data.
Synchronize:
- player identity;
- ready state;
- selections;
- lobby status.
Keep local:
- TextMeshPro references;
- instantiated row GameObjects;
- button states;
- colors;
- animations;
- layout.
Expanding the Lobby
The same data pattern can support additional features.
Skin Selection
Add:
C#
public byte SelectedSkinIndex;
The UI maps the index to a local skin icon or preview.
Team Selection
Add:
C#
public byte TeamIndex;
The authority can validate team size and balancing rules.
Character Selection
Store a compact character identifier:
C#
public byte CharacterIndex;
Use a local configuration table to resolve it to a prefab or visual.
Lobby Chat
Short messages can be sent using RPCs or a bounded Networked history.
Do not continuously append unbounded chat data to Networked state.
Host Settings
The Master Client can configure:
- selected map;
- game mode;
- round duration;
- score limit;
- team rules.
Store persistent match settings in Networked properties so all clients and late joiners receive them.
Player Statistics
Lobby UI can display profile data such as:
- rank;
- level;
- win count;
- account badge.
Persistent account data should usually come from an authentication or backend service rather than being trusted from arbitrary client input.
Networked State and Events
The general pattern is:
- A player performs a local UI action.
- The action is sent to the appropriate authority.
- The authority validates it.
- The authority changes Networked state.
- Fusion replicates the state.
- Each client updates its local UI.
This pattern applies to ready states, teams, skins, maps, and other lobby selections.
Key Concepts
| Concept | Description |
|---|---|
| In-room lobby | Staging interface for players already connected to the same Fusion room. |
PlayerRef |
Fusion identifier for a connected player. |
INetworkStruct |
Interface for structs stored in Fusion Networked state. |
LobbyPlayerData |
Struct containing one player’s synchronized lobby values. |
NetworkDictionary |
Fixed-capacity Networked collection keyed by PlayerRef. |
NetworkBool |
Fusion-compatible synchronized boolean. |
NetworkString |
Fixed-capacity string suitable for Networked state. |
UILobbyPlayer |
Local presentation component for one player row. |
| Master Client | Shared Mode peer responsible for authority over applicable shared objects. |
| State Authority | Peer allowed to write a NetworkObject’s state. |
| Ready validation | Check that every required player is ready before starting. |
| Network scene loading | Fusion-coordinated transition that moves all clients to gameplay. |
| Late joiner | Player joining after the room and lobby state already exist. |
Best Practices
Use this checklist when building an in-room lobby:
- Keep UI objects local.
- Store persistent lobby values in Networked state.
- Key player data by
PlayerRef. - Use
INetworkStructfor compact grouped player data. - Set an explicit collection capacity.
- Use Fusion-compatible types inside Networked structs.
- Let the proper State Authority modify lobby data.
- Use RPC sender information instead of trusting a supplied player ID.
- Validate every ready-state and start-game request.
- Make the Start Game button visible only to the Master Client.
- Also validate Master Client authority in code.
- Require all players to be ready before loading gameplay.
- Add a minimum player count where required.
- Prevent duplicate match-start requests.
- Handle unexpected disconnections.
- Recalculate UI and readiness after every join or leave.
- Test Master Client migration.
- Use Fusion scene loading for synchronized transitions.
- Add every network scene to Build Settings.
- Test with standalone clients, not only the Unity Editor.
Common Pitfalls
| Pitfall | Why It Is a Problem |
|---|---|
| Loading gameplay immediately after connecting | Players never enter the in-room staging flow. |
| Treating the lobby as Photon matchmaking | An in-room lobby manages players who are already connected. |
| Synchronizing UI GameObjects | UI should be reconstructed locally from Networked data. |
| Using managed strings in Networked structs | Networked state requires supported fixed-capacity types. |
| Letting clients edit another player’s ready state | Ready requests must be tied to the actual RPC sender. |
| Showing Start Game only through local UI logic | A modified client could still call the start method. |
| Not revalidating readiness before loading | Lobby state may change after the button becomes enabled. |
Using local SceneManager.LoadScene |
Other Fusion clients may remain in the lobby scene. |
| Forgetting Build Settings | Standalone clients may fail to resolve the lobby or gameplay scene. |
| Not removing disconnected players | Stale entries can prevent the match from starting. |
| Caching Master Client status permanently | Authority can change when the current Master Client leaves. |
| Using RPCs as the only ready-state mechanism | Late joiners would not know the current state. |
| Updating UI immediately before state confirmation | The UI can show a value that the authority rejected. |
| Using an unbounded collection | Fusion Networked collections require a defined capacity. |
| Duplicating lobby state in multiple systems | Conflicting sources of truth can produce inconsistent UI. |
Related Links
- Photon
- Photon Fusion
- Fusion Documentation
- Photon Dashboard
- Photon Samples
- Kenney Space Shooter Extension
- Fusion Asteroids
Summary
An in-room lobby gives players a synchronized staging area after they connect to a Fusion Shared Mode session.
LobbyPlayerData stores compact player information such as display name and ready state. LobbySessionController maintains the Networked player collection, validates ready requests, handles joins and leaves, and lets the Master Client start the match only when the lobby requirements are satisfied.
Each client constructs its own local player-list UI from the synchronized data. The UI sends player intentions, but the authoritative Networked controller decides whether those changes are accepted.
Once all required players are ready, the Master Client uses Fusion’s network scene-loading flow to move the entire room into gameplay together.
Last updated on
Back to top- Overview
- Video Timeline
- In-Room Lobby Architecture
- Starting from Fusion Asteroids
- Importing UI Assets
- Modifying the Connection Flow
- Lobby Scene as the Initial Network Scene
- Lobby Scene UI Hierarchy
- UILobbyPlayer
- Ready-State Presentation
- Creating the Player-Row Prefab
- LobbyPlayerData
- Why Use INetworkStruct?
- Extending LobbyPlayerData
- LobbySessionController
- Storing Player Data
- Why Key by PlayerRef?
- Registering Players
- Player Join Detection
- Player Leave Detection
- Local UI Dictionary
- Building the Player List
- Detecting Lobby Data Changes
- Event-Driven UI Updates
- Toggling the Local Ready State
- Ready-State RPC
- Requesting a Toggle
- Per-Player NetworkBehaviour Alternative
- Master Client Start Control
- Checking Whether Everyone Is Ready
- Minimum Player Count
- Updating the Start Game Button
- Starting the Match
- Validate Again on the Network Side
- Preventing Duplicate Starts
- Synchronized Scene Loading
- Leaving the Room
- Setting Up LobbySessionController in Unity
- Setting Up the Lobby Panel
- Button Bindings
- Build Settings
- Testing with Multiple Instances
- Testing Player Disconnection
- Testing Master Client Migration
- Late Joiners
- UI Is Not Network State
- Expanding the Lobby
- Networked State and Events
- Key Concepts
- Best Practices
- Common Pitfalls
- Related Links
- Summary