Scheduling Code

Scheduling code is useful in many situations, such as ensuring code executes after a specific action or cycle has completed, or delaying code for a specific duration of time. You can use the task library to optimize Roblox's Task Scheduler to manage and schedule code. You can also use a similar library called coroutine to schedule code which has some additional functionality.

Common Methods

The following are the most common task methods used to schedule code. You should use the task methods over legacy scheduling methods, such as wait(), to ensure that your code runs optimally.

The following table lists the relevant legacy global methods and their preferred, more optimized counterparts:

Legacy Global MethodsTask MethodsAdditional Alternatives
wait()task.wait()RunService.Heartbeat
wait(n)task.wait(n)
spawn(f)task.defer(f)task.delay(0, f)
delay(n, f)task.delay(n, f)
spawn(function () f(uv1, ...) end)task.defer(f, uv1, ...)task.delay(0, f, uv1, ...)
delay(n, function () f(uv1, ...) end)task.delay(n, f, uv1, ...)

task.spawn

task.spawn() takes a thread or function and resumes it immediately through the engine's scheduler. Additional arguments are passed to the thread or function being resumed.

The following code sample is an example of how you can use task.spawn() when calling a function that may yield while iterating over a set of objects:


local function playerAdded(player)
...
(yield)
end
for _, player in Players:GetPlayers() do
task.spawn(playerAdded, player)
end

task.defer

task.defer() takes a thread or function and defers it until the next resumption cycle at which point it is resumed with the engine's scheduler. Additional arguments are passed to the thread or function resuming.

You should typically use this when you want similar behavior to task.spawn() but don't care about the thread running immediately. The following code sample illustrates how the print() statement for "A" will defer until after the print() statement for "B" executes:


task.defer(print, "A")
print("B")
--> B
--> A

task.delay

task.delay() takes a thread or function and schedules it for resumption after the given amount of time elapses on the next Heartbeat step. The thread resumes with built-in error handling and support for other engine features. Any additional arguments are passed to the thread or function resuming.

Since the actual delay time may vary, the following code sample illustrates how you can calculate it by passing the current time as an argument:


task.delay(2, function (scheduledTime)
print(os.clock() - scheduledTime) --> 2.038702
end, os.clock())

A duration of zero will result in the thread or function resuming on the next step.

task.wait

task.wait() yields the current thread until the given duration (in seconds) elapses and then resumes the thread on the next Heartbeat step.

The actual yield time may vary. The following code sample illustrates how this method returns it for convenience:

Since the actual delay time may vary, the following code sample illustrates how you can get the actual time by storing the method's return value:


local elapsedTime = task.wait(2) -- wait for 2 seconds
print(elapsedTime) --> 2.0792941

If no duration is given the duration will default to zero meaning the thread will automatically resume on the next step. This means task.wait() is equivalent in behavior to RunService.Heartbeat.