How to make a GUI lobby?

Does anyone know a good tutorial on how to make a GUI lobby? Basically I wanna create a 2D player lobby list where players can make teams and join in other public teams but I can’t seem to find anything that could help me making one.

2 Likes

I’m currently making one myself, what you need to do is use remote events. When creating a lobby, I fire the server from the client, and fire all clients from the server to make a lobby appear to all players. Similar story with joining and leaving a party, using remote events. These are some of the scripts I made and am currently using. It’s still a little buggy and un-refined.

CLIENT SIDE SCRIPT THAT RUNS WHEN THE CREATE PARTY BUTTON IS CLICKED.


local debounce = true -- This is a debounce so you cannot create more than one lobby.

script.Parent.MouseButton1Up:Connect(function(player)
	if debounce == true then	
		debounce = false		
		script.Parent.Parent.Join.Visible = true -- This is the host's client's frame that shows the players in the lobby.

	    local username = game.Players.LocalPlayer.Name -- This is the name of whoever created the lobby

		game.ReplicatedStorage.CreateParty:FireServer(player, username) -- Transfers the name of the party creator to server side.

		script.Parent.Parent.List:TweenPosition(UDim2.new(-1.234, 0, 0.499, 0),Enum.EasingDirection.InOut, Enum.EasingStyle.Sine, 0.6) -- This tween makes my lobby list go off screen so you cant join your own lobby.
	end	
end)

SERVER SIDE SCRIPT THAT RUNS WHEN CLIENT FIRES SERVER

game.ReplicatedStorage.CreateParty.OnServerEvent:Connect(function(players, username) -- "username" is the name of the person who created the party.
	game.ReplicatedStorage.CreateParty:FireAllClients(players, username)

end)

CLIENT SIDE SCRIPT THAT RUNS WHEN ALL CLIENTS ARE FIRED FROM THE SERVER SCRIPT

game.ReplicatedStorage.CreateParty.OnClientEvent:Connect(function(username)
	print(">> Success.") -- Just here to check whether the remote event was successfully fired

	local hh = tostring(username) -- This is the name of the party creator we got when firing the server, and then firing all clients.
	print(">>", hh, "created a party!") -- Not required.
	
	local cloned = script.Parent.Player:Clone()	-- This created a small frame inside of another frame I have, which is a list of all parties that have been created.
	
	  cloned.Name = tostring(username) -- This is important, to name the frame, due to a button that 
    deletes the party.
    -- Remember to use "tostring" as when transferring the data, it turns the username into a 3 digit number that cannot be used.
	cloned.Parent = script.Parent
	cloned.TextLabel.Text = tostring(username) 
	cloned.Visible = true

end)

CLIENT SIDE SCRIPT TO DELETE THE PARTY

script.Parent.Parent.Delete.MouseButton1Up:Connect(function(player)	
	script.Parent.Parent.Join.Visible = false
	debounce = true	
	local username = game.Players.LocalPlayer.Name -- This is the name of whoever is deleting the party.
	game.ReplicatedStorage.DeleteParty:FireServer(player, username)	 -- Same story as creating the party, you need to transfer the username of the deleter so you can delete the party for all clients.
	script.Parent.Parent.List:TweenPosition(UDim2.new(-0.234, 0, 0.499, 0), Enum.EasingDirection.InOut, Enum.EasingStyle.Sine, 0.6) -- This tween brings back my party list frame. You can use the visible boolean if you want, but that doesnt looks as nice all the time.
	wait(0.7)
	script.Parent.Parent.Join.Visible = false -- This makes the host's lobby frame disappear, as the party no longer exists.
end)

SERVER SIDE SCRIPT TO DELETE THE PARTY
This works the same as creating the party, but it reverses the process.

game.ReplicatedStorage.DeleteParty.OnServerEvent:Connect(function(players, username)-- "username" is the name of the person who created and is now deleting the party.
	game.ReplicatedStorage.DeleteParty:FireAllClients(players, username)

end)

CLIENT SIDE SCRIPT THAT RUNS WHEN ALL CLIENTS ARE FIRED FROM THE SERVER SCRIPT

game.ReplicatedStorage.DeleteParty.OnClientEvent:Connect(function(username)
	print(">> Success")
	print(">>", username, "deleted a party... :(")
	if script.Parent:FindFirstChild(tostring(username)) then -- Checks whether a frame with the name of the party creator actually exists.
		script.Parent:FindFirstChild(tostring(username)):Destroy() -- Deletes it.
	end
end)

Now, in order for a player to join a party.

script.Parent.MouseButton1Up:Connect(function()
	if script.Parent.Parent.count.Text == "1/2" then -- This checks if the party is full. When a player joins a party, the text will change to "2/2", which renders this button virtually useless.
		local tapped = script.Parent.Parent.Name -- This is the party host's name, which we set when creating the party.
		local localplr = game.Players.LocalPlayer.Name	
	
		game.ReplicatedStorage.JoinParty:FireServer(tapped, localplr) -- This will fire the server, so we can make it appear that a player has joined the party for both client and host.

		script.Parent.Parent.Parent.Parent.Parent.Join.Join.Visible = false -- In the frame "Join" (Basically the local party frame), there is a button that allows you to join the game. This disables that button so that only the host can initiate the joining of the game.
		script.Parent.Parent.Parent.Parent.Parent.Join.Visible = true
		script.Parent.Parent.Parent.Parent.Parent.CreateParty.Visible = false -- This makes the create button invisible, so the player who is in the party cannot create a separate party. This will just make no sense. Similar thing going on with the next line. 
		script.Parent.Parent.Parent.Parent.Parent.Delete.Visible = false
	else
		print("Party is full. Try again later.")
	end
	
end)

And the server side script:

game.ReplicatedStorage.JoinParty.OnServerEvent:Connect(function(tapped, localplr)
	local s = pcall(function() 
	print(localplr)
	game.Players[tostring(tapped)].PlayerGui.ScreenGui.Main.Join.Table.Player2.user.Text = tostring(localplr) -- This is a text box which displays the username of the local player for the party host.

	game.Players[tostring(tapped)].PlayerGui.ScreenGui.Main.Join.PlayerCount.Text = "2/2" -- This is a player counter inside of the local party frame.

	game.Players[tostring(localplr)].PlayerGui.ScreenGui.Main.Join.PlayerCount.Text = "2/2"-- This is a player counter inside of the local party frame.

	game.Players[tostring(localplr)].PlayerGui.ScreenGui.Main.Join.Table.Player2.user.Text = tostring(tapped) -- This is a text box which displays the username of the party host for the local player.

	game.Players[tostring(localplr)].PlayerGui.ScreenGui.Main.Join.Visible = true

	game.ReplicatedStorage.JoinParty:FireAllClients(tapped) -- This fires a script that makes the frame that is in the party list have a textbox that displays 2/2, aka indicating that the party is full.
	end)
end)

Now leaving the party.

This is the same for joining the party, but it just reverses everything.

Client side:

script.Parent.Parent.Parent.Parent.Parent.Join.Leave.MouseButton1Up:Connect(function()
	local tapped = script.Parent.Parent.Name
	local localplr = game.Players.LocalPlayer.Name
	print(tapped, localplr)
	game.ReplicatedStorage.LeaveParty:FireServer(tapped, localplr)
	script.Parent.Parent.Parent.Parent.Parent.Join.Join.Visible = true
	script.Parent.Parent.Parent.Parent.Parent.Join.Visible = true
	script.Parent.Parent.Parent.Parent.Parent.CreateParty.Visible = true
	script.Parent.Parent.Parent.Parent.Parent.Delete.Visible = true
end)

Server side:


game.ReplicatedStorage.LeaveParty.OnServerEvent:Connect(function(tapped, localplr)
	
local s = pcall(function()
	    game.Players[tostring(tapped)].PlayerGui.ScreenGui.Main.Join.Table.Player2.user.Text = "Empty"
		game.Players[tostring(localplr)].PlayerGui.ScreenGui.Main.Join.Table.Player2.user.Text = "Empty"
		game.Players[tostring(tapped)].PlayerGui.ScreenGui.Main.Join.PlayerCount.Text = "1/2"
		game.Players[tostring(localplr)].PlayerGui.ScreenGui.Main.Join.PlayerCount.Text = "1/2"
		game.Players[tostring(localplr)].PlayerGui.ScreenGui.Main.Join.Visible = false
		game.ReplicatedStorage.LeaveParty:FireAllClients(tapped) -- This fires a script that makes the frame that is in the party list have a textbox that displays 1/2

end)

Whilst I’m at it, I’ll throw in the join game button for the party :slight_smile:

This requires two scripts in one button, and a remote event.

Local script:

script.Parent.MouseButton1Down:Connect(function(player)
	local player1 = script.Parent.Parent.Parent.Parent.Parent.Parent.Name
	local player2 = script.Parent.Parent.Table.Player2.user.Text
	print(player1)
	print(player2)
	script.Parent.RemoteEvent:FireServer(player1, player2)
end)

Server script:

local ts = game:GetService("TeleportService")
local placeid = _game_id_
local plr1
local plr2
script.Parent.RemoteEvent.OnServerEvent:Connect(function(player, player1, player2)
	plr1 = tostring(player1)
	plr2 = tostring(player2)
end)
local reservedserver

local s, e = pcall(function()
	reservedserver = ts:ReserveServer(placeid)
end)

script.Parent.MouseButton1Up:Connect(function()
	local users
	users = {	
		game.Players[plr1],
		game.Players[plr2]
	} 		

    ts:TeleportToPrivateServer(placeid, reservedserver, users)

end)

image
The remote events^^^

It’s taken me a while to write this, so I hope it actually helps a bit. I’ve only been working on this for the best part of a week, so it’s not the best. If you’d like, I can release a model.

8 Likes

Jesus this looks complicated but big thanks to you! Now I know what kind of scripting I need to make a lobby. Thanks again.

1 Like

Just a quick request. Could you please send me your explorer tab with all the scripts, remote events in their places and names?

Ill make a model of the current menu I have but I think there is some bug. I looked it up and it might be to do with roblox testing a new dev console, but I’m not sure. I’ll DM you.

2 Likes

there is a lot of things that go into making a lobby system

first you will need to secure it from exploiters by doing a lot of checks.

  • use remote functions a lot to be able to send back to the client a response
  • check if they already have a party and if they do ignore it
  • make sure they can only delete their party and not others
  • have a secure way of joining public and private server (public by an id, private by an invite code only given when invited [this will make it impossible for an exploiter to spoof a remote and steal an invite code])
  • make sure people cant join multiple parties (seen this a lot, where exploiters would spam join all parties)
  • add a kick system so just in case someone you dont want in there is there you can kick them. make sure when kicked they cant rejoin
  • handle all the parties on the server and request (requesting by remote functions) creation, deletion, joining, leaving, etc on the client

again a lot of stuff goes into this
it took me 4 days to get a functional and secure system