Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Why is my GUI not updating for some players?

if game.Players.NumPlayers >= 3 then
	for i = 30,0,-1 do
	script.Parent.Text = "Intermission "..i
	wait(1)
	end	
	
    for i = 60, 1, -1 do
        script.Parent.Text = "Time Left: 2:" .. i
        wait(1)
end
for i = 60, 1, -1 do
        script.Parent.Text = "Time Left: 1:" .. i
        wait(1)
    end
for i = 60, 1, -1 do
        script.Parent.Text = "Time Left: :" .. i
        wait(1)
end

elseif game.Players.NumPlayers < 3 then 
	script.Parent.Text = "Waiting for more players..."
end

Please help! It keeps saying "Waiting for more players..." for some players while there is a timer going on.

2 answers

✓ Accepted answer

This is an example of code where you REALLY need to tab every perfectly or else it will be confusing which end goes with which code block. So, let's do that.

if game.Players.NumPlayers >= 3 then
	
	for i = 30,0,-1 do
		script.Parent.Text = "Intermission "..i
		wait(1)
	end 
	
	for i = 60, 1, -1 do
		script.Parent.Text = "Time Left: 2:" .. i
		wait(1)
	end
	
	for i = 60, 1, -1 do
		script.Parent.Text = "Time Left: 1:" .. i
		wait(1)
	end
	
	for i = 60, 1, -1 do
		script.Parent.Text = "Time Left: :" .. i
		 wait(1)
	end

elseif game.Players.NumPlayers < 3 then 
	script.Parent.Text = "Waiting for more players..."
end

Now that it's readable, we can begin to debug.

You problem is that if statements only run once. The condition is either true or false. If it is true, then everything's fine and we proceed with the code. If it's false, we don't. It does not matter if the condition is true or false later, because the if statement will not run later.

It's kind of like if you do your homework or not. If you don't do your homework, you will get a bad grade. Your teacher doesn't give a crap if you do it the next day, because you didn't do it the time it was supposed to be done! It's the same in Lua. Who cares if this condition is true later? The computer essentially thinks. "It's not true now, and unless I'm told to check again later, I don't care what happens to it."

But this is not the only problem. Since a GUI will clone itself into a player's PlayerGui each time they respawn, if a player resets in the middle of the timer, the timer will start over. Therefore I recommend controlling all GUIs with a single string value in workspace, then using a server script to control that string value.

Server Script inside the string value in workspace:

while true do --While loop so it will continue to check if there's enough players
	if game.Players.NumPlayers >= 3 then
	
		for i = 30,0,-1 do
			script.Parent.Value = "Intermission "..i
			wait(1)
		end 
		
		for i = 60, 1, -1 do
			script.Parent.Value = "Time Left: 2:" .. i
			wait(1)
		end
		
		for i = 60, 1, -1 do
			script.Parent.Value = "Time Left: 1:" .. i
			wait(1)
		end
		
		for i = 60, 1, -1 do
			script.Parent.Value = "Time Left: :" .. i
			 wait(1)
		end

		script.Parent.Value = "Countdown's over" --For testing purposes.
	
	elseif game.Players.NumPlayers < 3 then 
		script.Parent.Text = "Waiting for more players..."
		wait() --So the game doesn't crash
	end
end

Local Script inside the GUI

script.Parent.Text = game.Workspace.StringValue.Value

game.Workspace.StringValue.Changed:connect(function()
	script.Parent.Text = game.Workspace.StringValue.Value
end)

There's a tutorial about pseudo chat guis. This is obviously not what you're looking for but it has an updating function that shows every player the most recent chats. I'll quickly show some code:

function UpdateGui(text)
	local startertext = game.StarterGui.PATH TO GUI --Change "PATH TO GUI" to the path where your GUI text object is located in StarterGui.
	startertext.Text = text --Sets startertext's text property to the text argument of the function.
	for i,players in pairs(game.Players:GetPlayers()) do
		local playertext = players.PlayerGui.PATH TO GUI --Change "PATH TO GUI" to the same path as the startertext variable, treat the PlayerGui as the StarterGui and continue from there.
		playertext.Text = text --Sets playertext's text property to the text argument of the function.
	end
end

This basically sets the text in the text object in all the player's PlayerGuis and the StarterGui. (In case a player dies or joins)

You may want to use a while loop too, unless you certainly know why you wouldn't need one. For now, we'll just stick with your original code.

If we were to use the above function in your code, it'd look something like this:

function UpdateGui(text)
	local startertext = game.StarterGui.PATH TO GUI --Change "PATH TO GUI" to the path where your GUI text object is located in StarterGui.
	startertext.Text = text --Sets startertext's text property to the text argument of the function.
	for i,players in pairs(game.Players:GetPlayers()) do
		local playertext = players.PlayerGui.PATH TO GUI --Change "PATH TO GUI" to the same path as the startertext variable, treat the PlayerGui as the StarterGui and continue from there.
		playertext.Text = text --Sets playertext's text property to the text argument of the function.
	end
end

if game.Players.NumPlayers >= 3 then
	for i = 30,0,-1 do
		UpdateGui("Intermission "..i) --This line of code runs the code inside the UpdateGui function, with the text argument being the text you want to show the players. This is the same for each of the calls to the UpdateGui function below. 
		wait(1)
	end
	for i = 60, 1, -1 do
		UpdateGui(script.Parent.Text = "Time Left: 2:" .. i)
		wait(1)
	end
	for i = 60, 1, -1 do
		UpdateGui(script.Parent.Text = "Time Left: 1:" .. i)
		wait(1)
	end
	for i = 60, 1, -1 do
		UpdateGui(script.Parent.Text = "Time Left: :" .. i)
		wait(1)
	end
elseif game.Players.NumPlayers < 3 then 
	UpdateGui(script.Parent.Text = "Waiting for more players...")
end

Hope this helps. Sorry if it is unclear, it is quite late here and I'm pretty tired.

This discussion is preserved as it was. New answers, comments, and votes are closed.