Project format
A Rally game you edit is a project: the game’s settings plus its world, with every script’s
TypeScript source inside the world. Rally Studio saves your draft as a project, AI tools create
objects in the same world format, and the upcoming rally command-line tool
will store a project as a folder of files that mirrors the game’s tree. This page describes all
three.
The project document
Section titled “The project document”A project is one JSON document:
| Field | Value |
|---|---|
format |
Always "rally-project/1". |
name |
The game’s name, 1 to 80 characters. |
dimension |
"3d" or "2d". |
maxPlayers |
Players per server, 1 to 100. |
world |
The game’s world, described below. |
engine |
The engine version the project was saved with. |
{ "format": "rally-project/1", "name": "Door Game", "dimension": "3d", "maxPlayers": 20, "engine": "0.1.0", "world": { "lighting": { "skyColor": "#8ec5ff" }, "workspace": { "children": [ { "class": "SpawnLocation", "name": "Spawn", "position": [0, 0.5, 0] }, { "class": "Part", "name": "Door", "position": [0, 4, -10], "size": [6, 8, 1], "color": "#8b5a2b", "attributes": { "locked": true }, "children": [ { "class": "Script", "name": "Open", "source": "import { script } from '@rally/sdk';\n" } ] } ] }, "replicatedStorage": { "children": [{ "class": "RemoteEvent", "name": "Knock" }] }, "starterPlayer": { "characterWalkSpeed": 18, "children": [ { "class": "StarterPlayerScripts", "children": [{ "class": "LocalScript", "name": "Camera", "source": "" }] } ] } }}The world
Section titled “The world”world has one section per service, each optional: workspace,
lighting, players, replicatedStorage, serverStorage, serverScriptService, starterGui
and starterPlayer. Any other section is an error. A section holds the service’s own properties,
plus children: the objects inside it.
Each object is a JSON object with:
class: its class name. Any class scripts can create, plusScript,LocalScriptandModuleScript. Players, characters, cameras and PlayerGuis are never stored.name(optional): defaults to the class name.- Any of the class’s properties. Properties left out keep their defaults, and Rally writes only the properties that differ from them. An unknown property is an error.
children(optional): the objects inside it, in order.attributes(optional): an object of attribute names to values: strings, numbers and booleans as is, and vectors and colors tagged, since an attribute has no type to go by:{ "$v3": [x, y, z] },{ "$v2": [x, y] },{ "$c3": 2915069 }(the color as a number,0x2c7afd).
Property values are JSON:
| Property type | Stored as |
|---|---|
number, string, boolean |
As is. |
Vector3 |
[x, y, z] |
Vector2 |
[x, y] |
Color3 |
"#rrggbb" |
| An enum | Its string, such as "neon". |
An instance (Model.primaryPart, ObjectValue.value, a constraint’s part0) |
A path of names separated by /, relative to the object itself or to its parent: "Body", "Wheels/Front". Leading .. go up from the object, like folders: ".." is its parent, and "../../Workspace/Door" reaches the Door from a value in ReplicatedStorage. A reference to something that isn’t in the game isn’t saved. |
Lists and records (Animation.tracks, Terrain.heights) |
As JSON. |
Scripts are objects of class Script, LocalScript or ModuleScript whose source is their
TypeScript code; Scripts and LocalScripts can also set enabled. The starterPlayer section’s
LocalScripts that every player runs go inside a child node of class StarterPlayerScripts,
without a name.
Objects whose archivable is false aren’t saved.
Scripts and imports
Section titled “Scripts and imports”A script imports the game API from @rally/sdk, and ModuleScripts either by their tree path
(@game/ReplicatedStorage/Config) or relative to the importing script’s parent (./DoorLogic for
a ModuleScript next to the script). Nothing else can be imported. Because tree paths use /,
object names can’t contain one. See ModuleScript.
The file layout
Section titled “The file layout”The rally command-line tool (coming soon) stores a project’s world as a folder of files, one
file per object, so you can edit scripts in your own editor and keep the game in version control.
The project’s settings (name, dimension, players per server) are kept next to the folder.
Each top-level folder is a service: Workspace, Lighting, Players, ReplicatedStorage,
ServerStorage, ServerScriptService, StarterGui and StarterPlayer, whose
StarterPlayerScripts folder holds the LocalScripts every player runs.
Workspace/ _.json the service's own properties, such as { "gravity": 100 } Baseplate.json { "class": "Part", "size": [64, 1, 64] } House/ an object with children is a folder… _.json …and its _.json holds its class and properties Door/ _.json { "class": "Part" } Open.server.ts a Script inside the Door part Open.meta.json the script's other properties: { "enabled": false } DoorLogic.ts a ModuleScriptReplicatedStorage/ Config.ts a ModuleScriptServerScriptService/ Main.server.ts a Script Rounds/ a Script with children: _.server.ts the Rounds script's own source Timer.ts a ModuleScript inside itStarterGui/ Hud/ _.json { "class": "ScreenGui" } Update.client.ts a LocalScriptStarterPlayer/ StarterPlayerScripts/ Camera.client.ts a LocalScript| File | Object |
|---|---|
Name.server.ts |
A Script. The file is its source. |
Name.client.ts |
A LocalScript. |
Name.ts |
A ModuleScript. |
Name.meta.json |
The other properties of the script Name, such as enabled and attributes. |
Name.json |
An object without children: { "class": "Part", … }. Without "class" it’s a Folder. |
Name/ |
An object with children: a Folder, unless its _.json names another class. |
Name/_.json |
The folder object’s class and properties. |
Name/_.server.ts, _.client.ts, _.ts |
Makes the folder a Script, LocalScript or ModuleScript with children; this file is its source and _.json holds its other properties. |
Service/_.json |
A service’s properties. A service’s class, name and attributes can’t change. |
- A script’s file is its source, byte for byte; an empty file is an empty script.
- JSON files use the world format above.
"class"can’t be set on a script (its file extension decides it) or on a service. - Adding a file adds an object, deleting it deletes the object, and moving it moves the object.
- Hidden files, editor backups (names ending in
~or.swp) and.d.tsfiles are ignored. Other files that aren’t.tsor.jsonare skipped with a warning.
A file is named after its object. When a name can’t be used as a file name, the file gets
another name and its JSON (the object’s .json, its _.json or the script’s .meta.json)
records the real one in "name":
- Siblings with the same name, ignoring case: the first keeps
Part.json, the next becomesPart ~2.jsonwith"name": "Part". - Characters some systems don’t allow in file names (
< > : " | ? *), a leading., or a trailing.or space: replaced with_. - Names that would read back as something else (
_; names ending in.server,.client,.meta,.ts,.json,.d,.swpor~; reserved device names such ascon): get a~2variant.
Names that can’t be file names at all (empty, ., .., or containing / or \) are errors:
rename the object in Rally Studio first. Any JSON file can set "name", so an object can also
have a name its file can’t.
Children are read in file-name order. When a folder’s children are in another order in the game,
its _.json lists them in "$order": file names without extensions. Objects that aren’t listed
come after the listed ones. "$order" is the only key that starts with $.