Skip to content

Globals

Everything a game script imports from @rally/sdk: the game’s services, the scheduler, value types, helper functions and every class.

Every script imports what it uses from @rally/sdk:

import { Players, Vector3, createLeaderstats, task, workspace } from '@rally/sdk';

Scripts can also import ModuleScripts from the game, by path (@game/ReplicatedStorage/Config) or relative to the script (./DoorLogic). See ModuleScript.

Game scripts run in a sandbox, on the game server or on a player’s device, so a few things you may know from other JavaScript environments aren’t there:

  • No timers (setTimeout, setInterval): use task and RunService, which run on game time.
  • No network requests (fetch, XMLHttpRequest, WebSockets): talk between the server and players with RemoteEvent and RemoteFunction, and save data with DataStoreService.
  • No web page (window, document, storage) and no Node.js APIs.
  • No top-level await: each script runs as a plain function. Wrap asynchronous code in task.spawn(async () => { … }), or use an async event handler.

JavaScript’s built-ins (Math, JSON, Date, Map, Promise and the rest) work as usual. console.log, console.warn and console.error write to the game’s output like print and warn.

Type: DataModel

The root of the game tree (a DataModel). game.getService('Players') also works.

Type: Workspace

The world: every part, model and character that exists physically lives under it.

Type: Players

Everyone in the game. Players.playerAdded, Players.getPlayers(), Players.localPlayer.

Type: Lighting

Sky, sun, ambient light and fog.

Type: ReplicatedStorage

Visible to the server and every client: put RemoteEvents and shared templates here.

Type: ServerStorage

Server-only storage: templates and secrets clients must never see.

Type: ServerScriptService

Where server scripts live (never sent to clients).

Type: StarterGui

UI copied into each player’s PlayerGui when they join.

Type: StarterPlayer

Character defaults (walk speed, jump power, health) and the client scripts every player runs.

Type: Script

The Script (on the server) or LocalScript (on a player’s device) running this code. A script inside a part can reach the part with script.parent.

Type: task

Game-time scheduling. await task.wait(1), task.delay(2, fn), task.spawn(async () => …). Pausing the game pauses every wait.

Type: RunService

heartbeat (after physics), stepped (before physics), renderStepped (client frames).

Type: TweenService

Animates properties: TweenService.create(part, { time: 2 }, { position }).play().

Type: UserInputService

Keyboard and mouse input on the player’s device: inputBegan, inputEnded, isKeyDown('KeyW'). On the server it exists but never fires.

Type: DataStoreService

Saved data: getDataStore(name), and getOrderedDataStore(name) for leaderboards. Server only: on players’ devices every method throws.

Type: HttpService

generateGuid(), jsonEncode(value) and jsonDecode(text). Games can’t make web requests.

Type: Debris

Removes objects later: Debris.addItem(ball, 4). Unlike task.delay, it still happens if this script stops or its code changes first.

Type: Live

Build live: state that survives code changes. Live.onSwap(() => ({ round })) hands state to this script’s next version, which reads it as Live.carried. Outside build sessions Live.building is false, handlers never run and Live.carried is undefined.

Type: Record<Easing, (t: number) => number>

The easing curves tweens and animations use, by name: each takes a progress from 0 to 1 and returns the eased value (easings.quadOut(0.5)). See Easing.

Type: (...args: unknown[]) => void

Writes a line to the game’s output: Rally Studio’s Output panel while you test, and the in-game developer console (open it with the backtick key). Arguments are joined with spaces; instances print as their path (Workspace.Map.Door), value types as text (Vector3(0, 5, 0)) and other values as JSON. In a published game, only the game’s owner sees output from server scripts.

Type: (...args: unknown[]) => void

Like print, as a warning.

Type: Vector3

Immutable 3D vector: new Vector3(0, 5, 0).add(Vector3.up.mul(2)).

Type: Vector2

Immutable 2D vector (UI positions and sizes).

Type: Color3

RGB color, channels 0–1: Color3.fromHex('#ff5a5f'), Color3.fromRGB(255, 90, 95).

Type: Quaternion

A rotation as a unit quaternion, for rotation math. Parts store rotation as Euler angles in degrees; convert with Quaternion.fromEulerDegrees and toEulerDegrees.

getChild<T extends Instance>(parent: Instance, name: string, cls: Class<T>): T

The child of parent called name, checked to be a cls and typed as one. Throws a readable error if it’s missing or of another class. Use it for objects your world always has: on players’ devices, everything that was in the game when the player joined is there before LocalScripts start. For anything created later, use waitForChild.

import { RemoteEvent, ReplicatedStorage, getChild } from '@rally/sdk';
const cheer = getChild(ReplicatedStorage, 'Cheer', RemoteEvent); // typed as a RemoteEvent
cheer.fireAllClients('Hooray!');
waitForChild<T extends Instance>(parent: Instance, name: string, cls: Class<T>, timeoutSeconds?: number): Promise<T>

Waits until parent has a child called name, then resolves with it, typed as cls. Rejects after timeoutSeconds (game time), if given, or if the child has another class. On players’ devices, replicated objects arrive over time, so client code should wait rather than assume.

import { Folder, NumberValue, print, task, waitForChild, waitForLocalPlayer } from '@rally/sdk';
task.spawn(async () => {
const me = await waitForLocalPlayer();
const stats = await waitForChild(me, 'leaderstats', Folder);
const coins = await waitForChild(stats, 'Coins', NumberValue);
coins.getPropertyChangedSignal('value').connect(() => print(`Coins: ${coins.value}`));
});
waitForLocalPlayer(): Promise<Player>

On a player’s device: resolves with that player’s Player. Use it in LocalScripts before reading Players.localPlayer.

createLeaderstats<K extends string>(player: Player, initial: Record<K, number>): Record<K, NumberValue>

Server: gives player a leaderstats folder with one NumberValue per entry, and returns the values by name so you can change them. Values in a player’s leaderstats folder show on the in-game leaderboard.

import { Players, createLeaderstats } from '@rally/sdk';
Players.playerAdded.connect((player) => {
const stats = createLeaderstats(player, { Coins: 0, Wins: 0 });
stats.Coins.value += 10;
});

These classes are exported by name, as values (for new and instanceof) and as types: Instance, Folder, BasePart, Part, MeshPart, SpawnLocation, Model, PointLight, Sound, Terrain, Animation, Constraint, WeldConstraint, HingeConstraint, SpringConstraint, RopeConstraint, NumberValue, StringValue, BoolValue, ObjectValue, RemoteEvent, RemoteFunction, BindableEvent, ScreenGui, GuiObject, Frame, TextLabel, TextButton, TextBox, ImageLabel, Behavior, MovingBehavior, Spinner, Mover, Floater, ColorCycle, Hazard, Checkpoint, Teleporter, JumpPad, SpeedPad, Collectible, Goal, Door, Trigger, Spawner, Chaser, Leaderstat, RoundTimer, Character, Player, PlayerGui, Camera, Script, LocalScript, ModuleScript.

@rally/sdk also exports api, the object the exports above are read from; use the named exports instead. Types that have no value are exported for annotations: Material, PartShape, TerrainMaterial, SculptMode, Easing, CameraType, CharacterState, Dimension, TweenInfo, RaycastOptions, RaycastResult, InputObject, AnimationTrack, AnimationKey, TerrainStroke, TerrainPaintStroke, DataValue, AttributeValue, Signal, Connection, Tween, DataStore, OrderedDataStore, the service types (TaskLibrary, RunService, TweenService, UserInputService, DataStoreService, HttpService, DataModel, Workspace, Players and the other services) and RallyApi.