Using tick() for handling time systems

Many of us might know of the tick() function. Many of us do not know how to use it or ways/methods of application for this function. It can be a useful function and has many use cases/applications. Like printing execution time information with some basic math and also other systems like cooldowns and other things.


Why not use task.wait()

(please do not use depreciated functions like wait())

these functions completely halt the thread that it is currently running in. We might not want to do this as we may want to do other functionality between the delay which is where we can use tick().


The code

Now. Lets say we want to run foo() and then calculate how long it took to run foo() but we also want to make it wait 2.5 seconds before running it again. All we need to do is the following:


local startTick = tick() -- get the time at the start of the execution.
-- We will replace the above tick with a new tick at the end of foo. You can do this wherever it fits in your own.

function foo()
	
	local sTick = tick()
	
	warn("I was ran!")
	
	print("It took me  ~"..tick() - sTick.." to finish my execution excluding this message")
	
	startTick = tick() -- new tick time
end


-- we do not want to set a new tick inside of the loop as this will just loop forever and wont ever execute foo. My experience anyway

-- A successful log should look like the following. Please ignore the fact it shows a negative number for the print.
-- It should not matter at least it hasnt when I have used tick().

--[[

  19:11:04.509   â–¶ We need to wait-0before executing foo again (x4)  -  Client - testing:29
  19:11:05.539   â–¶ We need to wait-1before executing foo again (x3)  -  Client - testing:29
  19:11:06.355   â–¶ We need to wait-2before executing foo again (x20)  -  Client - testing:29
  19:11:06.842  I was ran!  -  Client - testing:8
  19:11:06.842  It took me  ~0.000354766845703125 to finish my execution excluding this message  -  Client - testing:10

]]


game:GetService("RunService").RenderStepped:Connect(function(delta)
	
	-- if it has been more than 2.5 seconds we will execute.
	if ( tick() - startTick) >= 2.5 then
		
		foo()
		
	else
		
		print("We need to wait"..math.round(startTick - tick()).."before executing foo again")
		
	end
	
	task.wait() -- I forgot why this doesnt work without task.wait() but just dont remove it.
	-- At least that is the case within my studio instance. Might be a weird anomaly not sure. Dont ask me please <3.
end)


Disclaimer

I may have something wrong or missaligned with the truth in my post and if so please point it out to me and follow up with why. I WILL adjust any mistakes I have made when explaining. Just do not be rude as there is no need for attitude, we are all human.


NOTE

4 Likes

What about workspace:GetServerTimeNow()?

1 Like

Why would you need to use that for an alternative to tick()/task.wait()? I don’t see the point of using this. Tick gets the current Unix Epoch of the system anyway.

On top of this I honestly havent really used GetServerTimeNow as my tasks have never really needed it so I personally can’t see any reason for its use

1 Like

Your compariosn isn’t right though. When talking about tick(), the question “Why not task.wait()” is not relevant. Both, even if they’re only connected by the concept of time, do different things. Tick gets, as you said, the current Unix time, while the wait function halts the thread for x seconds. I did see posts regarding comparisons between tick and GetServerTimeNow. Also,

1 Like

It somewhat is as I am trying to teach the newer developers who may not understand. So in a way it is relevant.

1 Like

use os.clock() instead
Its better in everything

1 Like

just wanted to state that this would be mostly better if you wanted a synced time between the server and the client iirc

1 Like
  • If you want to measure execution time, use os.clock().
  • If you want to get a stable unix time, use os.time() (1 second resolution).
  • If you want to get the client’s best guess at the server’s time, use workspace:GetServerTimeNow(). This is also unix time, but with better resolution than os.time(). Good for syncing things between all the clients and the server.
  • If you want to do general timekeeping during runtime, use time(). I generally tell people to reach for time() unless they need one of the others. This is essentially the amount of time the current server or client has been running, and is updated once per frame.

The general rule is to not use tick() for anything anymore. There are a couple issues with tick:

  1. It may be up to 1 second off
  2. It is relative to the current system time (i.e. timezones affect it)
  3. Likely to be deprecated in the future
13 Likes

I didn’t even know that. tick() is terrible.

1 Like

The documentation for tick() just got updated in the last week to make a note on this Roblox globals | Documentation - Roblox Creator Hub

3 Likes

os.time() is also affected by this, and it isn’t due to tick() or os.time() being bad, but rather the time on the player’s computer being off

Windows (and basically every os) handles time synchronization automatically but it also has a button to manually synchronize the time. However, it doesn’t keep time synced that precisely


french moment

I had a report of os.time() being off by an hour (somehow) on someone’s computer causing issues between server and client messages in my fork of the LegacyChat. If you need time to be precises between the server and the client , workspace:GetServerTimeNow() or a custom syncing/offset solution is required

os.time()

I’m not sure why the docs state that tick() can be off by up to a second, I guess the implementation is off from the os’s time? In practice I’m not sure this is very relevant considering you’d have syncing issues regardless

3 Likes

Sorry I was not aware of this. Thank you so much! I will quote you in my reply and take this information with me.

1 Like

Both fairly interesting points. I have put sleitnicks reply on the post however as I feel it would likely be best to take his advice however not saying yours should be disregarded. I am not too 100% with certain things on this platform when it comes to understanding the inner workings (I have never really looked deeply at it all just read the docs, used them in theory/projects and that’s it.) so do understand my pov.

Again thank you both (@sleitnick) for your information and help!

2 Likes

Pretty sure os.time() is better for use on the server.

3 Likes

Perhaps, but os.time() has only precision up to the second…

The annoying thing with all this is that there is no “good” way to get high precision time. To get milliseconds precision, you have to use DateTime (which is a bit of a pain to work with), but that only gives you millisecond precision (for doing client side custom “tweens”, as a function of time, not great because 1ms is ~ 1/4 of a frame at 240fps)

What I ended up doing is making a TickModule, that use os.clock(), with an offset calculated with DateTime, to make it return UTC (or local) time. It should have millisecond precision (+ or - .5ms?), but has more digits to work with

3 Likes

Good points. I’m thinking specifically about server time here. On the server, tick() can be 1 second off. From my understanding the 1-second issue with os.time() was fixed a while back.

4 Likes