Wait Faster Than 1/60th of a Second

1/120 Wait

Hello all! I’m introducing something neat I found while playing around with LuaU, it allows instructions to run twice within a frame, but evenly spaced out as if it was 1/120th of a second, and even 1/180 of a second in the client. But it’s definitely not perfect, right now so I’m hoping better scripters in the community can improve upon this if they care to do so.

How Does It Work?

Heartbeat and Stepped both run within the same frame (and RenderStepped in the client). What happens is that these services are put into a table and then looped to run when Heartbeat fires and then run when Stepped fires, both within the same frame, changing a number value when both waits fire so that when a “Changed:” event is hooked it is fired around 1/120 of a second.

Credits to zeuxcg and Fractality_alt for the Image:

Here’s a video in it in action


What Is This Useful For?

Due to the ever growing world of events and tweening and connect() and whatnot and not needing to check for something every frame anymore, not much, but it can definitely be used to fire something as fast as possible be it a gun or calculations (As long as it’s optimized). It could also be used for more accurate wait times (Wait ~3/120th of a second instead of having to wait 1/30th of a second).

It’s uncopylocked, enjoy.

16 Likes

Is there really any purpose to updating something more than once per frame? Rendering, physics, network and basically everything else updates only once per frame. Doing same calculations multiple times per frame would only lead to worse performance and no actual benefit.
Smooth camera: only need to run once per frame, since that’s how fast actual camera is rendered.
Projectiles: still only need to update once per frame, since you would still have to wait until the next physics/network update.
It wouldn’t even work for waiting X amount of time, since just like for projectiles, you have to wait until the next update.

2 Likes

Odd, ROBLOX staff specifically stated that Physics at the very least runs at 240hz, although that was 3 years ago, but I understand your other points, I’m an amateur scripter so I don’t know too much, I just thought it would be somewhat beneficial to help developers break past the 1/60 mark.

Yes, it’s true that physics run at 240 Hz, or 240 times per second. However, it’s important to know when it all happens. If you open Physics stats window (Shift + F4, or Ctrl + Shift + F4 in studio), you would indeed find something like this: Phys. SimRate: Fixed240Hz. However, when you look at the FPS part, it would show you that Physics are actually running at the rate of about 60.0/s.

So what is going on? Why does Roblox staff say that physics run 240 times per second, but it clearly shows it running only 60 times per second?
Turns out, both of these are correct. If you open the microprofiler (Ctrl + F6), then pause it at any moment (Ctrl + P), you would see the breakdown of every frame. And if you zoom in and look really closely, you would find something like this:


And you would see 4 occurrences of worldStep.This means that physics calculations actually run 4 times per frame one after another, and at the rate of 60 frames per second you would get 240 calculations per second.
And if you look around a bit more, you would notice 2 more things: RunService.Stepped, which runs before physics, and RunService.Heartbeat, which runs after all those 4 calculations.

Conclusion: just treat physics as running once per frame, or 60 times per second (in ideal conditions).

5 Likes

Interesting find! Pretty cool, not sure how much I could use it but still a cool find!

Thank you so much for taking the time to explain this, this clears things up. I don’t know if anyone tells you this but you sound like an amazing programmer.

This is very important for multithreading and you explained it really well too.

This is one of these plug-ins that is an amazing and original idea…I have no idea how I could use this though.

Does anyone know how to use this is a game?

Can you explain to me why you would want to do this instead of using task.wait()?

If I recall correctly, task.wait() waits a minimum of 1/60 seconds, and yes although this wait time covers what most people need there may be some who want to wait 1/120th of a second, or 3/120th of a second, or run instructions “between the frames”, which is as easy as doing this:

for i = 1,#OfFrames do
NumberValueHere.Changed:wait()
end
1 Like

While I doubt this will be used much, it’s great to see that we now have this workaround for the people that do want/need that extra functionality. I still hate that wait() isn’t as optimised as it could be.

This is incorrect.

1 Like

Wow, seriously? I had no idea, thanks for sharing this.

1 Like

Thanks for summoning me: Would not recommend this.

You only get renders and user input at 60 FPS, so anything you do at a rate higher than that won’t do much to help you.

You could argue “but I want to run custom physics simulation at a higher rate than that”… well, since the inputs aren’t changing at a rate higher than 60 FPS, doing more physics solver steps at 60 FPS is basically the same as doing less solver steps at 120 FPS. And in fact, the 60 FPS approach will probably yield better results because with the 120 FPS approach you’ll have less even step sizes (alternating back and forth between a short step and a long one) which will give you less clean simulation.

7 Likes

Ah, I see, thanks for explaining, should I kill the thread or keep it here?

Doesn’t hurt to have up because it probably will lead people to a better understanding of the scheduling / frame structure than they had even if they don’t use it.

3 Likes