Introduction
Before reading please keep in mind this is a decently long read. There’s a lot to go over. By the end you should:
- Have an in-depth view of various matchmaking system approaches
- Have knowledge of the pros & cons of different approaches
- Have a basic idea of how to implement said approaches
Table of Contents
- Background Information
- Approaches
2.1 Same Server Matchmaking
2.2 Cross Server Matchmaking with MessagingService
2.3 Cross Server Matchmaking with HttpService - Conclusion
1.0 Background Information
What exactly is a matchmaking system? Rather than thinking in terms of Roblox let’s think in terms of some of the most popular games currently on the market. Fortnite, Valorant, CS:GO, Rainbow Six: Siege, etc. When a player loads up the game they are able to queue for a match where they will be placed with other players. There are different types of queues (casual, unrated, ranked, competitive, etc.). Some queues are entirely random where as others are based on tracked statistics (rank, kills, skill level, etc.).
This system is known as matchmaking. The game will find a match for you while queueing. This is an incredibly common concept and yet one that is rarely utilized or talked about on Roblox. I’m currently working on a game that will use a matchmaking system. Players are put into servers with a maximum of 20 players per server and will then have the main menu UI displayed where they can start/stop matchmaking. When enough players are in the queue (my game requires 4) the first 4 added to the queue are given priority and teleported to a reserved place.
2.0 Approaches
Roblox provides no easy way to implement this. The heavy lifting has to be coded from the ground up but there are a few ways to approach this. Each approach has various pros & cons so when making a matchmaking system it is important to decide what is most important for your game. I would like to note I did in fact create all these various approaches when deciding which was best for my game.
It’s worth keeping in mind that the following approaches share similar mechanics. This includes a queue system that manages players currently matchmaking, edge case handling for when players join/leave, opening a reserved place then teleporting the players there.
2.1 Same Server Matchmaking
The first and simplest approach is same server matchmaking. So how does this work? Well each server has its own matchmaking system per se. Basically when a player queues they are queueing with the other people in their server. So let’s say you have a lobby place with a max of 50 players. When players hit the matchmake button they get added to a queue. If enough players are in the queue remove them from the queue and teleport them. Pretty simple so let’s get into more complicated approaches.
Pros
- Very easy to implement
- Significantly more reliable compared to other approaches
Cons
- No cross server matchmaking
- If players are AFK they might never find a game
- Custom lobbies with private invites are not very viable
- Limited to same server players
2.2 Cross Server Matchmaking with MessagingService
So firstly what is MessagingService? It’s a service Roblox offers for cross server communication. On the threads I’ve read about matchmaking systems this seems to be considered the ideal way to handle matchmaking. The reason for this being it’s offered directly from Roblox and isn’t too much off a hassle to implement.
The way this approach works is by dedicating one server to be the “host” server. This server is randomly assigned and will always be the first server that starts in a place. The host server handles the actual matchmaking queue as well as an active server table that stores the JobIds of other servers that are online.
This data is stored & received by the host server specifically subscribing to certain topics using MessagingService. For example, it will listen for a topic called ServerUpdated
. When something is sent to this topic it will then handle it. In this case the topic is called from other non-host servers that will pass in a request (ServerAdded
, ServerRemoved
, etc.) as well as some data. When a server that is a non-host server starts up it will check if it is the host (usually through a datastore). If it isn’t then publish to the ServerUpdated
topic passing in ServerAdded
as well as the JobId of that server. It will then get added to the active server table.
This same process has to be repeated with actual matchmaking. A topic has to be created & listened to on the host for matchmaking. When a player queues the topic is published to with a certain request (such as Matchmake
) and when they dequeue it is published to with another request (such as EndMatchmaking
). The host adds the player to the queue, checks if there are enough players in the queue, then does teleporting by publishing to all servers who are listening to a teleport topic.
It’s also worth noting that rehosting is an important part of this approach. If a host server goes offline (all players leave and the server is closing) then a request needs to randomly be sent to a non-host server to become the new host.
This approach appears solid. Except for the countless posts talking about unreliability using MessagingService. Sometimes requests aren’t sent or received and this can cause major issues. You can’t return values using MessagingService so determining if a player is successfully queueing or if a server got added to the active servers table requires extra leg work and can be tedious.
Pros
- Cross server matchmaking
- Custom lobbies with private invites are very viable
Cons
- Potential unreliability
- MessagingService is rate limited
- Hard to implement
2.3 Cross Server Matchmaking with HttpService
Before reading any further I should mention that this approach can cost money depending on the size of your game. So if you decide to implement this approach be realistic with how well you expect your game to do! You should also have some prior JavaScript experience.
This approach relies on a web app as well as a REST API. To create a web app I’m using Glitch. Using Glitch you can create web apps extremely easily and they provide the tools necessary to create a REST API using Node.js.
For my web app I used the express framework. However, it may be worth looking into alternatives such as fastify.
Something important to remember is you’ll be using an API Key to access the backend of this web app. It will be passed as a header when making HTTP requests from Roblox. Save your API Key in a .env
file that can be accessed using process.env.API_KEY
. On Roblox you need to keep this API Key secure. I recommend writing part of the key to a datastore, and storing another part in a model that can be fetched using InsertService. This is fairly secure. It’s also possible to implement hashing algorithms for further security.
In your web app you’ll have various routes that will handle various functions. For example, my web app adds a new player to the queue like so:
/*
Add a player to the queue
*/
app.post('/queue/add/:playerid::serverid', (req, res) => {
validateKey(req, res); // Validate the API key
const playerId = req.params.playerid;
const serverId = req.params.serverid;
const alreadyExists = matchmakingQueue.some(queueElement => queueElement.playerId === playerId);
// Add to queue if not already in queue
if (alreadyExists)
res.end();
else {
matchmakingQueue.push({
playerId: playerId,
serverId: serverId
});
}
// Handle teleporting players if the queue matches the correct number of players
const playersToTeleport = resolveQueue();
if (playersToTeleport != undefined)
res.json([...playersToTeleport])
});
Then in Roblox you just send these HTTP requests and handle the responses. No host server needed since the web app basically acts as the host.
Pros
- Easy to implement
- Cross server matchmaking
- Custom lobbies with private invites are very viable
- Rate limits are barely noticeable (500 requests/min is more than sufficient)
- Can be further reduced by storing a local queue in Roblox
Cons
- Security can be a problem
- Unfortunately Roblox doesn’t have a very good way of securing private information like API keys
- Potential cost
- While Glitch provides a free web app solution the app automatically goes offline after 5 minutes
- This can be prevented by upgrading your account for $8/month
- Alternatively you can look at other ways to send requests to your web app to keep it online
3. Conclusion
I hope this tutorial furthered your knowledge on matchmaking systems. There are very few resources on this topic and I do hope to eventually see Roblox tackle it head on with something like a MatchmakingService. If you have any questions feel free to ask.