Scheduling
The scheduler answers two different questions:
- when should this code run? — next frame, every ten ticks, after a delay;
- how will it stop? — explicitly with
Cancel()or together with a feature scope.
Import it from the runtime where the work belongs. Client scheduling follows rendered frames; Reflex scheduling follows server simulation ticks.
Minimal examples
Section titled “Minimal examples”import { scheduler } from "@killscript/sdk/client";
// Every client frame.const frame = scheduler.frame(updateCamera);
// Approximately twice per second.const interval = scheduler.every(0.5, updateHud);
// Once, after 10 game ticks.const delayed = scheduler.afterTicks(10, showReadyState);
frame.Cancel();interval.Cancel();delayed.Cancel();In Reflex, import from @killscript/sdk/server and use scheduler.tick() in
place of frame().
Choosing the right method
Section titled “Choosing the right method”| Method | Use it for | Stops how |
|---|---|---|
frame(callback) | Camera, HUD and client input updates | Cancel() |
tick(callback) | Reflex simulation checks | Cancel() |
after(seconds, callback) | A simple native one-shot delay | Cannot be cancelled |
afterTicks(ticks, callback) | A cancellable tick-based deadline | Automatically or Cancel() |
every(seconds, callback) | A lightweight repeated task | Cancel() |
everyTicks(ticks, callback) | A repeated simulation task | Cancel() |
until(predicate, callback) | Wait until state becomes available | Automatically or Cancel() |
debounce(key, seconds, callback) | Run only after calls stop arriving | Replaced by the next call with the same key |
throttle(key, seconds, callback) | Allow at most one call per interval | Returns whether it ran |
every() does not try to replay missed calls after a slow frame. It schedules
the next run from the time the current run is observed, which is usually the
right behavior for UI refreshes and periodic scans.
Wait for game state
Section titled “Wait for game state”Objects such as the local agent may not exist during module initialization.
until() avoids a permanent frame loop for this one-time wait:
const waitForPlayer = scheduler.until( () => Agents.GetLocalAgent() !== undefined, () => initializeForPlayer(Agents.GetLocalAgent()!),);The returned subscription can still be cancelled if the owning feature is disabled before the player appears.
Debounce and throttle
Section titled “Debounce and throttle”Debounce is useful when an expensive refresh should happen once after a burst of changes:
function settingsChanged(): void { scheduler.debounce("settings:rebuild-hud", 0.2, rebuildHud);}debounce() does not return a subscription. A newer call with the same key
invalidates the pending callback, but a feature scope cannot cancel it
directly. Keep the callback harmless when its owning feature is no longer
active.
Throttle runs immediately, then rejects calls until the interval expires:
function reportPosition(): void { scheduler.throttle("debug:position", 1, () => { print(`${Agents.GetLocalAgent()?.Movement.Position}`); });}Keys are shared inside the generated client or server bundle. Prefix generic keys with a feature name so unrelated files do not suppress one another.