Help with Script Optimizations

Hello, I’ve recently finished this queue script although it has gotten long. Any optimizations or help is appreciated.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TeleportService = game:GetService("TeleportService")
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")

local PlaceId = "8772951933"

local LeaveEvent = ReplicatedStorage.Events:FindFirstChild("LeaveEvent")
local TransitionEvent = ReplicatedStorage.Events:FindFirstChild("TransitionEvent")
local List = {}

local SurfaceGui = script.Parent.SurfaceGui
local PlayersDisplay = SurfaceGui.Displays:FindFirstChild("Players")
local TimerDisplay = SurfaceGui.Displays:FindFirstChild("Timer")
local StatusDisplay = SurfaceGui.Displays:FindFirstChild("Status")

local Timer
local Teleporting = false
local Debounce = false

local SpawnLocation = game.Workspace:FindFirstChild("SpawnLocation")
local Gate = script.Parent

local function UpdateGui()
	PlayersDisplay.Text = #List
end

local function RemoveFromList(Character)
	for i=1,#List do
		if List[i] == Character.Name then

			table.remove(List, i)
			UpdateGui()

		end
	end
end

local function TeleportPlayers()
	if #List > 0 then

		StatusDisplay.Text = "Leaving"

		local PlayersToTeleport = {}
		local TeleportTime = 0
		
		for i=1,#List do
			if Players:FindFirstChild(List[i]) then
				
				table.insert(PlayersToTeleport, Players:FindFirstChild(List[i]))
				TransitionEvent:FireClient(Players:FindFirstChild(List[i]))
			else
				table.remove(List,i)
				
			end
		end 
		
		local Code = TeleportService:ReserveServer(PlaceId)
		
		Teleporting = true
		TeleportService:TeleportToPrivateServer(PlaceId,Code,PlayersToTeleport)
		
		repeat wait() until #List <= 0
		StatusDisplay.Text = "Ready"
		Teleporting = false

	end
end

Gate.Touched:Connect(function(Hit)
	if Debounce then return end

	Debounce = true

	local Character = Hit.Parent
	local Player = game.Players:FindFirstChild(Character.Name)
	local AlreadyExists = false
	
	if Hit.Parent:findFirstChild("Humanoid") then
		if Teleporting == false then

			for i=1,#List do
				if List[i] == Character.Name then
					AlreadyExists = true

				end
			end

			if AlreadyExists == false then
				if #List < 1 then

					table.insert(List,Character.Name)
					UpdateGui()
					LeaveEvent:FireClient(Player)

				end

				Player.CharacterRemoving:Connect(function(Character)
					RemoveFromList(Character)

				end)
			end
		end
	end
	wait(1)
	Debounce = false
end)

LeaveEvent.OnServerEvent:Connect(function(Player)
	if Player.Character then
		RemoveFromList(Player.Character)
	end
end)

while wait() do
	Timer = 20
	for i=1,Timer do

		Timer = Timer - 1
		TimerDisplay.Text = Timer
		wait(1)

	end
	TeleportPlayers()
end
1 Like

Oh god Thats alot guess I’ll copy all of it :cold_sweat:

1 Like
while true do -- use 'true' instead of 'wait()' because wait() takes up time and it's bad practice. it could break if you use 'wait()' because roblox could stop having wait return anything at any moment. unlikely but still.
	Timer = 20
	
	for i=1, Timer do
		Timer -= 1 -- neat little trick. works for all math operations.
		TimerDisplay.Text = tostring(Timer)
		task.wait(1)
	end
	
	TeleportPlayers()
end
1 Like

I believe if Timer equals 1 then this creates a stack overflow error. Probably use task.wait() instead though.

Whoops! My bad, I didn’t see what the code was trying to do. You’re correct.

1 Like

Nope it won’t. Since the timer is being set to 20 every 20 seconds (when the loop ends and tps all players) it shouldn’t cause any overflow.

Good point, I edited my original reply. Thanks.

2 Likes

I recommend to structure the List variable differently. It is faster to define an item as List[Character.name] = true. That is because you can now index the list with a character’s name, rather than go through the entire list and finding whether the character’s name is in there.

For example, you could rewrite RemoveFromList as

local function RemoveFromList(CharacterName)
        List[CharacterName] = nil 
        UpdateGui()
end
1 Like

You don’t even need to do that. Roblox has it’s own built-in functions that handle that perfectly. table.find and table.remove.

local found = table.find(List,Character.Name)
if found then 
  table.remove(List,found)
  UpdateGui()
end
1 Like

That is an option, but it is not as fast as my approach. The reason is that table.find uses a linear search algorithm.

Within the given array-like table haystack , find the first occurrence of value needle , starting from index init or the beginning if not provided. If the value is not found, nil is returned.
A linear search algorithm is performed.

My approach only uses indexing, which is faster than searching and indexing.