Matchmaking on top of Rooms
To start using Lobbies, please refer to the API.
A lobby is a virtual room that is not backed by a Replication Server. Lobbies have attributes and contain up to a certain number of players. Players also have attributes and can exchange messages in real time.
Matchmaking is the process of grouping players together based on a certain game-specific criteria.
The entire process consists of three phases - Matchmaking, Lobby Session and Game Session. The phases happen in exactly this order. Not all phases are mandatory.
The matchmaking phase is where players are grouped together based on certain criteria. In the case where players just want to jump into the game, the interface can be very simple - press the button to find other players to play with and that’s it.
The matching logic underneath is entirely game-specific so it is up to the developer to properly use the Lobby API in order to get the best possible result. To players it may look deceptively simple on the surface but under the hood the logic can get quite complex. Some games may require more sophisticated matchmaking logic so the matchmaking phase can be represented by an advanced UI that allows players themselves to create, browse and join lobbies on their own.
In the mockup above, Lobbies are filtered using the same matchmaking logic as in the previous scenario. The difference is that more than one result can be returned so players get to choose the best possible match out of the already curated list.
The Lobby Session phase begins once the player has found and joined a Lobby. Inside the Lobby players can exchange messages and have their data attributes synchronized until everyone is ready to start the game.
The first player to join a Lobby becomes the owner. There can only be one owner. Only the owner can change Lobby attributes and start the game. If the owner leaves the Lobby, one of the other players becomes the new owner.
Deciding when to start the game as an owner is entirely game-specific, and even the fact that a Lobby owner exists can be a hidden implementation detail and not exposed to the players. Alternatively, you may want to give the power to the Lobby owner to start the game whenever they want through an UI action. It is up to the game to decide how Lobby owners are handled.
Players can leave the lobby and new players can join at any time until the Lobby is full or until it is manually closed. Empty Lobbies are automatically deleted 5 minutes after the last player has left both the Lobby and the associated Replication Server Room (this can be adjusted on the project Dashboard). A couple of Lobby examples are shown below. You as the game developer have full freedom to come up with the logic and UX suited for your game.
Once enough players have joined the lobby the owner can start the game.
What we call the game phase is playing the game in a Room hosted by a Replication Server.
The process of creating Rooms and connecting all players at the same time, which can be quite complex to orchestrate, is handled by the SDK/backend.
When the Game Session starts, every player in the Lobby will receive a callback in Unity through the Lobby API with the Room endpoint data so they can connect to the Replication Server Room.
If no game-specific callback is registered, coherence will automatically connect the player to the Room using the CoherenceBridge component.
The Lobby still exists while the players are connected to the Replication Server. If you happen to disconnect or close your game and then log into the coherence Cloud again, the successful Login response will have the Room endpoint data available so you can reconnect and continue the Game Session phase.
When a Lobby is created, it can be either public or unlisted. Public Lobbies can be matched/searched and then joined by anybody. Unlisted Lobbies can be joined only if the player knows the Lobby ID. If a player leaves the Lobby they can rejoin again at any time.
When players start the Game Session, the Lobby can be optionally set to unlisted or closed as part of the process. If neither is set then the lobby remains in whatever state it was, i.e. either public or unlisted. In addition it is also marked as “in-game” (a room number is attached to the Lobby). Players can either choose to stay in the Lobby while in the game or leave the Lobby when they join the game.
Closed Lobbies can still contain players, i.e. if a Lobby is closed this doesn’t kick out the players. New players cannot join, only players who were in the Lobby when it closed can leave and rejoin. Closed Lobbies cannot be reopened.
Inactive players with no connection to the backend are removed from the Lobby after 1 minute. They can rejoin if the Lobby is not full.
When the last player has left both the Lobby and the associated RS room (if any), then and only then the Lobby is deleted after 5 minutes of inactivity.
This feature has been superseded by Cloud Storage.
Provides a database for storing key-value pairs from within game sessions.
The key-value store provides a simple way to store and retrieve data for the currently logged in player. For example, you could store the player's score, email address, or any other data.
This feature requires authentication.
The keys must be alphanumerical strings, underscore or dash. Currently, only strings are accepted as values. If you need to store numbers or complex types like arrays, you have to convert them to strings.
The total amount of stored data (keys + values) cannot exceed 256 KB per player.
There is no limit how often the data is stored or retrieved.
Player Accounts Authentication Service
To start using Player Account Authentication, please refer to the .
The Authentication service provides access to player accounts that uniquely identify them across multiple devices. Accounts are required in order to use the rest of the services.
There are two types of accounts - guest and user accounts.
Guest accounts provide an easy way to start using the services without providing specific user names or passwords.
The session data for the account is stored locally on the device, so it is important to know that uninstalling the game will also wipe out all the data and the account will be no longer accessible even if the player installs the game again.
User accounts require explicit authorization by the player. Currently, only user name and password are supported as means for authentication.
In the future, there will be support for more authentication platforms (for example, Steam).
Store data in the cloud
Cloud Storage is a general data storage service offered within the coherence Cloud.
Objects stored in cloud storage are identified using a tuple called storage object identifier or StorageObjectId
.
The storage object identifier consists of a type and an id. Type is intended to describe the general category that the object belongs to - for example, "Player" or "Settings" - and id is intended to uniquely distinguish the object from all other objects with the same type.
For example, to store player-specific data in cloud storage, you can set id to be the identifier of a user that has logged in to coherence Cloud:
The StorageObjectId
type is serializable by Unity, and can also be edited using the Inspector as a serialized field.
You must be logged in coherence Cloud to use this service. Read more about authentication on the Player Account Authentication page.
The CloudStorage API provides three methods, allowing you to save, load and delete objects.
The SaveObjectAsync method can be used to save an object to cloud storage.
The LoadObjectAsync method can be used to load an object from cloud storage.
The DeleteObjectAsync method can be used to delete an object from cloud storage.
All of CloudStorage's methods return a StorageOperation or a StorageOperation<TResult>.
These are Task-like objects. Methods that contain the async keyword can use await to wait for the operation to complete:
Coroutines can also use yield return to wait for the operation to complete:
It is also possible to execute a function when the operation completes successfully or fails, using OnSuccess and OnFail respectively.
If you need further info on how to do asynchronous programming within Unity, check out their documentation.
StorageOperations never cause exceptions to be thrown, even if you use the await
or yield
keywords with them. Instead, it is expected that you will detect and handle errors manually.
You can determine if a completed StorageOperation has failed using the HasFailed property. If an operation has failed, you can acquire more information about the failure via the StorageError object found in the Error property.
When an object is saved to cloud storage, its state is serialized to JSON using Json.NET.
By default all the public properties and fields of objects are serialized.
You can use Json.NET's serialization attributes to control how Json.NET serializes and deserializes your object.
In addition to supporting all the types that Json.NET can handle by default (primitive types, arrays, lists, dictionaries...), Cloud Storage also supports the following Unity types:
Saving and loading objects whose type derives from UnityEngine.Object is not supported. You can however serialize a UnityEngine.Object into a string using the built-in JsonUtility, and then save that string in cloud storage instead.
coherence Cloud has a rate limit of one API request of a particular type per second.
Having a rate limit of one API request of a type per second means is that if, for example, a save operation is made while another save operation is already in progress, then the second save operation will be queued, and will only get sent to the backend after one second has passed since the previous save operation.
However, the Cloud Storage service is able to automatically batch multiple storage operations into a single API request behind-the-scenes, which means that in practice an operation should almost never have to sit in queue for more than a second.
Currently, data is held for one hour. In the future, this will be configurable.
Any client can read or write storage objects at any time. Data is available as long as the client knows the identifier to access it.