Add task.loop for Spawning Interval Loops

Interval loops are common in game development, so a common pattern I do is spawning a while-loop as a thread with a passed function.

local function Loop(Time, Function, ...)
	while true do
		task.wait(Time)
		Function(...)
	end
end

task.spawn(Loop, 1, print, "Hello")

However, this is very boilerplate-y and could be implemented as a library function.

The Proposal

Add task.loop with the signiture <a..., b...>(duration: number, functionOrThread: (a...) -> b..., a...) -> thread.

It would spawn a single thread and execute it every duration in seconds, making it synonymous with the while-loop wrapper above.

task.loop(1, print, "Hello")
14 Likes

This would be great, since the alternative to task spawning while true loops is RunService events, which if you don’t time with deltaTime then you will execute your code every frame or physics tick and that’s bad when you are making AIs

2 Likes

why do you prefer doing that “task.loop” instead of doing regular loops

what is stopping you from just doing this???

task.spawn(function()
       while task.wait() do
           print("Hello")
       end
end)
1 Like

This is probably the reason task.loop isn’t added, it would be kinda extra

1 Like

Due to devforum moderation I will not answer the first one but I will answer the second one.

I agree it looks way cleaner but honestly I doubt that they would actually add task.loop into the engine if we already got RunService and second thing honestly they wont add it unless big developers like adopt me creator needs it. (im sorry but thats the truth)

I agree with this one and only because if you put bool value the loop will start earlier but only if you do your stuff before task.wait()

while true do
 --do something before task.wait
 task.wait()
end

You are wrong and correct with this one task.wait() returns number. Try this out yourself. Thats why the loop doesnt get broken. If task.wait() didnt return anything the loop would’nt be even running in first place.

local number=task.wait()
print(number)

I mean you can say that, but they literally have task.delay which is basically

task.delay(3, function()

end)

is the same as this

task.spawn(function()
 task.wait(3)

end)

It’s different though because the task isn’t created until that time has passed so you can cancel it before then

1 Like

i guess? but you can still cancel both the same regardless (they wont print lol)

You can cancel both but it still has performance implications

Then another issue with this is that the author showed how easy it would be to just make a function for this. task.delay is a different story because it doesn’t activate the function until that time passes but you can still cancel it before then.

Okay after seeing this I could see what you mean now.

Best idea ever, but
task.loop(1, print, "Hello")
wouldn’t work as print would be counted as an argument thingy hard to explain

yes it would, we have task.delay(1, print) that is pretty much the same parameters

Encouraging scripters to create infinite loops which do not self terminate, and then saying “it’s okay because they can always externally close the thread with task.cancel”, seems like a bad idea. I’d want a reliable means of aborting the loop.


Generally, when determining whether or not a new scripting feature is worth supporting, I feel it’s important to assess the impact it will have on the practices of scripters in aggregate. As it stands in this case, I’m just not convinced that impact will be a net positive. You ask ‘why wouldn’t we’–I’m concerned with ‘why would we’. Script architecture should primarily be event-driven. Creating infinite loops is usually seen as a last resort, as it tends to (though not necessarily) be indicative of wasteful design. If you’re implementing code similar to the proposed feature request, so often that you strongly feel it needs to be made an official addition to the task library, it’s perhaps worth evaluating whether or not your approach is efficacious to begin with.

I should add that I was careful to omit any technical reasoning as part of my initial response, as I didn’t want to derail the discussion with subjects better suited to engineers. But to be very clear, task.cancel is not infallible. If you want this to be implemented, and you want a viable means of terminating the threads it creates, then you really want two features.


I’m honestly not even entirely confident how to respond to this, because I feel it’s such a bad faith interpretation of my point. If there’s an event, please use it. Writing your own code, to do whatever the event already checks for, is wasteful. Hence my statement,

3 Likes

Personally I don’t use while true loops because you can achieve the same thing with a function, if not better

Sorry for the late reply, I was away for the week.

The entire point of this request is to create infinite interval loops which do not self-terminate and are handled externally. Its syntax-sugar for a common idiom in game logic, just like Rust’s loop.

1 Like

Just talk to the computer and say “COMPUTER, STOP THE LOOP NOW” and the loop should stop.
Ez fix done.

In all seriousness, what’s bad about having this as another option for infinite loops? You are not forced to use it

Every game runs on 1 main game loop, every single game. Even your “events” are just running inside a loop but executed when a condition is met. You do not understand programming

What is a genuine use case here that demands such a misuse-prone addition to the task library?

While yes, most processes run off of a main loop, events such as key presses and other user input are handled asynchronously through interrupts.

And yes, you can definitely use a loop to poll constantly for input, or any change, though it’s incredibly inefficient and a waste of CPU cycles. Events run independently of any sort of interval and can be computed immediately by the CPU. They are not fired when a “condition is met.”

Example

This is a loop that polls for user input and does something when it detects input.

while (true) do
    task.wait(0.1);
    if (isKeyDown(key)) then
        doSomething();
    end

Notice it will take at most 0.1s in order to read that the key has been pressed? Interrupts don’t have this problem and will execute any code that listens for events immediately.

Overall, as @AskWisp said, use events. They were made with the goal in mind to alleviate the need for infinitely running loops that poll constantly for input.

4 Likes