How-To Reduce High Latency in My Lobby Game?

I basically have a lobby that teleports players to another game. The max amount of spots the whole game can take is about 28. The max players for the game is 50. I will provide some of the code that I think is causing the high latency.

local function Check()
        if TwosValue then
            for _, v in pairs(Team1Folder:GetChildren()) do
                if v.Value ~= "" then
                    FilledNumber = FilledNumber + 1
                end
            end
            for _, v in pairs(Team2Folder:GetChildren()) do
                if v.Value ~= "" then
                    FilledNumber = FilledNumber + 1
                end
            end
            if FilledNumber == 4 then
                return true
            end
        else
            for _, v in pairs(Team1Folder:GetChildren()) do
                if v.Value ~= "" then
                    FilledNumber = FilledNumber + 1
                end
            end
            for _, v in pairs(Team2Folder:GetChildren()) do
                if v.Value ~= "" then
                    FilledNumber = FilledNumber + 1
                end
            end
            if FilledNumber == 2 then
                return true
            end
        end
    end

This local function is run every time a player hops on a spot. The FilledNumber is changed depending on the requirement for a certain amount of pads on the spot, in this case, 2.

Visual Representation

This for loop runs after someone hops on the spot to check if all the spots have been taken. I also have StringValues that change whether or not a Player is on that pad.

I have gotten cases where ping has spiked up to 1k or even 2k. I was wondering if there was a more effective way of handling all of this.

I also have it where it’s all changed in a module making it less laggy as well. Everything runs through different modules depending on what’s being done. For instance, I have a module that runs every time the pad is touched in order to add that player into the game. I also have a module where I start the game if the FilledValue is true aka when all the spots are taken, that’s when I know I can start the game.

for _, FilledValue in pairs(FilledValues) do
    FilledValue.Changed:Connect(function()
        if FilledValue.Value == true then
            self:FireEvent(CHECK_AMOUNT, FilledValue)
        end
    end)
end

I am using CollectionService here to check if any of the FilledValues have changed to true to see if I can start the game or not. I have a for loop in this module as well that fires to the clients that are on the spots.

 for i = 10, 0, -1 do --COUNTDOWN
            for _, v in pairs(Team1Folder:GetChildren()) do
                local Player = PlayerService:FindFirstChild(v.Value)
                if Player then
                    self:FireClientEvent(DISPLAY_PREP, Player, i)
                end
            end
            for _, v in pairs(Team2Folder:GetChildren()) do
                local Player = PlayerService:FindFirstChild(v.Value)
                if Player then
                    self:FireClientEvent(DISPLAY_PREP, Player, i)
                end
            end
            wait(1)
        end
    end

Basically it will say Game starts in “i” seconds.

I have many for loops that I think are creating the high latency. I’m thinking of maybe adding a second of wait time to maybe reduce that latency because I don’t have the loop waiting at all. Anyways, I have lots of code for you guys to help me on. If there’s any other questions, please let me know. Thanks :slight_smile:

-LukeGabrieI

I tried my absolute best to understand everything you’re trying to do. It does seem as if the for loops may be causing the latency. My first question to you is, do you have a debounce variable for every time a player steps on one of those buttons?

Yes I do. I also have been receiving feedback from people that whenever people hop off the spot, using the Exit GUI, it causes high latency when restarting the spots.

for _, v in pairs(Team1Folder:GetChildren()) do
            local Player = PlayerService:FindFirstChild(v.Value)
            if Player then
                self:FireClientEvent(DISPLAY_PREP, Player, nil)
            end
        end
        for _, v in pairs(Team2Folder:GetChildren()) do
            local Player = PlayerService:FindFirstChild(v.Value)
            if Player then
                self:FireClientEvent(DISPLAY_PREP, Player, nil)
            end
        end
        --Remove All Players from Spot
        for _, v in pairs(Team1Folder:GetChildren()) do
            local Player = PlayerService:FindFirstChild(v.Value)
            if Player then
                --Change Player's Team
                Player.Team = game.Teams.NoTeam
                --Reset Player's Pad Data
                local PadData = Player:WaitForChild("PadData")
                local CourtName = PadData:WaitForChild("CourtName")
                local PadName = PadData:WaitForChild("PadName")
                CourtName.Value = "COURT_0"
                v.Value = "RESTARTING"
                PadName.Value = 0
                --Teleport Player
                local Character = Player.Character
                if Character then
                    local Humanoid = Character:WaitForChild("Humanoid")
                    Character:MoveTo(TP_Part.Position, TP_Part)
                    Humanoid.WalkSpeed = 16
                end
            end
        end
        for _, v in pairs(Team2Folder:GetChildren()) do
            local Player = PlayerService:FindFirstChild(v.Value)
            if Player then
                --Change Player's Team
                Player.Team = game.Teams.NoTeam
                --Reset Player's Pad Data
                local PadData = Player:WaitForChild("PadData")
                local CourtName = PadData:WaitForChild("CourtName")
                local PadName = PadData:WaitForChild("PadName")
                CourtName.Value = "COURT_0"
                v.Value = "RESTARTING"
                PadName.Value = 0
                --Teleport Player
                local Character = Player.Character
                if Character then
                    local Humanoid = Character:WaitForChild("Humanoid")
                    Character:MoveTo(TP_Part.Position, TP_Part)
                    Humanoid.WalkSpeed = 16
                end
            end
        end

This happens if someone during the Game is starting in “i” seconds leaves right before they are teleported to the lobby.

--All Spots Taken
        if CheckNumber == 4 then
            wait(2)
            PrepareGame()
            --Players Stayed at Spots
            if not Restart() then --Restart() checks if any of the values have become vacant.
                StartGame()
                repeat wait(5) until Restart()
                wait(10)
                ResetGame()
            --Players Left Spots
            else
                RestartGame()
                wait(20)
                ResetGame()
            end
        end

 --Check if People left
    local function Restart()
        for _, v in pairs(Team1Folder:GetChildren()) do
            if v.Value == "" then
                return true
            end
        end
        for _, v in pairs(Team2Folder:GetChildren()) do
            if v.Value == "" then
                return true
            end
        end
    end

Sorry for the large tabs, I’m using VS Code to script.

1 Like

Thanks for the descriptive replies!

It seems you’re using GetChildren() quite a lot. Would it be possible for you to simply put GetChildren() on the end of the Team1Folder and Team2Folder variables outside of these functions? I’ve found predeclaring the children of an object helps tremendously in reducing latency.

However, it also seems like these variables are subject to change given the players in the game leaving and joining if I’m not mistaken. If this is the case, could you add PlayerAdded and PlayerRemoved functions that update these variables as they are needed?

--Remove Player Name From Pad
        for _, v in pairs(Team1Folder:GetChildren()) do
            if Player.Name == v.Value then
                --Revert Pad Color
                for _, v_2 in pairs(Team1BigPads:GetChildren()) do
                    if tonumber(v_2.Name) == PadName.Value then
                        v_2.BrickColor = BrickColor.new("Really red")
                    end
                end
                --Reset Player's Pad Data
                CourtName.Value = "COURT_0"
                v.Value = ""
                PadName.Value = 0
            end
        end
        for _, v in pairs(Team2Folder:GetChildren()) do
            if Player.Name == v.Value then
                --Revert Pad Color
                for _, v_2 in pairs(Team2BigPads:GetChildren()) do
                    if tonumber(v_2.Name) == PadName.Value then
                        v_2.BrickColor = BrickColor.new("Really blue")
                    end
                end
                --Reset Player's Pad Data
                CourtName.Value = "COURT_0"
                v.Value = ""
                PadName.Value = 0
            end
        end

I just joined a lobby a couple minutes ago, and this was the issue that was causing all the lag. Maybe I could just define the variables instead of getting them, like

local Team1BigPadsPadName1 = Team1BigPads["1"] --long but it could reduce lag lol.

But yes, I do have the PlayerRemoving Event connected to this, but what’s causing the lag is when they click “Exit”.

Exit Visual

PlayerService.PlayerRemoving:Connect(function(Player)
    self:FireEvent(PLAYER_LEFT, Player)
end)

Could you do something like this?

for _, v in pairs(Team1Folder:GetChildren()) do
            if Player.Name == v.Value then
                --Revert Pad Color
                Team1BigPads[PadName.Value].BrickColor = BrickColor.new("Really red")
                --Reset Player's Pad Data
                CourtName.Value = "COURT_0"
                v.Value = ""
                PadName.Value = 0
            end
        end

Avoiding nested GetChildren() functions in for loops could really help

Yeah that would definitely be a good thing to do. Is there anything else that I should optimize?

You could go even further!

for _, v in pairs(Team1Folder:GetChildren()) do
            if Player.Name == v.Value then
                --Revert Pad Color
                Team1BigPads[PadName.Value].BrickColor = BrickColor.new("Really red")
                --Reset Player's Pad Data
                CourtName.Value = "COURT_0"
                v.Value = ""
                PadName.Value = 0

                break --To avoid any further unnecessary loops
            end
        end

Or better yet, you could write it to where the objects in the Team1Folder and Team2Folder variables have the same name as the players. It would make it to where you could instantly refer to it like this, with no need for a for loop:

    local v = Team1Folder[Player.Name]
    Team1BigPads[PadName.Value].BrickColor = BrickColor.new("Really red")
    CourtName.Value = "COURT_0"
    v.Value = ""
    PadName.Value = 0

My best advice for you is to try and optimize your script as much as possible. Look for any long loops or constant GetChildrens(). I remember once I was trying to make something similar to this and getting rid of a lot of GetChildrens() and for loops helped tremendously. Good luck!