While loop vs Run Service loops

So basically I just found something I can’t really understand.

So for example you have a loop like this:

while true do 
	wait(5)
	print("test")
end

Now this works exactly how I would imagine. It waits 5 seconds and then prints “test”, then it waits 5 seconds again and prints “test” and so on.


But now let’s say you have a loop like this:

game:GetService("RunService").Stepped:Connect(function()
	wait(5)
	print("test")
end)

This loop for some reason, which I don’t understand, just keeps printing “test” without even bothering to wait those 5 seconds.

I also tried .Heartbeat and it’s the exact same.

So my question is why the second loop ignores the wait() completely?

1 Like

Every frame, you’re asking it to wait 5 seconds then print test. So every frame, another wait starts. After 5 seconds, it prints test. Then the next frame, another wait finishes and prints test.

It runs so fast that basically it doesnt even see the wait persay

It ignores the wait because it is an event, it runs everything the condition for the event to happen it met, in the case of heartbeat, physics have been calculated and so it runs the event, and once another event happens, it’ll run that code separately, unlike a while loop which respects waits,

You need to debounce the event to make it work like a while loop, respecting waits and what not

4 Likes

I use a

while wait() do
print ("hi")
end

loop. It will run every line of code n the amount of time your wait() was set. say I typed wait(2)
Every 2 seconds, it would print “hi”,.

You should probably stop using wait()

1 Like

I’ll just copy and paste my response to a similar topic:

Is Run Service heartbeat a better choice to use than a loop in terms of performance and efficieny though?

No, it’s not ignoring the wait(5) at all. A place with this script will have nothing print out for the first 5 seconds, then it will suddenly start printing every frame. Stepped fires about 60 times per second, and each time, it’s waiting 5 seconds and then printing “test” when the thread resumes. If you’re not convinced it’s not being ignored, change the wait(5) to wait(60) and notice that you’ll have no output for the first whole minute, then “test” printing at 60fps after 1 minute.

The Heartbeat version of a once-every-5-seconds tick looks like this:

local elapsed = 0
game:GetService("RunService").Heartbeat:Connect(function(dt)
    elapsed += dt
    while elapsed >= 5 do
        elapsed -= 5
        print("test")
    end
end)

When the delay is this long, you don’t need it to be a while loop, it can just be an if elapsed >= 5 then, but I gave you the general format that works for any delay duration, even sub-frame timings.