Multiplayer¶
The Beamable Multiplayer feature allows game makers to create real-time and turn-based multi-user game experiences.
What is a game server? A game server is the source of event coordination in a multiplayer video game. The server transmits enough events about its internal state to allow each connected client to maintain their own accurate version of the game. Events may contain various types of information including; properties about the game world, the players, and player input. See Wikipedia for more info.
Game Servers¶
Here are the leading options;
Dedicated Server
- The server processes game-specific logic. The server is the game.
- Ideal For: Persistent world games, MMOs, and first-person shooters.
Peer-To-Peer Server
- The server introduces client to client. Key communication passes directly from client to client.
- Ideal For: First-person shooters and games that can tolerate cheating.
Relay Server
- The server sends and receives events between all clients in a match. The match is the "Room" in which all the game players interact. Each client is the game.
- Ideal For: Real-time strategy, tower defense, MOBAs, card battlers, auto chess, and more...
Here is a comparison of various game servers;
| Default Benefits | Relay Server | Dedicated Server | Peer-To-Peer Server |
|---|---|---|---|
| Lower Bandwidth | ✔️ | ❌ | ❌ |
| Simpler Server Infrastructure & Simpler Setup | ✔️ | ❌ | ❌ |
| Client-Authoritative | ✔️ | ❌ | ✔️ |
| Lower Cost | ✔️ | ❌ | ❌ |
| Higher Security | ✔️ (Determinism) | ✔️ (Server-Authoritative) | ❌ |
| Lower Latency | ✔️ | ✔️ | ✔️ |
Beamable Multiplayer¶
The Beamable Multiplayer API is lean and straightforward to setup. The pipeline and workflow for development are ready out-of-the-box on day 1 of development, allowing game makers to focus on game-specific client logic.
Beamable Multiplayer uses relay server technology for rapid game development.
Beamable's Multiplayer is a relay server. This means that Beamable keeps a list of all events sent from all clients in a given match. Then, via push or pull, each client can ask "for all events since last time I asked". The clients then MUST advance the game play deterministically, replaying each player's input, so each client is in sync.
Plus, with Beamable Multiplayer, the game logic can access the full suite of Beamable functionality including Inventory, Cloud Save, and more!
here is a high-level diagram of the Beamable Multiplayer terms
| Name | Detail |
|---|---|
| Client | This refers to the instance of the game code that is running on each player's local device (e.g. Mobile Phone) |
| Event | The data packet that represents a player's turn in the game. This may be any serializable C# structure. |
| Latency | This measurement indicates the average total time needed for the game client to send an event to the Multiplayer server and receive the reply. Latency is measured in milliseconds (e.g. 200ms) |
| Matchmaking | This is the process of choosing a MatchId based on criteria. E.g. "Give me a match to play in with 3 total players with beginner skill level". Beamable includes an optional, light-weight Matchmaking service.Note: See Matchmaking for more info |
| SimClient | This class is the main entry point for Beamable's Multiplayer feature. |
| SimClient's TargetNetworkLead | This is network buffer. It represents how long the Multiplayer server holds game events before sending them back to clients. E.g. With a value of 5, the Multiplayer server will hold 5 events before sending those 5 to the game client's. A higher value provides more consistency to the clients' rendering experience, but at the cost of higher latency. |
| SimClient's Match | This represents a set of players playing a specific instance of the game together. Only players in the same match may collaborate, compete, and communicate. |
| SimClient's FramesPerSecond | This is the rate (in times per second) at which the client receives event updates from the Multiplayer server. As a data optimization, typically this is set lower than the rendering frame rate of Unity. |
| Server | This refers to the instance of the server code that sits between the game's clients and manages distribution of the game events. |
Game Security¶
To be more secure against any malicious hackers in your multiplayer game's community, consider never sending any game object state (player's heath, power of weapon, etc) as part of the messages to be synchronized over the network.
Any enterprising hacker can "easily" hack a game client to send inflated values which will only make the game worse for everyone. If all a player can do is send an "action". i.e. "What I did" ("I fired my equipped gun" rather than "I hit player 2 for 100 damage"), it becomes quite a bit harder for someone to cheat.
A hacker may also attempt to replay actions AGAIN for a particular turn or to send malformed game event object messages that can lead to a worst experience for other players.
Matchmaking¶
In multiplayer gaming, matchmaking is the process of choosing a MatchId based on criteria (e.g. "Give me a match to play in with 2 total players of any skill level"). Beamable supports matchmaking through its matchmaking service.
See Matchmaking for more info.
Playing "Against Yourself"¶
One of the challenges of developing a multiplayer game is testing it frequently as an individual developer. Finding a friend to play against you every time you run the game in development is prohibitive.
Here are 2 strategies to help the development process.
Adding a Bot¶
The sample game includes an optional bot opponent. This is an AI that plays against you. Simply click "Start Game: Human vs Bot" from the Menu Scene to activate it. Architecturally this is similar to the full game and it fully uses the Beamable Multiplayer event objects for each player move. However, it requires only one human player.
Playing Against Yourself¶
The sample game allows a workflow to test the full 2 player experience with relative ease. Build the Unity sample project as a standalone game for either Mac or PC. Then run the game in the Unity Editor also. Simply click "Start Game: Human vs Human" from the Menu Scene in both game clients to activate it.
Doing a build takes a few minutes. Depending on the specifics of your game, it may not be required to rebuild the standalone after every code change.
This is the process of choosing a MatchId based on criteria. E.g. "Give me a match to play in with 3 total players with beginner skill level". Beamable includes an optional, light-weight Matchmaking service.
Randomization and Determinism¶
In single-player game design, game makers may freely use randomization libraries to add variety to game play. The environment may be randomized, the enemy amount and variety can change every game session. This adds richness and replayability to the game.
In a multiplayer game its important that all players in a given game session have the SAME "random" experience. But how?
Randomization is supported by Beamable's Multiplayer with the following advice. During initialization the Beamable SimClient will pass along the same seed value to feed the random operations on each client. By using the same seed, each game client will be in-sync.
Multiplayer API¶
Here is the High-level Sequence for Beamable Multiplayer.
Experimental API
This API is experimental and may change in future versions.
Creating Multiplayer Session¶
Each game client connects this way. No one client has special status of 'host'. Depending on the needs of the game, the SimClient session may stay from the moment any one player joins until the moment the last player leaves.
1 | |
Create Custom Event
Depending on the complexity of the game play, there may be dozens of custom events.
1 2 3 4 5 6 7 8 | |
Subscribing To Events¶
The client must repeat this for each PlayerId of interest.
1 2 | |
Sending Events¶
Typically each player's input is converted into an event.
1 2 | |
Handling Event¶
Typically for a fair and consistent game play experience, best practices dictate that all events, even the local clients own player's events are sent to the server, later received, and then converted to rendered graphics and sounds. This way the requisite latency is the same for the local client as it is for all other clients in the same match.
1 2 3 4 | |
Handling Network Faults¶
It is possible that temporary network outages may occur. While these errors are occurring, player communication with the Beamable Game Relay is blocked, and no messages will be sent or received. When network connectivity resumes, the session will resume sending and receiving events.
Errors can be caught using callbacks available on the SimClient instance. When a network outage event occurs, the OnErrorStarted event will always trigger first. Later, when the outage has recovered, the OnErrorRecovered event will trigger. However, if the outage is too long, or if there is a different unrecoverable error, the OnErrorFailed event will trigger.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
The effect of OnErrorFailed event can also be captured by using a try/catch around the SimClient.Update function, like so...
1 2 3 4 5 6 7 8 9 | |
In the event that a network outage is unrecoverable, the entire SimNetworkEventStream instance needs to be reconstructed. Any further calls to SimClient.Update will re-throw the SimNetworkErrorException.
Custom Fault Tolerance¶
It is possible to inject custom network outage fault tolerance logic. Use Custom Dependency Injection to inject a new instance of ISimFaultHandler, or pass in a custom instance of ISimFaultHandler as an optional parameter to the SimNetworkEventStream.
The default implementation of the ISimFaultHandler is the DefaultSimFaultHandler.
Change Default Fault Tolerance Duration
By default, the DefaultSimFaultHandler instance will allow for 15 seconds of network outage before reporting an unrecoverable error. This duration can be adjusted by passing in a custom instance of the DefaultSimFaultHandler to the SimNetworkEventStream.
1 2 3 4 5 | |
Sample Code¶
Here is a complete Beamable Multiplayer example which creates a game session and sends/receives game events.
MultiplayerExample.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | |