How to make a global matchmaking system (Updated)

Greetings devs,

Not too long ago I shared a global matchmaking, and I’ve decided to revamp the post, with better explanation and footage.
This system is much simpler than other ones that I’ve seen, and not too hard to understand. Or at least I think it’s not too hard to understand, as I only started scripting a bit more than a month ago.
This matchmaking system will also include the total players ready.

Note: I have 2 RemoteEvents inside of ReplicatedStorage: “Ready Up” and “Total Players Ready”

This is inside of the ready up button Gui:

-- Note: You can put whatever text and colours you want for the Gui

script.Parent.BackgroundColor = BrickColor.new(0, 200, 0) -- Not ready colour
script.Parent.Text = "ready up like a pro" -- Not ready text
local ready = false -- The variable to control when the player is ready or not, as you can probably see

script.Parent.MouseButton1Click:Connect(function()
	if ready == false then -- This will determine if the player goes ready or unready, based on the current value of the variable
		script.Parent.BackgroundColor = BrickColor.new(200, 0, 0) -- Ready colour
		script.Parent.Text = "unready like a noob" -- Ready text
		ready = true
		game.ReplicatedStorage["Ready Up"]:FireServer(ready) -- Fires a RemoteEvent that will tell the ServerScript (which controls everything) that the local player readied up
	else
		script.Parent.BackgroundColor = BrickColor.new(0, 200, 0)
		script.Parent.Text = "ready up like a pro"
		ready = false
		game.ReplicatedStorage["Ready Up"]:FireServer(ready) -- Tells the ServerScript that the local player un-readied
	end
end)

This is inside of a ServerScript:

playersReady = {} -- This list will have a list of every player that is ready
shouldReply = true -- Whether this server will tell a new server how many players are ready or not
shouldChange = true -- Whether this server will change based on the other servers sending back how many players are ready or not

messagingService = game:GetService("MessagingService")

messagingService:SubscribeAsync("Queue", function(msg) -- This subscribes to the sub-category of messaging service (the queue)
	if string.find(tostring(msg.Data), "157981355") then -- This finds the number telling the server if the player is ready or unready; in this case, "157981355" means ready
		table.insert(playersReady, string.sub(msg.Data, 1, -10)) -- Removes the number telling the server to ready or unready the player, then adds it to the playersReady list
	elseif string.find(tostring(msg.Data), "058375937") then -- This finds the number telling the server if the player is ready or unready; in this case, "058375937" means unready
		table.remove(playersReady, table.find(playersReady, string.sub(msg.Data, 1, -10))) -- Removes the number telling the server to ready or unready the player, then adds it to the playersReady list
	end
	game.ReplicatedStorage["Total Players Ready"]:FireAllClients(playersReady) -- Tells our last script how many players are ready
end)

messagingService:SubscribeAsync("GetExternalPlayersReady", function() -- Servers that already exist are told to send the number of players ready with this function
	if shouldReply == true then
		shouldChange = false
		messagingService:PublishAsync("ExternalPlayersReady", playersReady) -- Tells our brand new server how many players are ready
		wait()
		shouldChange = true
	end
end)

messagingService:SubscribeAsync("ExternalPlayersReady", function(msg) -- The new server will use this to get how many players are ready in an external server
	for i in pairs(playersReady) do
		table.remove(playersReady[i]) -- Clears the current playersReady table
	end
	for i in pairs(msg.Data) do
		table.insert(playersReady, msg.Data[i]) -- Adds the players ready in another server the this server's playersReady table
	end
end)

game.ReplicatedStorage["Ready Up"].OnServerEvent:Connect(function(playerName, ready) -- Detects when a player readied or unreadied
	game.ReplicatedStorage["Ready Up"]:FireClient(playerName, ready)
	if ready == true then
		messagingService:PublishAsync("Queue", tostring(playerName).."157981355") -- This can be a number or code of any length, but make it something that no one has in their username.
	else
		messagingService:PublishAsync("Queue", tostring(playerName).."058375937") -- Same with this code.
	end
end)

game.Players.PlayerRemoving:Connect(function(playerLeaving)
	if table.find(playersReady, tostring(playerLeaving)) then
		messagingService:PublishAsync("Queue", tostring(playerLeaving).."058375937") -- Removes the player that left's name from the playersReady table; if it's on there
	end
end)

game.Players.PlayerAdded:Connect(function(playerJoining) -- Detects if this is a new server, if so, it will get the list of players that are ready from another server
	if #game.Players:GetPlayers() == 1 then
		shouldReply = false
		messagingService:PublishAsync("GetExternalPlayersReady", "")
		wait()
		shouldReply = true
	else
		game.ReplicatedStorage["Total Players Ready"]:FireClient(playerJoining ,playersReady)
	end
end)

This is inside of a Gui showing the total players ready:

game.ReplicatedStorage["Total Players Ready"].OnClientEvent:Connect(function(playersReady)
	if #playersReady == 1 then
		script.Parent.Text = #playersReady.. " player is ready"
	else
		script.Parent.Text = #playersReady.. " players are ready"
	end
end)

Here’s some footage of it in-game:

19 Likes

Don’t… please… NO SPACES IN INSTANCE NAMES AHHH

Pretty good tutorial, definitely simpler than what I would have made.

You could just use a symbol (not . though), like ready@<playername> and unready@<playername>, or use multiple channels. I initially thought they were user IDs or something.

3 Likes

Sorry to bump this, but I’m curious if this could be improved by using MemoryStoreService instead of MessagingService?
https://developer.roblox.com/en-us/articles/memory-store

It has a built-in queue function and has lower latency compared with DataStores as well as a higher request rate.

6 Likes

does it teleport people to a game

2 Likes

image

Nevermind, it looks like it works now.