Timer Not In Sync For All Clients

I wrote a timer script on a local script a while ago and if a player joined late then the timer would start from the beginning for that player and not display the same as everyone else. To fix this I’ve tried to make a server sided timer. Still not in sync. Here’s a script I have, should I create a remote event that communicates to the client and updates the GUI all the time?

ServerScript located in ServerScriptService:

game.Players.PlayerAdded:Connect(function(plr)
	
	-- Variables
	local playerGui = plr:WaitForChild("PlayerGui")
	local gui = playerGui:WaitForChild("TimerGUI")
	
	local timerLabel = gui.TimerLabel
	local underText = gui.Undertext
	
	local playerCount = game.ReplicatedStorage.Players.Value
	
	game.ReplicatedFirst:RemoveDefaultLoadingScreen()
	timerLabel.Text = "Loading..."
	underText.Text = "Loading..."
	
	-- Timer Function
	local function timer(minutes, seconds, untilText)
		repeat
			wait(1)
			underText.Text = untilText
			if seconds <= 0 then
				minutes = minutes - 1
				seconds = 59
				timerLabel.Text = minutes..":"..seconds.."s"
			else
				seconds = seconds - 1
				timerLabel.Text = minutes..":"..seconds.."s"
			end
			
			if seconds <= 9 then
				timerLabel.Text = minutes..":0"..seconds.."s"
			else
				timerLabel.Text = minutes..':'..seconds.."s"
			end
			
			if minutes == 0 and seconds == 5 then 
				game.ReplicatedStorage.Sounds.Countdown:Play()
			end
		until minutes == 0 and seconds == 0
	end
	
	-- Player Added
	plr.Character.Humanoid.WalkSpeed = 0
	timerLabel.Text = "Waiting for players"
	underText.Text = "please wait"
	
	repeat wait() until playerCount >= 1
	
	timer(0, 16, "until the round begins")
	plr.Character.Humanoid.WalkSpeed = 20
	game.ReplicatedStorage.Events.StartStats:FireAllClients()
	
	-- Main Timer
	timer(4, 1, "until the gate opens")
	
	-- Choose Gate Function (JUST IGNORE THIS)
	local gates = game.Workspace.Gates
	local gate = math.random(1, 7)
	local pickedGate = gates["Gate"..gate]
	
	local plane = game.ServerStorage.Planes["Gate"..gate.."Plane"]
	plane.Parent = game.workspace.GamePlay
	
	pickedGate.Open.Value = true
	pickedGate.GateSign.SignPart.SurfaceGui.TextLabel.TextColor3 = Color3.new(0, 250, 0)
	
	for index, child in pairs(pickedGate.Door:GetChildren()) do
		if child.Name == "DoorHandle1" or "DoorHandl2" or "MiddleFrame" or "DoorPart1" or "DoorPart2" then
			child.Parent = game.ServerStorage
		end
	end
	
	timerLabel.Text = "Gate "..gate.." was chosen"
	underText.Text = ""
	
	timer(1, 1, "to get to gate "..gate)
	game.ReplicatedStorage.Events.RoundEvents.EndRoundClient:FireAllClients()
	
	-- Countdown Sound Function
	local db = true
	while wait(0.1) do
		if timerLabel.Text == "00:05s" then
			if db == true then
				db = false
				game.ReplicatedStorage.Sounds.Countdown:Play()
				repeat wait(1) until game.ReplicatedStorage.Sounds.Countdown.Playing == false
				db = true
			end
		end
	end
end)

This is what the GUI looks like:
image
image
Feel free to ask as many questions as you want in the comments :slightly_smiling_face:

1 Like

its because they have different join times if you do it on a single value then it would work also you are making a big mistake abbreviating the time

here is a function to make it simple

local function ConvertTime(input)
    return ("%02i:%02i"):format(s/60%60, s%60)
end

print(600) -- 10:00
2 Likes

Instead of making a new timer every time a player joins, just use Remote Events, have a server script with a main timer, and just fire the time value to the players every second using FireAllClients(). No need for game.Players.PlayerAdded and all that.

Make sure that:

  1. You’re keeping the values either in ServerStorage or in the script itself.
  2. You’re not giving each player a timer value, or doing something everytime a player is added.
  3. You use FireAllClients() or something similar to pass the same value each second to all players

Let me know if you have any questions.

2 Likes

Thank you, I’ve done just that! I was considering doing that before I published this post but I assumed it wouldn’t of worked cause I thought there must have been a limit on how often you can send remote events, but clearly not. Thanks for your help, I have a perfectly in sync timer now!

1 Like