This is a guide to building the back-end of a simple game character selection system that lets us see the character selected by other players in our device in real-time. Let us explore how we can implement a character selection system for a real-time multiplayer game.
The main goal of this module is to allow our players to pick a character from a set of available characters and make it visible to other players in real-time. If there is no real-time validation of the selected characters, multiple players might select the same character. We need a system where the different player can select their desired character on a first-come, first-serve basis. That means, if one player selects a specific character, then other players should not be able to select that same character. In this article, we will learn how we can make such a system for character selection.
Before diving into the details, we assume you have already set up a new project with some sort of socket connection and already know the basics of the event system used by Socket.io. If not, it's a good idea to learn the basics of Socket.io in Unity and set up a dummy server before moving forward.
This guide is simply an overview of the architecture, unlike a tutorial where you follow step-by-step guides. Instead, I'll share how you can build a few different pieces and put them together, so let's dive right into the details.
We need to make a simple database that will hold information about all the players and their selected characters. Personally, I'd pick MongoDB because of its simplicity over a relational database. A Redis server would suffice too. For the sake of this article, I'm using MongoDB with Mongoose.
I have a Users model that contains basic information about the player. A player can only be present in only one room, so we have a
roomName field to keep track of the game the player is currently playing.
I also have a Rooms model, which basically represents a game. It contains basic information about the game, the list of players, and more. The property that we are interested in is the
characters property. It contains the list of characters selected by the players. Both the
characters are ordered lists of
String. The first item of the
characters list represents the character of the first item of the
These two models are the only essential collections we need to get started. The
Rooms model also contains a property
gameStarted that keeps track of whether the game has started.
Next, we need to write a controller that listens for events emitted by the client when one of the players picks a character. Let's call the event
CharacterChange . The event will be fired by a game client, such as a Socket.io client in Unity, whenever a player changes a character.
Here's a sample code to do just that.
Let's break down the controller's job into smaller pieces so we can understand better.
- When the client sends the selected character for the given player, we look at the
characterslist in the user's current room to see if the character is already in use. If it's already there, we reject the request to change by ignoring it or sending an appropriate message.
- If the character is not in use, we set the new character to the
characterslist for the player. Then we emit an event to all the connected clients in the room to send the
That's all. After receiving the event, it's the clients' job to properly update the UI to mark the unavailable characters.
What about Race conditions that might occur from multiple requests?
Different databases have different ways of dealing with race conditions when reading or inserting data into or from the database. In the case of MongoDB, we need to use some sort of validation inside the
findOne callback. Redis has its own way of handling race conditions by using transactions. Based on your choice of database, you might have to look by yourself at how race conditions can be handled. In the end, the goal is to ensure that two players don't select the same character.
That's it. I hope you at least know a basic concept about how character selection can be updated in real-time for different players in the same lobby.