Skip to content

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.

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": "" }]
}
]
}
}
}

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, plus Script, LocalScript and ModuleScript. 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.

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 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 ModuleScript
ReplicatedStorage/
Config.ts a ModuleScript
ServerScriptService/
Main.server.ts a Script
Rounds/ a Script with children:
_.server.ts the Rounds script's own source
Timer.ts a ModuleScript inside it
StarterGui/
Hud/
_.json { "class": "ScreenGui" }
Update.client.ts a LocalScript
StarterPlayer/
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.ts files are ignored. Other files that aren’t .ts or .json are 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 becomes Part ~2.json with "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, .swp or ~; reserved device names such as con): get a ~2 variant.

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 $.