How to make an accurate cooldown timer?

In my game, players are able to use powers which after being used, initiates a cooldown period. In the server this is simple as I simply need to wait(x) a certain amount and disable the cooldown for the power for that player.
However on the client I would have to use:
for i = 10, 0, -1 do
wait(1)
This is so that there is a visible timer on the client side as well as a second method of checking whether a power is active. However, during moments where there is a lot going on in the game, the timer slows down and doesn’t wait 1 second. I understand that using wait(1) does not mean it will actually wait 1 second but instead wait AT LEAST 1 second. Is there a way to accurately create a cooldown timer that is visible on a GUI?

4 Likes

I’m afraid wait(1)'s the most accurate you can get to 1 second, unless you do something insane like this

local t = tick()
local holdingval
function subt()
holdingval = tick() - t
end
repeat subt until holdingval >= 1000

although I do not suggest the above since it might not even be better, it might be costly on performance, takes up a bit more memory, and if the server is lagging the players probably wouldn’t be too surprised if the timer was moving slowly.

In my opinion, wait(1) is you best choice, but if you really want to use the above, go ahead and try I guess

2 Likes

For a timer that is accurate down to the nearest millisecond use something like:

local Initiate = tick()
while tick() - Initiate < 90 do
    game:GetService("RunService").Heartbeat:Wait()
    -- execute function
end

EDIT: This tick() loop ensures that the loop duration only lasts for X amount of seconds, but if you are just trying to have a very accurate wait(1) loop, swap the Heartbeat:Wait() line with wait(1).

5 Likes

I’m afraid my scripting experience is relatively limited :frowning: but I am willing to read upon this.

2 Likes

Let me know if you need an explanation on anything.

the tick() function gets the amount of miliseconds from a certain date (forgot when, think it was in the 1900s)

1 Like

So if I replace the entirety of the Heartbeat:Wait() line with just wait(1), would that mean the < 90 would refer to the amount of loops that would run, therefore 90 seconds.

I see, what about os.time? Is there any difference between the two? As I use os.time to create a subscription based developer product.

os.time is lua’s, and tick() is roblox’s

if I’m not mistaken they’re the same except for the fact tick() goes into the decimal place while os.time does not

1 Like

The 90 Seconds is the condition that the loop MUST run for that amount of time, the Heartbeat:Wait() just means that theres a 0.02 second delay inbetween the loop running again, versus a 1 second wait with wait(1)

1 Like

Just a note, it’s actually 90 miliseconds in your script
tick gets its value in miliseconds
1000 miliseconds = 1 second

forgot about the wait

1 Like

I usually just have one timer on the client and one on the server for abilities

I also don’t use wait(x) as it tends to yield and that isn’t always wanted

local debounceTick = tick()
local debounceTime = 5

function ability()
	
	local currentTime = tick()
	if currentTime - debounceTick >= debounceTime then -- checks if it's been greater than debounceTime amount of seconds since we last did the ability
		
		debounceTick = tick()
		print("ability fired")
		
	end
	
end

also you don’t need a timer that’s 100% accurate to the millisecond for abilities

3 Likes

But for visual purposes, where there is a TextLabel that counts it down, how would you go about creating an accurate one?

function getRemainder(DebounceTick, DebounceTime)
	return DebounceTime - (tick() - DebounceTick)
end

can get the exact remainder of the cooldown in seconds with this function, I’d use this in a loop to update the text label

4 Likes

Sorry to bump this thread, but I’ve been offline and couldn’t respond.

image
This is incorrect, the loop duration is 90 seconds, not milliseconds like you claim, it updates to every Heartbeat:Wait() tick until the 90 second condition has been reached.

EDIT: Added a quote.

2 Likes

Since os.time doesn’t go into decimal places does that mean you can only read it by seconds instead of 0.5 of a second for example

Does this mean tick() is a more accurate way to measure the exact time that has passed?

I don’t know if I’m missing something but you could just use task.wait it’s very accurate and easy to use

1 Like

This video might help

3 Likes