Timer counting down 2x as fast

I currently have a timer system for each induvial player. The timer system involves a GUI on the players screen.

  1. What do you want to achieve? Keep it simple and clear!

I am trying to make it where if the local player dies, their timer will reset.

  1. What is the issue? Include screenshots / videos if possible!

Whenever the player dies, their timer does reset but it counts down 2x as fast. It should only count down by 1 every second.

Here is a video of the issue I am having:

And here is the code that I have which is a local script in StarterPlayerScripts:

local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("OneMinuteTimer")
local remoteEvent2 = ReplicatedStorage:WaitForChild("StopTimer")
local Checkpoint = workspace:WaitForChild("Checkpoints")

local lastCheckpointTouched = nil
local heart = "rbxassetid://13841443245"
local skull = "rbxassetid://13841410348"

local clonedgui = Player.PlayerGui:WaitForChild("Timer")
local timerTime = 2 * 60 
local Started = false
local mode = false
local running = false

local red = Color3.fromRGB(231, 37, 37)
local black = Color3.fromRGB(0,0,0)
local white = Color3.fromRGB(255, 255, 255)
local green1 = Color3.fromRGB(80, 207, 61)

local timersound = game.ReplicatedStorage.TimerSound

local function ResetTimer()
	wait()
	if running == false then
		running = true
		StartTimer()
	end
	
	if lastCheckpointTouched and lastCheckpointTouched.TimeValue then
		if lastCheckpointTouched.TimeValue.Value == 1 then
			timerTime = 1 * 60 
		elseif lastCheckpointTouched.TimeValue.Value == 2 then
			timerTime = 45 
		elseif lastCheckpointTouched.TimeValue.Value == 3 then
			timerTime = 30 
		else
			print("Hi - Unknown Checkpoint Value")
		end
		
		if not Started then
			Started = true
			task.spawn(StartTimer)
		else
			Player.CharacterAdded:Wait()
			timerTime = timerTime
		end
	end
end

local function changeColour()
	if clonedgui.Frame.TextLabel.TextColor3 == red and clonedgui.Frame.TextLabel.UIStroke.Color == black then
		clonedgui.Frame.TextLabel.TextColor3 = green1
		clonedgui.Frame.TextLabel.UIStroke.Color = black
	end
end

function StartTimer()
	while timerTime > 0 and running == true do
		timerTime = timerTime - 1
		timerTime = math.max(0, timerTime)

		local minutes = math.floor(timerTime / 60)
		local text = string.format("%d:%02d", minutes, timerTime % 60)
		clonedgui.Frame.TextLabel.Text = text

		if minutes <= 0 and timerTime <= 10 and timerTime >= 9.5 then
			clonedgui.Frame.TextLabel.TextColor3 = red
			clonedgui.Frame.TextLabel.UIStroke.Color = black
			timersound:Play()
		end

		if timerTime <= 0 then
			if mode == false then
				print(mode)
			else
				print(mode)
				Player.Character.Humanoid.Health = 0
			end
		end
		wait(1)
		Player.Character:WaitForChild("Humanoid").Died:Connect(function()
			ResetTimer()
		end)
	end
end

remoteEvent.OnClientEvent:Connect(function(checkpointPart)
	changeColour()
	if checkpointPart and checkpointPart:IsA("BasePart") then
		if lastCheckpointTouched ~= checkpointPart then
			lastCheckpointTouched = checkpointPart

			print(lastCheckpointTouched.TimeValue.Value)

			if lastCheckpointTouched.TimeValue.Value == 1 then
				timerTime = 1 * 60 
			elseif lastCheckpointTouched.TimeValue.Value == 2 then
				timerTime = 45 
			elseif lastCheckpointTouched.TimeValue.Value == 3 then
				timerTime = 30 
			else
				print("Hi - Unknown Checkpoint Value")
			end
			
			local image = clonedgui.image.modeimage

			if lastCheckpointTouched.Mode.Value == true then
				mode = true
				image.Image = skull
			else
				image.Image = heart
				mode = false
			end
			
			changeColour()

			ResetTimer()
		end
	end
end)      

local function stoptimer()
	running = false
	clonedgui.Frame.TextLabel.Text = "0:00"
	lastCheckpointTouched = nil 
end

remoteEvent2.OnClientEvent:Connect(stoptimer)

3 Likes

Heyo, Test This

Every time you die your script runs again so just break the loop when the player dies you can create a debounce for that

local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("OneMinuteTimer")
local remoteEvent2 = ReplicatedStorage:WaitForChild("StopTimer")
local Checkpoint = workspace:WaitForChild("Checkpoints")

local lastCheckpointTouched = nil
local heart = "rbxassetid://13841443245"
local skull = "rbxassetid://13841410348"

local clonedgui = Player.PlayerGui:WaitForChild("Timer")
local timerTime = 2 * 60 
local Started = false
local mode = false
local running = false
local died = false

local red = Color3.fromRGB(231, 37, 37)
local black = Color3.fromRGB(0,0,0)
local white = Color3.fromRGB(255, 255, 255)
local green1 = Color3.fromRGB(80, 207, 61)

local timersound = game.ReplicatedStorage.TimerSound

local function ResetTimer()
	wait()
	if running == false then
		running = true
		StartTimer()
	end

	if lastCheckpointTouched and lastCheckpointTouched.TimeValue then
		if lastCheckpointTouched.TimeValue.Value == 1 then
			timerTime = 1 * 60 
		elseif lastCheckpointTouched.TimeValue.Value == 2 then
			timerTime = 45 
		elseif lastCheckpointTouched.TimeValue.Value == 3 then
			timerTime = 30 
		else
			print("Hi - Unknown Checkpoint Value")
		end

		if not Started then
			Started = true
			task.spawn(StartTimer)
		else
			Player.CharacterAdded:Wait()
			timerTime = timerTime
		end
	end
end

local function changeColour()
	if clonedgui.Frame.TextLabel.TextColor3 == red and clonedgui.Frame.TextLabel.UIStroke.Color == black then
		clonedgui.Frame.TextLabel.TextColor3 = green1
		clonedgui.Frame.TextLabel.UIStroke.Color = black
	end
end

Player.Character:WaitForChild("Humanoid").Died:Connect(function()
	died = true
end)

function StartTimer()
	while timerTime > 0 and running == true do
		if (died) then
			break
		end
		
		timerTime = timerTime - 1
		timerTime = math.max(0, timerTime)

		local minutes = math.floor(timerTime / 60)
		local text = string.format("%d:%02d", minutes, timerTime % 60)
		clonedgui.Frame.TextLabel.Text = text

		if minutes <= 0 and timerTime <= 10 and timerTime >= 9.5 then
			clonedgui.Frame.TextLabel.TextColor3 = red
			clonedgui.Frame.TextLabel.UIStroke.Color = black
			timersound:Play()
		end

		if timerTime <= 0 then
			if mode == false then
				print(mode)
			else
				print(mode)
				Player.Character.Humanoid.Health = 0
			end
		end
		
		wait(1)
		Player.Character:WaitForChild("Humanoid").Died:Connect(function()
			ResetTimer()
		end)
	end
end

remoteEvent.OnClientEvent:Connect(function(checkpointPart)
	changeColour()
	if checkpointPart and checkpointPart:IsA("BasePart") then
		if lastCheckpointTouched ~= checkpointPart then
			lastCheckpointTouched = checkpointPart

			print(lastCheckpointTouched.TimeValue.Value)

			if lastCheckpointTouched.TimeValue.Value == 1 then
				timerTime = 1 * 60 
			elseif lastCheckpointTouched.TimeValue.Value == 2 then
				timerTime = 45 
			elseif lastCheckpointTouched.TimeValue.Value == 3 then
				timerTime = 30 
			else
				print("Hi - Unknown Checkpoint Value")
			end

			local image = clonedgui.image.modeimage

			if lastCheckpointTouched.Mode.Value == true then
				mode = true
				image.Image = skull
			else
				image.Image = heart
				mode = false
			end

			changeColour()

			ResetTimer()
		end
	end
end)      

local function stoptimer()
	running = false
	clonedgui.Frame.TextLabel.Text = "0:00"
	lastCheckpointTouched = nil 
end

remoteEvent2.OnClientEvent:Connect(stoptimer)
3 Likes

Thanks for the response. It is giving me an error “Players.naderbocker2.PlayerScripts.LocalScript:82: attempt to index nil with ‘WaitForChild’”

2 Likes

Replace your script with this one

First, you shouldn’t create a WaitForChild inside a loop, and secondly, you don’t need to catch the player.Died event, because it can be executed only once per script, and I don’t recommend putting it inside a loop, because it it will always be storing it and then when you die it will run everything at once.

Just create this event outside of a loop creating a debounce of “died”, and check if it dies, if it dies just break and reset as if it were an event inside it

local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("OneMinuteTimer")
local remoteEvent2 = ReplicatedStorage:WaitForChild("StopTimer")
local Checkpoint = workspace:WaitForChild("Checkpoints")

local lastCheckpointTouched = nil
local heart = "rbxassetid://13841443245"
local skull = "rbxassetid://13841410348"

local clonedgui = Player.PlayerGui:WaitForChild("Timer")
local timerTime = 2 * 60 
local Started = false
local mode = false
local running = false
local died = false

local red = Color3.fromRGB(231, 37, 37)
local black = Color3.fromRGB(0,0,0)
local white = Color3.fromRGB(255, 255, 255)
local green1 = Color3.fromRGB(80, 207, 61)

local timersound = game.ReplicatedStorage.TimerSound

local function ResetTimer()
	wait()
	if running == false then
		running = true
		StartTimer()
	end

	if lastCheckpointTouched and lastCheckpointTouched.TimeValue then
		if lastCheckpointTouched.TimeValue.Value == 1 then
			timerTime = 1 * 60 
		elseif lastCheckpointTouched.TimeValue.Value == 2 then
			timerTime = 45 
		elseif lastCheckpointTouched.TimeValue.Value == 3 then
			timerTime = 30 
		else
			print("Hi - Unknown Checkpoint Value")
		end

		if not Started then
			Started = true
			task.spawn(StartTimer)
		else
			Player.CharacterAdded:Wait()
			timerTime = timerTime
		end
	end
end

local function changeColour()
	if clonedgui.Frame.TextLabel.TextColor3 == red and clonedgui.Frame.TextLabel.UIStroke.Color == black then
		clonedgui.Frame.TextLabel.TextColor3 = green1
		clonedgui.Frame.TextLabel.UIStroke.Color = black
	end
end

Player.Character:FindFirstChildOfClass("Humanoid").Died:Connect(function()
	died = true
end)

function StartTimer()
	while timerTime > 0 and running == true do
		if (died) then
			ResetTimer()
			break
		end

		timerTime = timerTime - 1
		timerTime = math.max(0, timerTime)

		local minutes = math.floor(timerTime / 60)
		local text = string.format("%d:%02d", minutes, timerTime % 60)
		clonedgui.Frame.TextLabel.Text = text

		if minutes <= 0 and timerTime <= 10 and timerTime >= 9.5 then
			clonedgui.Frame.TextLabel.TextColor3 = red
			clonedgui.Frame.TextLabel.UIStroke.Color = black
			timersound:Play()
		end

		if timerTime <= 0 then
			if mode == false then
				print(mode)
			else
				print(mode)
				Player.Character.Humanoid.Health = 0
			end
		end
	end
end

remoteEvent.OnClientEvent:Connect(function(checkpointPart)
	changeColour()
	if checkpointPart and checkpointPart:IsA("BasePart") then
		if lastCheckpointTouched ~= checkpointPart then
			lastCheckpointTouched = checkpointPart

			print(lastCheckpointTouched.TimeValue.Value)

			if lastCheckpointTouched.TimeValue.Value == 1 then
				timerTime = 1 * 60 
			elseif lastCheckpointTouched.TimeValue.Value == 2 then
				timerTime = 45 
			elseif lastCheckpointTouched.TimeValue.Value == 3 then
				timerTime = 30 
			else
				print("Hi - Unknown Checkpoint Value")
			end

			local image = clonedgui.image.modeimage

			if lastCheckpointTouched.Mode.Value == true then
				mode = true
				image.Image = skull
			else
				image.Image = heart
				mode = false
			end

			changeColour()

			ResetTimer()
		end
	end
end)      

local function stoptimer()
	running = false
	clonedgui.Frame.TextLabel.Text = "0:00"
	lastCheckpointTouched = nil 
end

remoteEvent2.OnClientEvent:Connect(stoptimer)

1 Like

it seems that the issue lies in the ResetTimer function. Currently, you have a line that sets the timerTime variable to the checkpoint value, but then immediately sets it again to itself without any change

Player.CharacterAdded:Wait()
timerTime = timerTime

This redundant line does not have any effect on the timer. To fix the issue and ensure that the timer counts down by 1 every second after resetting, you need to remove that line from the ResetTimer function.

local function ResetTimer()
	wait()
	if running == false then
		running = true
		StartTimer()
	end
	
	if lastCheckpointTouched and lastCheckpointTouched.TimeValue then
		if lastCheckpointTouched.TimeValue.Value == 1 then
			timerTime = 1 * 60 
		elseif lastCheckpointTouched.TimeValue.Value == 2 then
			timerTime = 45 
		elseif lastCheckpointTouched.TimeValue.Value == 3 then
			timerTime = 30 
		else
			print("Hi - Unknown Checkpoint Value")
		end
		
		if not Started then
			Started = true
			task.spawn(StartTimer)
		end
	end
end

1 Like

Put it in the TextLabel without the ResetOnSpawn on, otherwise, if you keep dying over and over again, the text will count as a negative time, and you don’t want that.

It is necessarily needed to have a Screengui, a textlabel and more if you want to (since you already have it, but forgot to add it into the original game, meaning you added it with a script).

local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("OneMinuteTimer")
local remoteEvent2 = ReplicatedStorage:WaitForChild("StopTimer")
local Checkpoint = workspace:WaitForChild("Checkpoints")

local lastCheckpointTouched = nil
local heart = "rbxassetid://13841443245"
local skull = "rbxassetid://13841410348"

local clonedgui = Player.PlayerGui:WaitForChild("Timer")
local timerTime = 2 * 60 
local Started = false
local mode = false
local running = false

local red = Color3.fromRGB(231, 37, 37)
local black = Color3.fromRGB(0,0,0)
local white = Color3.fromRGB(255, 255, 255)
local green1 = Color3.fromRGB(80, 207, 61)

local timersound = game.ReplicatedStorage.TimerSound

local function ResetTimer()
	wait()
	if running == false then
		running = true
		StartTimer()
	end
	
	if lastCheckpointTouched and lastCheckpointTouched.TimeValue then
		if lastCheckpointTouched.TimeValue.Value == 1 then
			timerTime = 1 * 60 
		elseif lastCheckpointTouched.TimeValue.Value == 2 then
			timerTime = 45 
		elseif lastCheckpointTouched.TimeValue.Value == 3 then
			timerTime = 30 
		else
			print("Hi - Unknown Checkpoint Value")
		end
		
		if not Started then
			Started = true
			task.spawn(StartTimer)
		else
			Player.CharacterAdded:Wait()
			timerTime = timerTime
		end
	end
end

local function changeColour()
	if clonedgui.Frame.TextLabel.TextColor3 == red and clonedgui.Frame.TextLabel.UIStroke.Color == black then
		clonedgui.Frame.TextLabel.TextColor3 = green1
		clonedgui.Frame.TextLabel.UIStroke.Color = black
	end
end

function StartTimer()
	while timerTime > 0 and running == true do
		timerTime = timerTime - 1
		timerTime = math.max(0, timerTime)

		local minutes = math.floor(timerTime / 60)
		local text = string.format("%d:%02d", minutes, timerTime % 60)
		clonedgui.Frame.TextLabel.Text = text

		if minutes <= 0 and timerTime <= 10 and timerTime >= 9.5 then
			clonedgui.Frame.TextLabel.TextColor3 = red
			clonedgui.Frame.TextLabel.UIStroke.Color = black
			timersound:Play()
		end

		if timerTime <= 0 then
			if mode == false then
				print(mode)
			else
				print(mode)
				Player.Character.Humanoid.Health = 0
			end
		end
		wait(1)
		Player.Character:WaitForChild("Humanoid").Died:Connect(function()
			ResetTimer()
			timerTime += 1
		end)
	end
end

remoteEvent.OnClientEvent:Connect(function(checkpointPart)
	changeColour()
	if checkpointPart and checkpointPart:IsA("BasePart") then
		if lastCheckpointTouched ~= checkpointPart then
			lastCheckpointTouched = checkpointPart

			print(lastCheckpointTouched.TimeValue.Value)

			if lastCheckpointTouched.TimeValue.Value == 1 then
				timerTime = 1 * 60 
			elseif lastCheckpointTouched.TimeValue.Value == 2 then
				timerTime = 45 
			elseif lastCheckpointTouched.TimeValue.Value == 3 then
				timerTime = 30 
			else
				print("Hi - Unknown Checkpoint Value")
			end
			
			local image = clonedgui.image.modeimage

			if lastCheckpointTouched.Mode.Value == true then
				mode = true
				image.Image = skull
			else
				image.Image = heart
				mode = false
			end
			
			changeColour()

			ResetTimer()
		end
	end
end)      

local function stoptimer()
	running = false
	clonedgui.Frame.TextLabel.Text = "0:00"
	lastCheckpointTouched = nil 
end

remoteEvent2.OnClientEvent:Connect(stoptimer)
1 Like

Thanks for the response. That didn’t fix the problem, do you think that it could be because of the line if running == false then?

1 Like

Put the local script into the TextLabel?

1 Like

You’re right, the line if running == false then in the ResetTimer function could be causing the issue

local function ResetTimer()
	wait()
	running = true
	StartTimer()
	
	if lastCheckpointTouched and lastCheckpointTouched.TimeValue then
		if lastCheckpointTouched.TimeValue.Value == 1 then
			timerTime = 1 * 60 
		elseif lastCheckpointTouched.TimeValue.Value == 2 then
			timerTime = 45 
		elseif lastCheckpointTouched.TimeValue.Value == 3 then
			timerTime = 30 
		else
			print("Hi - Unknown Checkpoint Value")
		end
		
		if not Started then
			Started = true
			task.spawn(StartTimer)
		end
	end
end
1 Like

No it doesn’t actually look like that fixed the problem, now when the player dies or resets the timer restarts but is counting down by 4 seconds at the same 2x pace.

1 Like

I guess, anyhow I put a teeny-tiny different script.

It may look exactly the same but.

1 Like

The timer GUI is being cloned to every players PlayerGui as soon as they join the game. The timer GUI is in Replicated Storage, should I still put the script you provided in the timer GUI?

That still outputs an error trying to index nil with “FindFirstChildOfClass”

The issue with the timer counting down 2x as fast when the local player dies can be resolved by restructuring the code. Currently, the StartTimer function is being called multiple times, which leads to unexpected behavior.

To fix this, you can modify the code as follows:

local function ResetTimer()
	if running == false then
		running = true
		StartTimer()
	end
	
	-- Rest of the code...
end

function StartTimer()
	-- Move the Player.Character:WaitForChild("Humanoid").Died connection outside the while loop
	Player.Character:WaitForChild("Humanoid").Died:Connect(function()
		ResetTimer()
	end)
	
	while timerTime > 0 and running == true do
		-- Rest of the code...
	end
end

By moving the Player.Character:WaitForChild("Humanoid").Died connection outside the while loop in the StartTimer function, it ensures that the connection is established only once. This prevents the timer from counting down 2x as fast when the player dies.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.