Skip to main content

Multiplayer

Making multiplayer games with Easel is incredibly easy. Code as if all your players are in one shared world, like a singleplayer game, and Easel will make your game multiplayer, completely automatically!

How to enable multiplayer in your Easel game

To enable multiple players to join a game, set the maxHumanPlayers parameter for your game entrypoint function, like this:

pub game fn World.Main(maxHumanPlayers=10) {
// this is now a multiplayer game with a maximum of 10 players
}

If maxHumanPlayers is greater than 1, then the game will be a multiplayer game. Easel takes care of the rest. It really is that easy!

info

Multiplayer is baked into the fabric of the Easel programming language itself. That is why anything you code in Easel is multiplayer without any special effort on your part. It's like magic! See Rollback Netcode to learn more about how it works under the hood.

Matchmaking

When maxHumanPlayers is set to a value greater than 1, other players who are searching for a game with the exact same set of parameters may be added to the same game.

tip

The server has an internal limit on how many maximum human players can be in a game at once, and so it may not achieve the requested maxHumanPlayers if it is too high. Currently, the server limit is 16, but this may increase over time.

Players may also be limited to only joining games within their region. See Regions for more information.

Locking the game

Some games have the concept of a lobby, where players can join and leave before the game starts. In Easel, there is no separate lobby. Instead, the game begins in an "unlocked" mode where players can freely join and leave. Then, at some point, perhaps based pressing a "start" button once a minimum number of players have joined, the game becomes "locked", no new players can join, and the game can begin.

Call the LockGame function to lock the game. Once the game is locked, players cannot join or leave. This should be used when the game is about to start. For example, if your game is a racing game, call LockGame just before the race starts.

While LockGame stops new players from joining, the CommenceGame function marks the beginning of the game. Because in most games both of these occur at the same time, calling CommenceGame will first lock the game if it hasn't been already (equivalent to calling LockGame) before starting the game.

Once a game has been concluded using ConcludeGame, the game is also considered locked. In other words, players cannot join a game that has already ended.

Leaving players

When a player leaves, whether their player entity gets despawned or not depends on whether the game is locked. If the game is not locked, the player entity will be despawned when they leave. If the game is locked, the player entity will never be despawned, even if they leave. Instead, their IsPresent property will change to false. This is useful because sometimes the player entity owns other entities which are essential for the remaining players to be able to complete the game. It may be a good idea to watch the IsPresent property using a with block and make a bot take over control of the player entity when the player leaves so that the game can be completed.

The only change due to locking is whether the player entity is despawned or not. Signals like await BeforePlayerLeave still do fire just the same after the game is locked.

Locking applies immediately

LockGame applies instantly, even though it may take a fraction of a second for the server to get the message and stop adding players. Any players who are added within this fraction of a second will see the locked game but will not join it. As soon as their client detects the situation they will be reassigned to a new game.

This means your game can rely on no more players being joiniing the instant LockGame is called. This means it is safe to call LockGame and immediately begin the game.

Catching up

When a player joins a game, their client will need to replay all inputs that have been made so far. A "Catching up..." message will be shown to the player while they are catching up.

During the phase before LockGame when players are still joining, it is best to avoid complicated calculations that may slow down catching up to the game for new players. For example, wait until your game begins before adding bot enemies to the game.

Eliminating players

The Eliminate function tells the engine that the player is no longer actively participating in the game. Eliminating players can help improve the experience for the remaining players, as they will be excluded from the networking calculations. For example, you may want to do this when a player's tank is destroyed in a tank battle game. When the player respawns, you can set Eliminated = false (see Eliminated) to bring them back into the game.

Eliminated players will be changed from colored to grey on the Scoreboard to indicate their eliminated status.

Suspending upon inactivity

In multiplayer games, it is common for players to join, and then switch to another tab while waiting for other players to join. Sometimes the tab game is open for 10+ minutes while waiting.

In multiplayer mode, Easel games automatically suspend the simulation after 1 minute of inactivity, that is, 1 minute of no player inputs like mouse movements or key presses. This means that if another player joins after a long wait, they will not have to catch up on all the time that has passed, speeding up the joining process significantly. There is no need to waste computational resources on a game that no one is looking at!

tip

Only multiplayer games will be suspended after 1 minute of inactivity. Singleplayer games will run continuously, even without input. If you are making the kind of game where people just watch the screen without input for long periods of time, consider making it a singleplayer game instead.

How does it work?

When you publish your game onto the Easel platform, Easel's servers host your game for you, including all the multiplayer functionality. When a player joins your game, they will automatically be matched to other players who are also looking to play the same type of multiplayer game. Every input from each player is sent to all the other players in the game through a peer-to-peer relay. The Easel programming language has been carefully designed to be deterministic, which means that if any client takes the same sequence of inputs and simulates the game world, it will always arrive at the same game state, which is how Easel makes your game multiplayer without any extra effort on your part.

This is just the tip of the iceberg of how multiplayer works in Easel. See Rollback Netcode to learn more about how it works under the hood.