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.
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
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!
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.