Skip to content

task

Game-time scheduling: wait, delay, defer and spawn work without timers.

  • Get it: import { task } from '@rally/sdk'

Game time moves only when the game steps: 30 times a second on the game server, once per frame on players’ devices. Pausing or stopping the game pauses every wait with it. There are no setTimeout or setInterval in game scripts; use task instead.

Errors thrown by functions run through task (including rejected promises from async functions) are written to the game’s output instead of stopping the script.

wait(seconds?: number): Promise<number>

Resolves after seconds (default: the next step) with the time actually waited.

On the game server, steps are 1/30 of a second apart, so even a short wait lasts at least that long there.

spawn<A extends unknown[]>(fn: (...args: A) => unknown, ...args: A): void

Runs fn now; errors are reported, not thrown.

Use it for loops and for anything that awaits: scripts can’t use await at their top level.

delay<A extends unknown[]>(seconds: number, fn: (...args: A) => unknown, ...args: A): () => void

Runs fn after seconds. Returns a cancel function.

defer<A extends unknown[]>(fn: (...args: A) => unknown, ...args: A): void

Runs fn on the next step.

time(): number

Seconds of game time since the game started.

import { print, task } from '@rally/sdk';
task.delay(3, () => print('three seconds later'));
task.defer(() => print('next step'));
task.spawn(async () => {
for (let i = 3; i > 0; i--) {
print(i);
await task.wait(1);
}
print('go!', task.time());
});
import { Part, getChild, task, workspace } from '@rally/sdk';
// A door that closes 5 seconds after the last time someone touched it.
const door = getChild(workspace, 'Door', Part);
let closeLater: (() => void) | undefined;
door.touched.connect(() => {
door.canCollide = false;
door.transparency = 0.7;
closeLater?.(); // touching it again restarts the countdown
closeLater = task.delay(5, () => {
door.canCollide = true;
door.transparency = 0;
});
});