Still have questions? Join our Discord server and get real time help.
Log in to vote

How can I tell while true do to run a command only once for the loop?

Asked by
Seyfert 90
3 years ago
Edited 3 years ago

Hello there guys, I have a script where I want a GUI to display saying "Not enough players" if there aren't a certain amount of players in the game, while also removing the GUI if enough players are met. The script is in ServerScriptService, and with FilteringEnabled set to on, scripts in ServerScriptService are not able to read PlayerGuis. So I have to use a for i, v to clone a GUI into the player. The problem with this is that with the while true do running, it is constantly cloning GUIs into the player and the game becomes INCREDIBLY laggy.

How can I make it so while true do only runs ONCE and then restarts the loop? Do I include a break somewhere?

while true do wait()
    if game.Players.NumPlayers >= MinPlayers  then      
        for i, v in pairs(game.Players:GetChildren()) do
        local playergui = v:FindFirstChild("PlayerGui")
            if playergui then
            local somegui = playergui:FindFirstChild("playercheckgui")
                if somegui then
                print("Destroyed first GUI in PlayerGui")   
    for i, v in pairs(game.Players:GetChildren()) do
            local player = v:FindFirstChild("PlayerGui")
            local screengui ='ScreenGui', player) 
            screengui.Name = "playercheckgui"
            ---- Create textLabel
            local imageLabel ='ImageLabel', player.playercheckgui)
            imageLabel.Position =, 0, 0, 0)
            imageLabel.Size =, 0, 0.15, 0)
            imageLabel.BackgroundTransparency = 1

The other alternative is to place this script in Workspace and call it a day? But that is bad security wise, yes?

1 answer

Log in to vote
Answered by
Link150 1342 Badge of Merit Moderation Voter Administrator
3 years ago
Edited 3 years ago

The correct solution is to not use an infinite loop at all. Instead, connect a callback function to the Players.PlayerAdded event. That callback will be fired each time a new player joins.

So, each time a player joins, check if there are enough players; If there are, hide the gui for all players by disabling its Visible property; If not, show the gui by enabling its Visible property.

However, as you mentioned, gui elements located in StarterGui are cloned over to PlayerGui by none other than the client. If network filtering is enabled then the server will refuse to acknowledge the existance of the cloned gui elements, meaning they can only be accessed from clientside scripts.

But this isn't a problem for us, as gui elements should be manipulated from clientside anyway. This is assuming the original gui element is located in StarterGui:

local players = game:GetService("Players")

local player = players.LocalPlayer
local playerGui = player:FindFirstChild("PlayerGui")

local minPlayers = 8

        We make sure the gui exists, as exploiters can edit the DataModel of
        their client as they wish; which may break clientside scripts, if not
        written properly.

    if playerGui:FindFirstChild("ScreenGui") and
    playerGui.ScreenGui:FindFirstChild("Frame") then
        frame.Visible = players.NumPlayers >= minPlayers
Very interesting how you manipulated the GUI from the clientside way instead of the server side way I was doing. I was not aware it cold be done like that, very neat indeed, Thanks! For you or anyone wondering what I did to mitigate the issue before I saw your reply, I kept the while true do loop and added a debounce past the "else", something like this if not debounce then debounce = true and Seyfert 90 — 3y
Infinite loops are bad. You should consider using Event callbacks. Link150 1342 — 3y
@Link150 ...apparently I am not supposed to be using playeradded in a localscript strange. Idk though Seyfert 90 — 3y

Answer this question