Serverless multiplayer game
Multiplayer games are a popular game mechanic that allow multiple players to interact and play games together. This sample demonstrates how to create or join a Lobby Service game lobby and compete in a simple arena-style game where players collect coins for points.
To use this sample use case, you must download and install the UGS Use Cases project in your Unity project.
During the course of the sample, players can perform the following actions:
- Randomize their names.
- Create public and private lobbies for others to join.
- Join lobbies either from a list of public lobbies or by entering a secret key to join private ones.
- View other players in the lobby.
- Signal they are ready to start the game.
- Play a multiplayer game using Relay Service and Netcode for GameObjects (NGO) to facilitate player movement and collect coins for points.
- View information such as winners, scores, and personal high stats at the end of the game.
Important: Unless you are testing the serverless multiplayer game sample on different devices you must set each instance to a different profile using the profile switcher drop-down at the top of the screen. See Set up computer to test multiplayer for explanation and additional details.
To see this use case in action, open the samples menu and navigate to Serverless Multiplayer Game. To open this scene directly and interact with the use case:
- In the Unity Editor Project window, select Assets > Use Case Samples > Serverless Multiplayer Game, then double-click
ServerlessMultiplayerGameSample.unityto open the sample scene.
- Press Play to enter Play mode.
When the scene loads, the following initialization steps occur:
- Sample-related managers are set to DontDestroyOnLoad so they can remain intact in all scenes of the sample.
- The Profanity Manager is initialized, causing all valid player names and lobby words to be propagated to the allow list so only permitted words will be presented to the player.
- UGS is initialized and the player signed in with the correct profile name.
- Remote Config is read to configure coin spawning, game duration, etc.
- The main menu is shown so the player can choose to host or join a game, randomize his/her name, change UGS profile name to use, etc.
Set up computer to test multiplayer
You must be able to play multiple instances of this sample to test this use case.
The following are some techniques to facilitate multiplayer testing:
- Clone the repository again (or copy the project folder) to another folder. You can then open both/all instances in the Unity Editor simultaneously and enter Play Mode in each instance to test the sample.
- Use ParrelSync to clone the project. This is the preferred method because changes made to the base project automatically propagate to all clones for testing. Note that this is not a Unity product so we recommend reviewing the documentation and license agreement before using.
Important: In either of the above cases, ensure that each instance is signed in to UGS with a different anonymous ID.
Do this by changing the
Profile ID on the main scene to a different profile (the scene defaults to the last profile used or
Profile-1 by default).
Changing this profile selection signs you in to a different Authentication service profile which simulates having multiple accounts on a single device.
Note that the profile switcher only works on the main scene; once you leave to create or join a lobby, the choice is locked in and you cannot change it until you return to the main scene.
For more details, refer to Manage profiles.
This use case contains multiple scenes to divide the sample into smaller pieces, allowing developers to only review the implementation they're interested in learning.
Always begin Play Mode with the
ServerlessMultiplayerGameSample scene, which changes to the other scenes as needed.
The sample begins with the
ServerlessMultiplayerGameSample scene where players can choose to start or join a lobby, randomize their player name, and, if creating a lobby, randomize the lobby name, and adjust setup parameters such as max players or public/private flag.
The player remains in this scene until a lobby is either created or joined, both of which causing play to progress to the
Once a game ends or the player leaves the
Lobby scene, they return to this scene.
If the player just finished playing a game, the results screen displays the outcome along with the current player's stats.
Closing the results screen returns the player to the main menu so another lobby can be created/joined to start a new game.
Once a lobby has been created or joined on the
ServerlessMultiplayerGameSample scene, the sample opens the
Lobby scene, which shows the contents of the current lobby, and permits players to signal ready or leave.
Additionally, the host has the option to remove players from the lobby.
All players are required to signal they are ready before a game can begin.
Players remain in this scene until all players are ready (play proceeds to
Game scene), or the player leaves the lobby and returns to the
After a minimum of two players have joined the lobby and all players have signaled ready, the
Game scene launches, where an immediate countdown from three begins.
Once complete, players can move and collect coins, which are spawned individually or in clusters (based on the Remote Config configuration).
Once players can move, the game timer begins counting down and the game ends once the game timer expires.
When the game ends due to the game timer expiring, players automatically return to the
ServerlessMultiplayerGameSample scene, where the game results as well as each player's personal stats appear.
Once that results screen closes, the main menu reappears (still in the
ServerlessMultiplayerGameSample) and another lobby can be created or joined.
Notable manager classes
This use case has a few notable manager classes that facilitate different aspects of the sample.
ProfanityManager class ensures that user generated strings don't contain offensive language, while the
GameManager class processes requests from players, controls gameplay, and updates clients’ state based on game events.
This sample implements a Profanity Manager to ensure that the player and lobby names created by one player, but visible to all players, do not include any offensive language.
ProfanityManager class uses an allowlist to validate the strings that the client receives from the Lobby Service.
This validation ensures that even if one player hacks the system to submit an offensive string, any other players who receive that lobby name or username would not be able to see the invalid string.
Note that using an allowlist for input such as usernames can be limiting, since it is difficult to make such a list exhaustive. In this case, you could instead use a blocklist to filter out the specific words deemed inappropriate.
You can find the
ProfanityManager class in
Serverless Multiplayer Game/Scripts/Menu/ProfanityManager.cs, and the strings included in the player and lobby names allowlists are in
Serverless Multiplayer Game/Scripts/Menu/PlayerNameManager.cs and
Serverless Multiplayer Game/Scripts/Menu/LobbyNameManager.cs, respectively.
If you wanted to use a refactored version of the Profanity Manager, replace the
ProfanityManager.IsValidLobbyName methods with your own implementation.
Game Network Manager
Being a multiplayer game, this sample requires a Game Network Manager to facilitate game communication between players.
The Game Network Manager is instantiated on the host when the
Game scene is first loaded due to the existence of a
GameSceneManager in the scene.
This Game Network Manager instantiates the Game Network Manager in its
The Game Network Manager handles things such as
- Starting the host/client
- Creating player avatars for all players
- Coordinating countdowns and game timers
- Allowing players to move to collect coins once countdown is complete
- Communicating with other managers when needed, such as when scoring
- Coordinating game over by propagating the final score and waiting for all players to acknowledge receipt
- Issuing request that all players return to main menu
As mentioned above, the Game Network Manager is instantiated at runtime so it can be properly configured on the host using
Thus, the host has control of the Game Network Manager, and all clients are able to interact with it as needed to facilitate gameplay.
GameNetworkManager class can be found at
Serverless Multiplayer Game/Scripts/Game/GameNetworkManager.cs.
To replicate this use case, you'll need the following Unity packages in your project:
|Automatically sign in the user anonymously to keep track of their data on the server side. This sample also uses the Authentication service to switch profiles to simulate different players to facilitate multiplayer testing.
|Stores the player's name, win/games counts and high scores.
|Handles creating or joining lobbies so players can gather to start a game. The lobby also stores each player's ready flag, as well as the Relay Join Code, which is needed to join the Relay Service allocation to facilitate real-time gameplay.
|Netcode for GameObjects
|Spawn network objects such as player avatars and coins, synchronize movement and despawn network objects as needed.
|Creates/joins a multiplayer allocation to facilitate real-time gameplay with the creator of the lobby acting as relay service host.
|Maintain game settings such as coin spawning frequency, coin wave sizes, game duration, etc.
To use these services in your game, activate each service for your Organization and project in the Unity Cloud Dashboard.
This sample uses Cloud Save to store each player's lifetime stats, which include name, win count, total game count and high scores. Note that using different profiles results in each having separate UGS data, so each player sees different stats.
The following is an example of a player's Cloud Save data:
"highScores": [33, 27, 17],
To replicate this sample scene's setup in the Unity Cloud Dashboard, you must:
- Configure values for the Remote Config service.
Set up the following config values in the Unity Cloud Dashboard:
|List of game settings for all possible games, based on the number of players in the game.
Additional information about the fields in the above config value:
|Number of players in specified configuration. Valid values are 2, 3 and 4 and there must be 1 of each to specify game configuration for each count of players.
|Length of game in seconds. All games currently last 60 seconds, but these values could be changed for longer games with more players.
|How long to wait to spawn first set of coins. This permits players to get their bearings before the initial wave of coins appears.
|How long do coins remain in play before despawning. This adds urgency because coins can disappear, requiring players to hurry to capture them in time.
|How long to wait after a wave of coins is spawned before spawning the next wave. Coins spawn in waves so players have multiple options of coins to attempt to collect.
|How many clusters of one coin (that is, individual coins) should be spawned in each wave. There is usually one cluster of one, so a player with no better option can at least try for the single coin.
|How many clusters of two coins (that is, pairs of coins) should be spawned in each wave. There is usually at least one cluster of two coins so one of the players can have an opportunity to score two points while the other player only gets one.
|How many clusters of three coins to spawn per wave. Two-player games don't need clusters of three, but games with more players can add three coin clusters.