Getting into a room to play with (or against!) someone is very easy with Photon. There are basically three approaches: Either tell the server to find a matching room, follow a friend into their room, or get a list of rooms to let the user pick one.
We think, for modern games it's best to use quick and painless server-side matchmaking, so we discourage using room listings. Below, we will explain the options and things to keep in mind if you roll your own.
- Matchmaking Checklist
- Random Matchmaking
- Not So Random Matchmaking
- Play With Your Friends
- Other Matchmaking Options
If you are having issues matching players, here is a quick checklist:
- Verify that you are using same
AppIdin all clients.
- Verify that clients are connected to the same
Region. By design, Photon Cloud is region locked. Only players connected to same region can play with each other no matter what device or platform they're using.
- Verify that you are using same AppVersion in all clients. More information can be found here.
- Before trying to join a room by name, make sure that this room is created or use
- If you are trying to join a random room, make sure to choose the same lobby (name and type) used when creating it.
- If you are doing random matchmaking using room properties as a filter make sure to set the keys of those properties to be visible from the lobby when creating the room.
- If you are doing random matchmaking with SQL filters make sure to set the reserved filtering properties keys used to be visible from the lobby. It is also important to relax the SQL filter with each random matchmaking attempt or create new rooms at some point after a number of failed attempts.
- If you are implementing asynchronous matchmaking make sure to use webhooks with proper configuration (enable "AsyncJoin") or use AsyncRandomLobby.
The workflow described here gets players into rooms without asking them to pick one (randomly) from a long list of rooms.
If you just want to get players into a room quickly, do the following:
- Try "Join Random". This is an operation named
JoinRandomRoom, depending on the API / platform.
- In best case, that's it. Your client will join a room successfully.
- In worst case, no room is existing or no space is left in any room.
- If this doesn't find a room instantly, create one!
- If you never show room names (and why should you), don't make up a name. Let the server do this! Set null or "" as "room name" when calling OpCreateRoom. The room gets a guid which is unique.
- Apply a value for "max players". This way, the server eventually stops adding players.
- If your client is alone in the room (players == 1): Wait. Show a screen you're waiting for opponents.
- When enough players are in the room, you might "start" the game. To keep new players out, "close" the room. The server stops filling up the room, even if it's not full yet.
- Note: When you close the room, there is a short time where players maybe are already on the way in. Don't be surprised if someone joins even after closing.
Using this workflow, joining a game is a breeze for your players.
When you use this approach, check if your client API has a setting for "Auto-Join Lobby" (a parameter named "autoJoinLobby" or similar).
Make sure it's
false, to speed up your client's join workflow.
Not So Random Matchmaking
Totally random matchmaking is not always something players will enjoy. Sometimes you just want to play a certain map or mode (two versus two, etc.).
In Photon Cloud and Loadbalancing, you can set arbitrary "Custom Room Properties" and use them as filter in
Room Properties and the Lobby
Room properties are synced to all players in the room and can be useful to keep track of the current map, round, start-time, etc. They are handled as Hashtable with string keys. Brief names are better, so use "gm" instead of "GameMode" as example.
By default, properties are not sent to the Master Server to keep things lean. To make "map" and "game mode" available for for matchmaking, you can set a list of "room properties shown in the lobby" when you create a room.
Note that "ai" has no value yet. It won't show up in the lobby until it's set in the game via
Room.SetCustomProperties. When you change the values for "map" or "ai", they will be updated in the lobby with a short delay, too.
Keep the list short to make sure your clients performance doesn't suffer from loading the list.
Again: You don't have to join the lobby (and get the awfully long room list) to make use of
roomPropsInLobby. When you set some for the lobby, they become available as filter, too.
Filtering Room Properties in Join Random
OpJoinRandom, you could pass a Hashtable with expected room properties and max player value. These work as filters when the server selects a "fitting" room for you.
If you pass more filter properties, chances are lower that a room matches them. Better limit the options.
Make sure you never filter for properties that are not known to the lobby (see above).
Play with Your Friends
If your users communicate with friends (e.g. with Photon Chat), they can easily make up a room name and everyone just uses
OpJoinOrCreateRoom to get into that room.
A unique room name could be composed (e.g.) as: "friendName1 + friendName2 + randomInteger".
To avoid anyone else joining, create the room invisible like so:
JoinOrCreateRoom, the room gets created if it didn't exist.
If it's full, the operation
OpJoin fails, so check:
You can also find a friend with
OpFindFriends - if you got unique userIDs.
Publishing UserIDs in a Room
Photon uses a UserID in various places. For example, you can find friends only with a suitable UserID per player.
We added an option to Photon, which makes the UserID of players known per room.
For that, set
true, when you create a room.
The server will then provide the UserID and you can access it on the client via
- UserIDs are broadcasted, with player properties, in the Photon join event.
- The UserID for a client can be set in three ways:
- Client sets
- Returned by an external web service using Custom Authentication. It will override the value sent by the client.
- Photon will make up UserIDs (GUID) for users that don't explicitly set theirs.
- Client sets
- Generally, UserIDs, are not intended to be displayed.
Matchmaking Slot Reservation
Sometimes, a player joins a room, knowing that a friend should join as well.
With Slot Reservation, Photon can block a slot for specific users and take that into account for matchmaking.
To reserve slots there is an
expectedUsers parameter in the methods that get you in a room (
When you know someone should join, pass an array of UserIDs.
JoinRandomRoom, the server will attempt to find a room with enough slots for you and your expected players (plus all active and expected players already in the room).
The server will update clients in a room with the current
expectedUsers, should they change.
To support Slot Reservation, you need to enable publishing UserIDs inside rooms.
Example Use Case:
You can use this to support teams in matchmaking: The leader of a team does the actual matchmaking. He/She can join a room and reserve slots for all members.
The others don't have to do any matchmaking but instead repeatedly call:
When the leader arrives in a room, the
FindFriends operation will reveal that room's name and everyone can join it.
Photon is organizing your rooms in so called "lobbies". There is a default lobby but your clients can create new ones on the fly.
Lobbies begin to exist when you specify a lobby in
Like rooms, lobbies can be joined. In a lobby, the clients only get the room list of that lobby. Nothing else. There is no way to communicate with others in a lobby.
By now, we encourage everyone to not join lobbies: Often clients just get a long list of room names and players pick one randomly to finally start playing. There is not a lot information in a long list of room names, which have all the same ping.
To give your players more control over the matchmaking, use filters for random matchmaking.
Multiple lobbies can still be useful, as they are also used in (server-side) random matchmaking.
Lobbies are identified using their name and type. The name can be any string, however there are only 3 types of lobbies. Each one has a unique capability which suits specific use cases:
Default Lobby Type
Nothing special about this type of lobbies. It is the most suited type for synchronous random matchmaking. Probably the less sophisticated and most used type.
For example, the recommended default lobby (
TypedLobby.Default) has a
null name and
SQL Lobby Type
Simply put, this lobby type replaced "room-lists on clients" in favor for more elaborate matchmaking filtering in the operation JoinRandomRoom. This can be used for a server-side skill-based matchmaking that's completely client-driven.
Internally, SQL-lobbies list rooms in a SQLite table with up to 10 special "filtering-properties". Currently, the naming of those is fixed as: "C0", "C1" up to "C9". Only integer-typed and string-typed values are allowed and once a value was assigned to any column in a specific lobby, this column is locked to values of that type.
Despite the fixed filtering-property names, clients have to define which ones are needed in the lobby. Values for these room properties can be set anytime. Other properties can be set (as usual) but can't be used in matchmaking.
Queries can be sent in
JoinRandomGame operation. The filtering queries are basically SQL statements based on the "C0" .. "C9" values.
string sqlLobbyFilter = "C0 = "stringValue";
string sqlLobbyFilter = "C0 = \"stringValue\"";
You can use lobbies of the SQL-type to implement your own skill-based matchmaking.
First of all, each room gets a fixed skill that players should have to join it. This value should not change, or else it will basically invalidate any matching the players in it did before.
As usual, players should try to get into a room by JoinRandomRoom. The filter should be based on the user's skill. The client can easily filter for rooms of "skill +/- X".
JoinRandomRoom will get a response immediately as usual but if it didn't find a match right away, the client should wait a few seconds and then try again! You can do as many or few requests as you like. Best of all: The client can begin to relax the filter rule over time.
It's important to relax the filters after a moment. Granted: A room might be joined by a player with not-so-well-fitting skill but obviously no other room was a better fit and it's better to play with someone.
You can define a max deviation and a timeout. If no room was found, this client has to open a new room with the skill this user has. Then it has to wait for others doing the same.
Obviously, this workflow might take some time when few rooms are available. You can rescue your players by checking the "application stats" which tell you how many rooms are available. You can adjust the filters and the timing for "less than 100 rooms" and use different settings for "100 to 1000 rooms" and again for "even more".
Asynchronous Random Lobby Type
This lobby is similar to the default lobby type with one major difference only:
room entries stay in the lobby list for one hour after they are closed
(respective room state is removed from Photon Game Servers when all players have left and
Those rooms need to be visible to be received in the lobby list by the client. In case you need to show players available games.
In all cases, they need to be open to be joined in asynchronous matchmaking.
Other Matchmaking Options
If you want to roll your own matchmaking, please make sure that most of that is done server side. The clients don't have perfect information about how full rooms are as the room-list update frequency from server to client is low (~1..2 seconds).
When you have thousands of players, several will send their "join" requests at the very same time. If a room gets full quickly, your players will frequently fail to join rooms and matchmaking will take longer and longer.
On the other hand, the server can distribute players perfectly, preferring almost full rooms and respecting your filtering.
That said, using a room as matching place, before the actual gameplay starts, is in most cases not a good idea for popular games.