How do you create a timer with milliseconds for speedrun

I’m trying to add speedrunning to my game and I know how to make a simple timer with minutes and seconds, but I have no clue how to make a timer with 3 seperate digits of milliseconds.

2 Likes

Use RunService.Heartbeat and track how much the deltaTime has increased by.

Code:

local RunService = game:GetService("RunService")

local totalTime = 0

RunService.Heartbeat:Connect(function(deltaTime)
	totalTime += deltaTime
	
	print(totalTime)
end)

In my testing, it keeps around 15 decimal digits of precision.

1 Like

Thank you, it works, but what is delta time?

Alternatively, you could resort to:

local RunService = game:GetService("RunService")

local clockStart = os.clock()
local timeElapsed = 0

RunService.Heartbeat:Connect(function()
    timeElapsed = os.clock() - clockStart
end)

deltaTime is the amount of time since the previous frame.

@HexadecimalLiker
You’re just reinventing deltaTime, not sure why you would do this.

How can you easily format this into 0:00:000

Like minute:second:millisecond?

If you want to do that, format the string accordingly:

local RunService = game:GetService("RunService")

local totalTime = 0

local function ToMSM(s)
	return string.format("%02i:%02i:%03i", s/60%60, s%60, s%1*1000)
end

RunService.Heartbeat:Connect(function(deltaTime)
	totalTime += deltaTime
	
	print(ToMSM(totalTime))
end)

Source: Creating a timer that displays milliseconds - #9 by JavierR100

Does the “%” when doing the calculations round it, if so then up or down?

1 Like

It rounds it to the nearest hundredth or thousandth.

For example, if we were roundingto the nearest hundredth:

0.005 would be rounded to 0.01
0.004 would be rounded to 0.00

Edit: Oh apologies, I thought you were talking about the string.format. The modulo operator gets the remainder of the division.

So for example:

7 % 7 = 0
6 % 7 = 6

The best way to do this is how @HexadecimalLiker suggested

local RunService = game:GetService("RunService")

local clockStart = os.clock()
local timeElapsed = 0

RunService.Heartbeat:Connect(function()
    timeElapsed = os.clock() - clockStart
end)

@Katrist He is not reinventing deltaTime, since with floating point numbers, there is a possibility of loosing precision every time an operation is done, and therefore with your method, over time there is a possibility of loosing a bit of precision. So Instead of of adding the deltaTime every frame, you take the time at the start and subtract it from the current time. This is more precise, especially over tens of thousands of frames.

Technical Details

In the luau source you can see that the clock function is directly from the system time, which is possibly more precise than the deltaTime in the Heartbeat event.
luau/VM/src/lperf.cpp at master · luau-lang/luau (github.com)
On windows this calls the QueryPerformanceCounter which is built into the OS.

In summery, adding the dt every frame isn’t the best since it introduces errors over time so comparing from a timestamp at the start is preferred.
However, in this sort of case, close-to-millisecond precision probably isn’t necessary : P so either method will work alright.

3 Likes

This feels like you’re highly optimizing something that doesn’t need to be lol. Calling os.clock itself also takes time, further factoring into the precision error that your code makes too.

There’s really no need though, it’s not like the player will notice a 0.0001 second difference.

1 Like

Did you know: it doesn’t matter if it “takes time” because it just immediately updates it at each event? Also the time difference between calling the C function clock and using deltaTime are very close. Would you prefer speed over reliability?

% is the “modulo” operation. Modulo - Wikipedia

Yes, but that means that the time would be offset slightly.

Yes, especially when a 0.0001 second difference is unrecognizable to a human.

All of this literally does not matter though, I think we can end the dicussion.

…but it would do the same thing with deltaTime

Which would be another reason why deltaTime is better, since it’s faster.

Like I said though,

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