Timer with miliseconds

I’m making a obby game, where the game counts the time you took to beat a specific obby.
I made a timer script myself, but it seems to be taking longer to count that a normal timer.
Here is the code:

local val = 0
local mili = 0
local sec = 0
local min = 0

while true do
	wait(.1)
	val = val + 1
	mili = mili + 1
	if mili > 9 then
		mili = 0
		sec = sec + 1
		game.SoundService.Timer:Play()
	end
	if sec > 59 then
		sec = 0
		min = min + 1
	end
	
	if sec < 10 then
		local text = min..":0"..sec..":"..mili
		script.Parent.Parent.Main.Timer.Text = text
	else
		local text = min..":"..sec..":"..mili
		script.Parent.Parent.Main.Timer.Text = text
	end
	
	script.Parent.Parent.Miliseconds.Value = val
end 

For some reason the timing in this script seems to be off.
Why does that happen?

Any help?

EDIT: I want the format of the timer to be this: 0:00:0 (minutes:seconds:miliseconds)

2 Likes

Don’t increment the time after a wait in a loop. Instead, store the starting time and then subtract it from the current time to get how many seconds/milliseconds have passed using tick()

local start = tick() 
while true do
    wait()
 
    local diff = tick() - start
    print(diff, "seconds has passed since the start") 

    local min = math.floor(diff / 60)
    print(min .. ":" .. (diff - min*60), "total time has passed") 
end
4 Likes

I’ve never used tick() before, so I’m a total noob to this.

How would I make your script print the time in this format: 0:00:0 instead of 0:0.0000000000000?

So for instance: 2:07:3 instead of 2:7.337853975399876

tick() returns the local time with milliseconds. In order to turn i.e. 0.312345 into 3, you can simply multiply the number by 10 and use math.floor on it:

local start = tick() 
while true do
    wait()
 
    local diff = tick() - start
    print(diff, "seconds has passed since the start") 

    local min = math.floor(diff / 60)
    local sec = diff - min*60
    local mil = math.floor((sec - math.floor(sec)) * 10) -- doing 7.123 - 7 gives us 0.123, then multiply by 10 and floor to get just 1
    sec = math.floor(sec)
    print(min .. ":" .. sec .. ":" .. mil, "total time has passed") 
end

(typed on phone so excuse any mistakes)

16 Likes

Hello! I found this post very useful, but if a player were to die, how would you stop the timer?

Old post, sorry, but isn’t using wait() in a while loop bad performance wise?

while true do
    wait()
--stuff
end
2 Likes

I tried to make my code example look like an edit of the op’s code for easier understanding, hence why I kept the loop and the wait()

Anyways personally I don’t think wait() in a loop would cause more performance issues than ex. Heartbeat:Wait() in the same loop, because wait()'s yielding time increases if the game isn’t “keeping up”, causing the loop to run less often, which in this case would be a good thing imo. (Note that I might be wrong, I didn’t really stress test it).

But if you absolutely need your code to loop continuously then yeah, go with RunService, though personally I’d do that for stuff related to physics or rendering, not for a timer.

3 Likes

Hmm, maybe this solution will be the most efficient?

Using this code in a local script so the player sees the timer updating with milliseconds, then in a server script you would have a tick() for when the round starts and one tick() for when the player finishes it.

The true timer would be tick2 - tick1 value and so it will not cause lag for the other players.

Or this concern would be about the competing player alone that will experience lag because of the resources used up by wait() in a loop/Heartbeat:Wait() on his device?

1 Like