What is an optimized alternative to "while true do" loops?

Question is in title.

Yes, it’s probably a stupid question, but I want to become better at ROBLOX game development by switching from these infinitely lagging behemoths to a better alternative if one exists.

Thanks for any suggestions.

2 Likes

It depends on the situation, but I will replace true with wait(x) because it will wait(x) and run the inside of the loop. I also sometimes use

local x = 1
repeat
    wait(.1)
    x = x + 1
until x >= 100
print(x) --> 100 or something

I like to use RunService because I can connect and disconnect the loops where I want so I have more control over them.

Ex:

local RunService = game:GetService("RunService")
local connectionTable = {}

connectionTable.connectionLoop = RunService.Heartbeat:Connect(function(step)
  --while loop code here

end)

--When shutting down the loop
connectionTable.connectionLoop:Disconnect()

--Shutting down all loops in a table
for _, connection in pairs(connectionTable) do
  connection:Disconnect()
end

Using while loops (especially while true do) is pretty chaotic coding and has a ton of potential to cause bugs in your game. Also do task.wait() instead of just wait(). It’s the new version of it

6 Likes

Normally I use RunService.Heartbeat (Server) and RunService.RenderStepped (Client)

local runService = game:GetService("RunService")
runService.Heartbeat:Connect(function()
   --do whatever
end)

You don’t need to add a task.wait() to the code above, it kind of does that automatically based on my experience with it.

https://developer.roblox.com/en-us/api-reference/event/RunService/Heartbeat
https://developer.roblox.com/en-us/api-reference/event/RunService/RenderStepped

3 Likes

Use Task Scheduler to find out when you should use what. I’v used Heartbeat on the client and it’s not server specific

2 Likes

Okay, I’m seeing a lot of good answers for per-frame or per-game tick loops, and I can definitely see the value in them if you want to run a script at a constant speed that can dynamically keep up with the server so that games can run smoothly.

However, is there an alternative available if you want to do something like, say, execute code every X amount of seconds instead of per-frame code execution?

For the most part you want to avoid using loops which run forever, if possible either make code run in response to fired events or create loops which have breaking points (loops with conditions which when satisfied cause the loop to terminate).

I can understand where you’re coming from. Though, from where I’m standing, if you were to do that, you may still have to do something like this:

local MyEvent = workspace.Event

MyEvent.Event:Connect(function()
--<some code here....>
end))

And then to fire the event:

while wait(x) do
   workspace.Event:Fire()
end

From my understanding, RunService.Heartbeat() would work here as well (via the deltaTime property), but is there a better alternative?

EDIT: Post I was replying to got removed.

“From my understanding, RunService.Heartbeat() would work here as well (via the deltaTime property), but is there a better alternative?”

You are correct, but I’m not sure how this answers my question (blockquoted above). I don’t intend to be rude, I’m just asking for help from the community in the nicest way I can think of.

They don’t lag and it’s probably the most efficient thing you can use. It’s what you do in them that determines if it lags or not. Every “looping” method has their own use case.While loops and repeat loops are actually different. Repeat loops run code then check conditionals, while loops check conditionals then it runs code:

while false do
    print("foo") -- doesn't print
end
repeat
    print("bar") -- prints
until true

This also applies to every other loop.

Yes

--Interval is to execute code every X amount of seconds instead of per-frame code execution
local interval = 0.1
local start = tick()
local nextStep = start+interval
local iter = 1

connectionTable.connectionLoop = RunService.Heartbeat:Connect(function(dt)
    if(tick() >= nextStep)then
        iter = iter+1
        nextStep = start + (iter * interval)

        --while loop code here
    end
end)
6 Likes

Also just a reminder, the decision to use Heartbeat or Renderstep does not rely on if it’s being run on the client/server. Task Scheduler explains when to use each case. As an example, yesterday I used a Heartbeat on the client to check the magnitude between a player and a part when they enter a zone in the game.


1 Like

Thanks for the extra info, I’ll be sure to put it to good use. Hopefully this can help me with all sorts of game optimization from here on out.

1 Like