Help with scripting stopwatch script

Hi there. Im making a game called Adventure World, and this is the basic idea of it. You complete obbies/courses to unlock new courses. But in order to unlock those courses, you need to collect coins and get good completion times. I have been scripting for more than a year and need some help.

Right now im trying to create a stop watch timer. I know a little bit on how to use the tick function, but I really need some guidance on how to create this. Im also trying to learn about string converting (string.sub, string. format, ect.).

I have made some of the script(BELOW) and I have tried looking up how to create a stopwatch timer, but its not what im looking for or its a little to confusing.

-- Timer Looks like this:   00:00.00

local function displayTime()
	local text = script.Parent.Text
	local milliseconds =  -- This is what I need help with
	local seconds =  --This is what I need help with
	local minutes =  --This is what I need help with
	Text = (minutes.. ":" .. seconds.. "." ..milliseconds)

while timeIsRunning == true do -- timeIsRunning is a made up bool value I just made up, and is set to true when players click the start button. But I don't need help with that

So basically I just need help with the milliseconds, seconds, and minutes part of this script. Please tell me if there is a better way to do this.


This may be of some use to you.

First off, the text won’t even update with this - you’re assigning a variable to the current text and when you change that variable, it’ll update the variable and not the text

For displaying the time, you can get the time difference of two ticks: the initial (starting) tick, and the current. tick returns the number of seconds elapsed from the UNIX epoch (January 1, 1970) based on the computer’s time. Unlike os.time, tick returns exactly the number of seconds elapsed:

local function displayTime(diff)
	local label = script.Parent
	local milliseconds =  ("%.3f"):format(tostring((diff % 1) * 1000))
	local seconds =  diff % 60
	local minutes =  math.floor(diff / 60) % 60
	label.Text = (minutes.. ":" .. seconds.. "." ..milliseconds)

local t = tick()

while timeIsRunning do
    displayTime(tick() - t)

thanks for these resources. I will look into them!

1 Like

I tried this script, and when it runs I get lots of numbers after the decimal point. I can I fix this?

while wait(0.001) do
    miliseconds = miliseconds + 1
    if miliseconds == 1000 then
        seconds = seconds + 1
        miliseconds = 0
    if seconds == 60 then
        minutes = minutes + 1
        seconds = 0
1 Like

Here’s a bit of fixes:

local function displayTime(diff)
	local label = script.Parent
	local milliseconds =  ("%.3s"):format(tostring((diff % 1) * 1000))
	local seconds =  math.floor(diff % 60)
	local minutes =  math.floor(diff / 60) % 60

    if seconds < 10 then
        seconds = "0" .. tostring(seconds)

	label.Text = (minutes.. ":" .. seconds.. "." ..milliseconds)

@DatMADBuilder One thing to note: wait’s minimum wait time is 0.03 seconds. Also, don’t use wait as a condition for a while loop



  1. wait has a minimum duration much higher than 0.001, about 1/30 in practice.
  2. while wait() do
  3. Trying to count iterations in a loop for timing will never be the best option. The minimum wait time is unlikely to be the same on very CPU-intensive games.

To get around these issues, you could at least use the first return value of wait(), which is the actual time yielded. Unfortunately, just adding that time to a counter might reduce the accuracy of your timing.
The most accurate solution is to use tick() to calculate the elapsed time since the start of the timer.

special thanks to @Raretendoblox for almost making my reply pointless while I was still typing


I never knew that there was a minimum that high, but using wait() as a condition for a while loop, is the same as doing

while true do

so in theory it just saves time while coding.

one tiny problem:
In this picture I spawned right by the finished line to stop the time.
It shows a decimal after milliseconds. How would I fix this? I also got rid of the thousandths place in the milliseconds cause I don’t think I need that part. Either way though it will still show the decimal.

1 Like

did you ever figure it out? im still trying to make this lol

Yes, here it is:

local function displayTime(diff)
	local seconds =  string.format("%05.2f", diff % 60)
	local minutes =  math.floor(diff / 60) % 60
	if minutes < 10 then -- if the time is greater than 10 minutes, then ...
	     timerGui.Text = "0".. minutes .. ":" .. seconds
	else -- if its not greater
	 timerGui.Text = minutes .. ":" .. seconds

local t = os.clock()
local timer
local function timerFunction()	
	local timePassed = os.clock() - t
	if timePassed  >  900  or isFinished then --if the time is greater than 15 minutes or finsihed
		timer:Disconnect() --stop timer
	displayTime(timePassed) -- display the time
timer = runService.Heartbeat:Connect(timerFunction) -- this timer runs on runservice

Let me know if you have any questions

1 Like

yeah i have a few questions and sorry if there stupid :sweat_smile:

what is os.clock() do
what is run.Service
and what is hearbeat.

everything else seems pretty straightfoward thx

Sorry for the late response.

I don’t have a clear definition for os.clock(), but i think its similar to tick(). Here is the definiton on the hub:

os.clock is the amount of CPU time used by Lua in seconds.

RunService is mostly used for time managing scripts. It has an event called Heartbeat, which runs, or is fired, at every frame(fps). So if the game is running at 60fps(frames per second), RunService.Heartbeat will run 60 times.

Again, sorry for the late response, and these are great questions. Before, I was a bit confused on how run service worked too. If you have anymore questions, I will gladly answer them.

Have a good day.


no questions thank you very much!