For example, lets say I want to check the position of a player every 3 seconds (this is just an example, what is being executed is much more complex).
I could do something like this:
while true do
-- Perform check, do stuff.
task.wait(3)
end
Or, I could use RunService with a check:
local RunService = game:GetService("RunService")
RunService.Heartbeat:Connect(function(delta)
local now = tick()
if now - lastCheck >= 3 then
-- Perform check, do stuff.
end
end)
What system is more scalable? This will be done many times on the server by many different things. I am not sure if it is better to just have a heartbeat with checks for every object or a separate while loop for every object. What should have less load (if there is a difference)?
In terms of optimization, a while loop that yields would use the least amount of memory.
In terms of accuracy, both should be fairly precise, both being resumed by the scheduler on runtime.
In terms of scalability, I would say wrapping a loop in a thread would be the most straightforward. You can easily control when the logic yields (before, in-between or after), send arguments into it when spawning, and can instantly cancel, whilst connections may linger just one extra frame before stopping.
local function Loop(Arg1, Arg2)
while true do
print(Arg1, Arg2 + 1)
task.wait(1)
end
end
local Thread = task.spawn(Loop, "Hello", 5)
task.cancel(Thread)
Having individual loops would create multiple threads that would be running at the same time, which can lead to some nasty race conditions (What if one object’s loop wanted to get the state of another?)
Macro-managing a global loop may be better if what you are doing is meant to interact with its other elements, i.e., a global queue or custom physics handler. If what you are trying to achieve is meant to be self-contained, go ahead with making them separate, as handling them on a case-by-case basis may be easier.