Lesson 6 of 10

A coroutine scheduler

Goal

Pause with yield and continue with resume

01

Explanation

A cutscene in a game is a series of steps with waits in between: the guard speaks, two seconds later he speaks again, and then the door opens. If you write it with timers, it gets chopped into scattered functions plus variables that remember “where we were”. A coroutine, on the other hand, is a function that pauses in the middle with coroutine.yield and later carries on from the same line with coroutine.resume, so you write the scene from top to bottom, the way it reads.

A coroutine needs someone to wake it up, and that's the job of the scheduler. It remembers when each task should wake up, and on every frame it resumes the tasks whose time has come and removes every task whose coroutine.status has become "dead". Citizen.Wait in FiveM and task.wait in Roblox are built on this idea.

Note that when an error happens inside the coroutine, coroutine.resume doesn't throw it. Instead it returns false along with the error message, so if you ignore the first value, you'll see the scene stop halfway without any message, and you won't know where to look.

02

Your task

Complete wait(seconds) so it gives the scheduler the length of the pause through coroutine.yield, Scheduler:spawn(fn) so it adds a task to tasks that starts on the first update and not before, and Scheduler:update(now) so it resumes every task whose time has come, records when it should wake up, and removes finished tasks. If a task throws an error, print its message with print, remove the task, and let the other tasks carry on.

Checks

6 checks
  1. A task starts on the first update, not before
  2. The wait function pauses the task until its time comes
  3. A finished task is removed
  4. Each task resumes at its own time
  5. One task's error doesn't stop the other tasks
  6. The error message is printed, not lost
main.lua
OutputLua 5.4 (wasmoon)

Loading Lua.

–/6

Checks start once the environment is ready.

6 checks listed under “Your task”.