Still have questions? Join our Discord server and get real time help.
0

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

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
somegui:Destroy()
print("Destroyed first GUI in PlayerGui")
end
end
end
else
for i, v in pairs(game.Players:GetChildren()) do
local player = v:FindFirstChild("PlayerGui")
local screengui = Instance.new('ScreenGui', player)
screengui.Name = "playercheckgui"
---- Create textLabel
local imageLabel = Instance.new('ImageLabel', player.playercheckgui)
imageLabel.Position = UDim2.new(0.3, 0, 0, 0)
imageLabel.Size = UDim2.new(0.35, 0, 0.15, 0)
imageLabel.BackgroundTransparency = 1
end
end


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

0
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
end
end)

0
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
0
Infinite loops are bad. You should consider using Event callbacks. Link150 1342 — 3y
0
@Link150 ...apparently I am not supposed to be using playeradded in a localscript https://forum.roblox.com/Forum/ShowPost.aspx?PostID=190238127 strange. Idk though Seyfert 90 — 3y