Time Counter not working properly

Greetings,

I wanted to make a time counter script that counts milliseconds, seconds and minutes. But when I test the game, the countdown stops at 8 milliseconds and won’t go further. Can anyone explain what I did wrong?

local timer = script.Parent --TextLabel where the countdown is shown

local milliseconds = 0
local seconds = 0
local minutes = 0

while true do
	if milliseconds > 99 then
		milliseconds = 0
		seconds = seconds + 1
		if seconds > 59 then
			seconds = 0
			minutes = minutes + 1
		end
	end
	
	if milliseconds < 9 then
		if seconds < 9 then
			if minutes < 9 then
				timer.Text = "0"..minutes..":0"..seconds..":0"..milliseconds
			else
				timer.Text = minutes..":"..seconds..":"..milliseconds
			end
		end
	end
	
	wait(.01)
	milliseconds = milliseconds + 1 --Adds milliseconds
end
2 Likes

Try this:

--//Variables
local timer = script.Parent --//TextLabel where the countdown is shown

--//Controls
local milliseconds = 0
local seconds = 0
local minutes = 0

--//Loops
while true do
	if milliseconds > 99 then
		milliseconds = 0
		seconds += 1
		
		if seconds > 59 then
			seconds = 0
			minutes += 1
		end
	end
	
	timer.Text = (minutes < 10 and "0".. minutes or minutes) 
		.. (seconds < 10 and ":0".. seconds or ":".. seconds) 
		.. (milliseconds < 10 and ":0".. milliseconds or ":".. milliseconds)

	task.wait(0.01)
	milliseconds += 1 --//Adds milliseconds
end

Thanks a lot, it’s working now as it should.

1 Like

Okay if everything works, you should set my reply as the solution. If you have any more problems, feel free to ask.

I made another script that is more accurate and accounts for the player’s FPS so there isn’t any inconsistencies with the time.

New script:

--//Services
local RunService = game:GetService("RunService")

--//Variables
local timer = script.Parent

--//Controls
local timeElapsed = 0

--//Functions
local function ConvertSeconds(s)
	return string.format("%02i:%02i:%02i", s/60%60, s%60, s % 1 * 100)
end

RunService.RenderStepped:Connect(function(deltaTime)
	timeElapsed += deltaTime
	timer.Text = ConvertSeconds(timeElapsed)
end)

Optimization for @Katrist’s script would be as followed.

task.wait(0.01) would not specifically wait 0.01 seconds, this is an unreliable method. So instead we are going to use Runservice.

local RunService = game:GetService("RunService")

RunService:BindToRenderStepped("Timer", 1, function(dt)
   ...
end)

dt stands for Delta time also known as the change in time. How long it took to go from frame 1 to frame 2 etc.
Now we will save the time

local t = 0

And to change the time we will use:

t += dt

Now to get the miliseconds we can just use:

-- here we can round it off, but it doesnt make much difference
local mili = math.floor((t % 1) * 1000)

For the seconds we can do:

local sec = math.floor(t % 60)

And lastely for minutes we can use:

local min = math.floor(t/60)

Now a quick explaination on %, also known as the remainder. Basically X % Y is the same as

local X, Y = ...
print(X%Y)
print(((X/Y) - math.floor(X/Y)) * Y)

Basically you get the remainder which is left.

Example:

0%3 = 0; 3%3 = 0; 6%3 = 0
1%3 = 1; 4%3 = 1; 7%3 = 1
2%3 = 2; 5%3 = 0; 8%3 = 2

Now we turn all the values into strings with tostring(), though this is not necessary, but will surely prevent any errors.

Then we will add 0s to the values until they are big enough. For example we got the string "1" for seconds, we want that to become "01", so we will need to repeatedly add 0s to the value. Same for the milliseconds, but "1", would become "001", well because 1000 millisecond is the same as 1 second.

(Remember they have to be strings for this) Now we will get the length of the numbers and then add 0s to them until it’s not needed anymore. We can use # to get the length. It would look like this:

min = string.rep("0", 2 - #min) .. min
sec = string.rep("0", 2 - #sec) .. sec
milli = string.rep("0", 3 - #milli) .. milli

Now we only have to put double collumns : in between of them like so:

timer.Text = min .. ":" .. sec .. ":" .. milli

Now the code would look something like this:

local RunService = game:GetService("RunService")
local timer = script.Parent

local t = 0
RunService:BindToRenderStepped("Timer", 1, function(dt)
   t += dt
   
   local min, sec, milli = (math.floor(t/60)), (math.floor(t % 60)), (math.floor((t % 1) * 1000))
   min, sec, milli = tostring(min), tostring(sec), tostring(milli)
   min, sec, milli = string.rep("0", 2 - #min) .. min, string.rep("0", 2 - #sec) .. sec, string.rep("0", 3 - #milli) .. milli

   timer.Text = min .. ":" .. sec .. ":" .. milli
end)

This will run every frame unlike while true do as well as accurately count the time unlike task.wait().

I already made a script that uses RenderStepped, also string functions like string.rep are less performant than math operations.

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