Timer only appearing one player at a time

I’ve got a script to show a countdown timer for all players. However, this only does it one player at a time, not all at once. All help appreciated

commands.cd = function(sender, arguments)
	local countdown = tonumber(arguments[1])
	
	for ea, child in ipairs(game.Players:GetPlayers()) do
		local announcement = game.ServerStorage.Countdown:Clone()
		announcement.Header.Description.Text = sender.Name.."'s Countdown"
		announcement.Parent = child.PlayerGui.Countdowns.Holder
		
		for i = countdown, 0, -1 do
			announcement.Announcement.Text = tostring(i)
			wait(1)
		end
		
		announcement:Destroy()
	end
end

The reason is that you have a loop going through each player, and then on each player creating and counting down a timer. The issue right now is that the code won’t move on to the next player until the code for the first player (the timer) is done.

Wrapping it in a coroutine moves that code to another thread, in essence meaning it will carry it out while moving on to the next player.

Also, consider changing wait() to task.wait(). More accurate version of it.

2 Likes

Does this change anything?

commands.cd = function(sender, arguments)
	local countdown = tonumber(arguments[1])
	
	for ea, child in ipairs(game.Players:GetPlayers()) do
		local announcement = game.ServerStorage.Countdown:Clone()
		announcement.Header.Description.Text = sender.Name.."'s Countdown"
		announcement.Parent = child.PlayerGui.Countdowns.Holder
		
		spawn(function()
          for i = countdown, 0, -1 do
			 announcement.Announcement.Text = tostring(i)
			 task.wait(1)
		  end
        end)
		
		announcement:Destroy()
	end
end

I prefer to use spawn over coroutines, but it’s up to you.
[The reason to what happend here is mentioned by @ifkpop ]

1 Like

image

The issue is the final line of code, announcement:Destroy(). That should be moved inside the coroutine / spawned func. Right now you destroy the announcement object while the function is attempting to manipulate it.

commands.cd = function(sender, arguments)
	local countdown = tonumber(arguments[1])
	
	for _, child in ipairs(game.Players:GetPlayers()) do
		coroutine.wrap(function()
			local announcement = game.ServerStorage.Countdown:Clone()
			announcement.Header.Description.Text = sender.Name.."'s Countdown"
			announcement.Parent = child.PlayerGui.Countdowns.Holder
		
			for i = countdown, 0, -1 do
				announcement.Announcement.Text = tostring(i)
				task.wait(1)
			end		
			announcement:Destroy()
		end)()
	end
end

In this code I also moved all of it inside a coroutine, since there is no downside to doing so. If coroutine.wrap() isn’t working as intended, use spawn() as @Valkyrop mentioned.

EDIT: Looks like you are not using the key in the for loop, so I replaced the variable name ea to _, since a _ indicates that it will not be used.