Services
Services are the engine’s built-in systems. Some are objects at the top of the game tree, such as
workspace and Players. Others are libraries, such as task and TweenService. You import all
of them by name from @rally/sdk:
import { Players, RunService, task, TweenService, workspace } from '@rally/sdk';This page describes each one and its most useful members. The API reference has every member of every class.
At a glance
Section titled “At a glance”| Import | What it’s for | Works on |
|---|---|---|
game |
The root of the tree | both |
workspace |
The world: parts, gravity, raycasts | both |
Players |
Who’s playing: joins, leaves, characters | both |
Lighting |
Sky, sun, ambient light and fog | both |
ReplicatedStorage |
Objects both sides see: remotes, shared state | both |
ServerStorage |
Server-only objects: templates | server (empty on clients) |
ServerScriptService |
Server scripts | server (empty on clients) |
StarterGui |
UI copied to each player when they join | both |
StarterPlayer |
Defaults for new characters | both |
task |
Waiting and scheduling on game time | both |
RunService |
Per-step events, and which side the code runs on | both |
TweenService |
Smoothly animating properties | both |
UserInputService |
Keyboard, mouse and touch; the built-in controls | player’s device only |
DataStoreService |
Saving data between sessions | server only |
HttpService |
Unique ids and JSON | both |
easings |
Easing curves | both |
print, warn |
Writing to the output | both |
“Works on both” means the service exists on the server and on every player’s device. What it does there follows the usual rule: changes made on the server replicate to players, and changes made in a LocalScript stay on that player’s device.
Services in the tree
Section titled “Services in the tree”The first nine imports are objects in the game tree. game.getService finds the tree services by
class name too — game.getService('Players') is the same object as Players — but the libraries
below aren’t in the tree, so import them.
workspace
Section titled “workspace”The 3D or 2D world. Everything physical lives in it.
gravity— studs per second squared, downward. Default 196.2.fallenPartsDestroyHeight— unanchored parts that fall below this height are destroyed, and characters below it die. Default -500.dimension—'3d'or'2d', read-only. Set when the game was created.currentCamera— on a player’s device, the camera.nullon the server. See Input and camera.raycast(origin, direction, options?)— the first thing a ray hits, ornull. The length ofdirectionis how far the ray goes. Returns theinstanceit hit (a part, a character or terrain), theposition, the surfacenormaland thedistance. Options:ignore(instances the ray passes through) andhitCharacters(defaulttrue).getPartsInRadius(center, radius)— the parts that overlap a sphere.
import { print, task, Vector3, workspace } from '@rally/sdk';
task.spawn(async () => { await task.wait(); // physics queries see the world from the first step on // Straight down from high above the origin, ignoring characters: where's the ground? const hit = workspace.raycast(new Vector3(0, 100, 0), new Vector3(0, -200, 0), { hitCharacters: false, }); if (hit) print('ground at height', hit.position.y, 'on', hit.instance);});Physics covers raycasts, forces and constraints in depth.
Players
Section titled “Players”Everyone in this server.
playerAddedandplayerRemoving— fire when someone joins or leaves.getPlayers()— everyone here now.getPlayerByUserId(userId)— the player with that Rally account id, if they’re here.getPlayerFromCharacter(instance)— the player a character belongs to.localPlayer— on a player’s device, that player.nullon the server.maxPlayers— how many players fit in this server, read-only. It’s your game’s Max players per server setting.characterAutoLoads— whether characters spawn on their own when players join and after they die. Defaulttrue.respawnTime— seconds between a character dying and respawning. Default 3.
Players and characters covers all of it.
Lighting
Section titled “Lighting”How the world is lit. Changes on the server apply for everyone; changes in a LocalScript apply only on that player’s device — a darker sky while they’re in a cave, say.
skyColorandambient— the sky’s color and the light that fills shadows.brightness— the sun’s strength, 0 to 10. Default 1.6.sunDirection— the direction sunlight travels, as aVector3.fogColorandfogEnd— fog’s color, and the distance at which it’s total.fogEnd0 turns fog off.shadows— whether things cast shadows.
import { Color3, Lighting, task } from '@rally/sdk';
// Dusk falls over ten seconds.task.spawn(async () => { for (let i = 0; i <= 10; i++) { const t = i / 10; Lighting.skyColor = Color3.fromHex('#bfdcff').lerp(Color3.fromHex('#ff9b6b'), t); Lighting.brightness = 1.6 - t; await task.wait(1); }});For smooth changes, tween the properties instead.
ReplicatedStorage, ServerStorage and ServerScriptService
Section titled “ReplicatedStorage, ServerStorage and ServerScriptService”Containers, with no members of their own beyond what every instance has.
- ReplicatedStorage holds what both sides need:
RemoteEvents, shared state, templates both sides clone. - ServerStorage holds what only the server should have: templates to clone into the world, server-only ModuleScripts. On players’ devices it’s empty.
- ServerScriptService holds server Scripts. On players’ devices it’s empty.
How games are organized explains what goes in each.
StarterGui
Section titled “StarterGui”ScreenGuis here are copied into each player’s PlayerGui when they join. Changing StarterGui while
the game runs only affects players who join afterwards — to change a player’s UI, change their
PlayerGui. See User interface.
StarterPlayer
Section titled “StarterPlayer”Defaults that each new character gets when it spawns:
characterWalkSpeed— studs per second. Default 16.characterJumpPower— upward speed when jumping. Default 50.characterMaxHealth— Default 100.
Inside it, StarterPlayerScripts holds the LocalScripts that run on every player’s device;
game.getService('StarterPlayerScripts') finds it.
Libraries
Section titled “Libraries”Scheduling on game time. There’s no setTimeout or setInterval in scripts; use these:
task.wait(seconds?)— resolves aftersecondsof game time (or the next step), with the time actually waited. Use it withawait.task.delay(seconds, fn)— runsfnlater. Returns a function that cancels it.task.spawn(fn)— runsfnnow, and reports its errors instead of throwing them. The way to runasynccode from a script’s top level.task.defer(fn)— runsfnat the start of the next step.task.time()— seconds of game time since the game started.
Tasks and timing covers them in depth.
RunService
Section titled “RunService”Events that fire every step of the game, and where the code is running.
heartbeat— every step, after physics, with the step’s length in seconds. The usual place for per-step game logic.stepped— every step, before physics.renderStepped— on a player’s device only: every rendered frame, just before drawing. The place for camera and visual updates.isServer()andisClient()— which side this code is running on. In Studio’s Play, where the server and your device’s scripts run together in your browser, both aretrue.
TweenService
Section titled “TweenService”Animates properties smoothly from their current values to targets.
TweenService.create(instance, info, goals)returns aTween.goalsmaps property names to target values: numbers,Vector3,Vector2orColor3.info.time(seconds),info.easing(default'quadInOut'),info.repeatCount(extra plays; -1 repeats forever),info.reverses(play backwards after each play),info.delay(seconds before starting).- A
Tweenhasplay(),pause(),cancel(),playing, and acompletedevent.
import { getChild, Part, TweenService, Vector3, workspace } from '@rally/sdk';
// A platform that slides 20 studs and back, forever.const platform = getChild(workspace, 'Platform', Part);TweenService.create( platform, { time: 3, easing: 'sineInOut', reverses: true, repeatCount: -1 }, { position: platform.position.add(new Vector3(20, 0, 0)) },).play();Animation and tweens covers tweens and keyframe animations.
UserInputService
Section titled “UserInputService”Input on a player’s device. On the server it exists, but its events never fire.
inputBeganandinputEnded— a key or mouse button went down or up. Handlers get the input (kind,key,position) andgameProcessed, which istruewhen the UI used it.isKeyDown(key)— whether a key is held right now, such as'ShiftLeft'.mouseMoved,mouseLocationandmouseLocked— mouse movement and position, and whether the pointer is locked to the game.touchEnabled— whether the device has a touch screen;lastInputType—'touch'or'keyboardMouse', whichever the player used last.addTouchButton(key, label)/removeTouchButton(key)— on-screen buttons for touch players. Keys your scripts listen for get one automatically.viewportSizeandsafeAreaInsets— the game view’s size and the screen edges covered by a notch or home bar.defaultControls— set it tofalseto turn off the built-in movement and camera controls.
Input and camera covers input and the camera.
DataStoreService
Section titled “DataStoreService”Data that outlives a game server: progress, currencies, high scores. Server only — on players’ devices, every method throws.
getDataStore(name)— a store of JSON values by key, withget,set,update,incrementandremove. Every method returns a promise.getOrderedDataStore(name)— a store of numbers you can rank withgetSorted, for leaderboards.
import { DataStoreService, Players, print, warn } from '@rally/sdk';
const visits = DataStoreService.getDataStore('Visits');
Players.playerAdded.connect(async (player) => { try { const count = await visits.increment(player.userId); print(`${player.displayName} has visited ${count} times`); } catch (e) { warn('could not count the visit', e); }});Data stores covers saving, loading and leaderboards.
HttpService
Section titled “HttpService”Ids and JSON. Despite its name, it can’t make web requests: games don’t have network access.
generateGuid()— a new random unique id string.jsonEncode(value)andjsonDecode(text)— the same asJSON.stringifyandJSON.parse.
easings
Section titled “easings”The easing curves that tweens use: linear, quadIn, quadOut, quadInOut, cubicInOut,
sineInOut, backOut, bounceOut and elasticOut. Each is a function that takes progress from 0
to 1 and returns eased progress, which starts at 0 and ends at 1 (backOut and elasticOut
overshoot on the way). Use them to shape motion you drive yourself:
import { easings, getChild, Part, RunService, Vector3, workspace } from '@rally/sdk';
// Pop a part up 4 studs over half a second, overshooting a little at the end.const pad = getChild(workspace, 'Pad', Part);const start = pad.position;let t = 0;const connection = RunService.heartbeat.connect((dt) => { t = Math.min(1, t + dt / 0.5); pad.position = start.add(new Vector3(0, 4 * easings.backOut(t), 0)); if (t === 1) connection.disconnect();});print and warn
Section titled “print and warn”Write to the game’s output: Studio’s Output panel while you test, and the developer console in
the player. print logs normally and warn as a warning. Instances print as their path, like
Workspace.Map.Door. See Debugging.
Helpers
Section titled “Helpers”@rally/sdk also has four helpers for everyday jobs:
getChild(parent, name, Class)— the child calledname, typed asClass. Throws a readable error if it’s missing or another class.waitForChild(parent, name, Class, timeoutSeconds?)— waits until the child exists, then returns it typed asClass. Use it on players’ devices, where objects arrive over time.waitForLocalPlayer()— on a player’s device, resolves with theirPlayer.createLeaderstats(player, { Coins: 0, Wins: 0 })— on the server, gives a player aleaderstatsfolder with oneNumberValueper entry, shown in the in-game player list. Returns the values by name.
script and game
Section titled “script and game”scriptis the Script or LocalScript running the code. In a ModuleScript, it’s the script that imported the module. A Script inside a part usesscript.parentto get the part.gameis the root of the tree. BesidesgetService, it hasgetInstanceById(id), which finds an instance by itsid.
Next steps
Section titled “Next steps”- Events and signals — connect to the events these services fire.
- Tasks and timing —
taskandRunServicein depth. - API reference — every class, property, method and event.