Lobbies and Matchmaking

Lobby Basics

Lobbies are the matchmaking layer of the Photon Cloud. Every visible room is listed in exactly one lobby, and every matchmaking operation, room lists, random joins, filters, runs against the lobby you address. A lobby only organizes rooms; players in a lobby do not see or interact with each other.

The client automatically joins the default lobby when the connection is established, so simple games never need an explicit lobby call. Call SetAutoJoinLobby(false) before connecting to opt out, for example when the game always targets a named lobby anyway.

Lobby Types

LobbyType::Default matches rooms by exact equality on their lobby-visible custom properties. LobbyType::SqlLobby replaces equality matching with query-style filters over indexed properties and has its own page: SQL Lobby Matchmaking.

Joining and Leaving a Lobby

JoinLobby(name, type) enters a lobby and LeaveLobby() exits it; both return Task<Result<void>>. Calling JoinLobby() without arguments targets the default lobby, and IsInLobby() reports the current membership.

Joining a lobby the client is already in fails instead of being a no-op. Because the client auto-joins the default lobby on connect, switching to a named lobby right after connecting means leaving the default lobby first.

Switch from the default lobby to a named one:

C++

Task<Result<void>> EnterRankedLobby(RealtimeClient& client)
{
    Result<void> left = co_await client.LeaveLobby();
    if (left.IsErr())
    {
        co_return left;
    }

    co_return co_await client.JoinLobby(PHOTON_STR("ranked"), LobbyType::Default);
}

Room Lists

While the client is in a lobby the server pushes listing updates through OnRoomListUpdated(const std::vector<RoomListing>&). GetCachedRoomList() returns the most recent list without a round trip, which is usually all a room browser needs between updates.

Field Type Description
Name StringType Unique room name.
PlayerCount int Players in the room.
MaxPlayers uint8_t Player limit, 0 when unlimited.
IsOpen bool Whether the room accepts joins.
DirectMessaging DirectMode The room's direct messaging mode.
CustomProperties RealtimeMap The room's lobby-visible custom properties.

Random Matchmaking

JoinRandomRoom(MatchmakingOptions) asks the server to drop the player into a room matching the given options. When no room matches, the Task resolves to ErrorCode::NoMatchFound instead of waiting for one to appear.

JoinRandomOrCreateRoom(createOptions, matchmakingOptions) closes the classic race between "no match found" and "create a room": when nothing matches, the server creates the room described by createOptions in the same operation. This makes it the recommended default flow for drop-in multiplayer.

Match on a game mode and cap the room at eight players:

C++

Task<Result<MutableRoomView>> EnterDeathmatch(RealtimeClient& client)
{
    MatchmakingOptions matchmaking;
    matchmaking.Filter[PHOTON_STR("mode")] = PHOTON_STR("deathmatch");
    matchmaking.MaxPlayers = 8;

    CreateRoomOptions create;
    create.MaxPlayers = 8;
    create.CustomProperties[PHOTON_STR("mode")] = PHOTON_STR("deathmatch");
    create.LobbyProperties = {PHOTON_STR("mode")};

    co_return co_await client.JoinRandomOrCreateRoom(create, matchmaking);
}

Matchmaking Options

Field Default Description
Filter empty Custom properties a room must match exactly.
MaxPlayers 0 Only match rooms created with this player limit; 0 matches any.
Mode MatchmakingMode::FillRoom The fill strategy.
LobbyName empty The lobby to match in; empty targets the default lobby.
Lobby LobbyType::Default The type of the addressed lobby.
SqlFilter empty Query filter for the SQL lobby.
ExpectedUsers empty User ids to reserve slots for in the matched room.

Filter compares exactly: a room matches only when every property in the filter equals the room's lobby-visible custom property of the same key. Range or combination queries are not expressible here, that is what the SQL lobby is for.

MatchmakingMode picks the fill strategy. FillRoom (the default) fills rooms one after another, which gets players into full matches fastest; SerialMatching distributes players over the matching rooms in order and RandomMatching spreads them randomly, which keeps room populations even at high player counts.

Lobby Statistics

GetLobbyStats() returns a Task<Result<std::vector<LobbyStats>>> with the current player and room counts of each lobby on demand. Each LobbyStats entry carries the lobby Name, its Type, the PeerCount and the RoomCount.

For a continuously updated picture, construct the client with ClientConstructOptions.AutoLobbyStats = true (default false). The server then pushes statistics updates through OnLobbyStats; this push is independent of lobby membership and of the SetAutoJoinLobby setting.

Back to top