Making an accurate 1 second delay

I just wanted to confirm this.

So you might know what task.wait() actually does. It delays the script by the yield provided, followed by one frame. Now, I think I found a way to make it extremely accurate to one second.

You can get the amount of time a frame lasts for before refreshed using RunSevice’s “delta time”:

local delta = RunService.Heartbeat:Wait()

while task.wait(1-delta) do
    --code
end
--Does this run on exactly one second? Who knows.

Just wanted to clarify it, tell me if you know. Thanks.

2 Likes

Try using the pattern I love using:

local lastTime = os.clock()

RunService.Heartbeat:Connect(function()
    if (os.clock() - lastTime) >= 1 then
        -- High precision to one second, but always rough around the edges 
        -- especially with performance impacting it.
        lastTime = os.clock()
    end
end
2 Likes

I quite literally mean making it very accurate.

task.wait() by itself is accurate but it’s not pin-point, kind of like yours, having “roughness around it’s edges”.

1 Like

Yeah, I’m afraid there’s no other way to make it exact. You can only estimate it because machines are not able to time it right every time. It’s always going to be decimals somewhere. Hypothetically you’re going to need an extremely expensive piece of hardware to be able to make it precise enough!

1 Like

You can calculate delta time, by the way, by very simply dividing 1 by your FPS.

local fps = 60

print(1/fps)
--0.01666
--delta time

Well what can be the most accurate?
Is it very simply task.wait()?

According to what I remember from last time of talks about task.wait(), it is the most accurate one as you can get.

This is the same as doing task.wait(1)

1 Like

It won’t really lead to higher accuracy. You’re just setting it back a frame instead. It means that instead of overshooting, you will probably undershoot the time value. You can’t really hit an exact wait because that would mean landing exactly on a heartbeat. Basically task.wait() waits the exact amount you specified, and then queues the code for execution at the next moment it can. Your code makes that happen early instead of late.

I mean since you know about deltatime and you’re curious about making it ‘extra’ accurate then I assume you want to know what accumulator loops are. They calculate passed time taking deltatime into account making them extremely useful in any situation where there’s any lag in the game.

I always use this type of script in my games. task.wait() is not guaranteed to run every frame, it’s not guaranteed 60 fps. While Heartbeat and Renderstepped run at 60 ticks they come with the deltatime argument that you can use in case ANY server lag.

Here’s my answer on another topic with a little demonstration:


So if you want something accurate to 1 second use this:

--!strict

local RS = game:GetService("RunService")

local rate: number = 1
local accumulated: number = 0

RS.RenderStepped:Connect(function(deltaTime: number)
	accumulated += deltaTime
	while accumulated >= rate do
		accumulated -= rate
		print("1 second. Takes lag into consideration")
	end
end)

You can always add some sort of offset to it if you’re making a timer using os.clock just to make it extra accurate but I haven’t had issues with that in my clocks.

2 Likes

I don’t know if it’s any better, but Custom Wait, the best solution to yielding itself, is slightly better than task.wait().

1 Like

Yeah it’s basically what I wrote. An accumator loop except with the os.clock offset applied. This should be the solution. :+1:

1 Like

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