Docs
These docs are made to be read by both humans and AI. They are the same docs given to your AI when it runs!
Core Objects
Ball
A ball in the world.
| Field | Type | |
|---|---|---|
| id | ||
| type | 'ball' | |
| name | string | |
| material | BallMaterialSettings | null | Visual Material texture settings. |
| opacity | number | 0-1. |
| color | ||
| outline | OutlineEffect | null | |
| isAlwaysOnTop | boolean | Whether to render in front even if visually blocked. |
| radius | number | |
| location | ||
| movement | ||
| isWalkthrough | boolean | Whether this object can pass through other objects. |
| isAnchored | boolean | Whether this object is totally unmovable. |
| density | number |
Brick
A brick in the world.
| Field | Type | |
|---|---|---|
| id | ||
| type | 'brick' | |
| name | string | |
| material | BrickMaterialSettings | null | Visual Material texture settings. |
| opacity | number | 0-1. |
| color | ||
| outline | OutlineEffect | null | |
| isAlwaysOnTop | boolean | Whether to render in front even if visually blocked. |
| size | ||
| location | ||
| movement | ||
| isWalkthrough | boolean | Whether this object can pass through other objects. |
| isAnchored | boolean | Whether this object is totally unmovable. |
| density | number |
Cylinder
A cylinder in the world. Its symmetry axis is local Z.
| Field | Type | |
|---|---|---|
| id | ||
| type | 'cylinder' | |
| name | string | |
| material | CylinderMaterialSettings | null | Visual Material texture settings. |
| opacity | number | 0-1. |
| color | ||
| outline | OutlineEffect | null | |
| isAlwaysOnTop | boolean | Whether to render in front even if visually blocked. |
| radius | number | |
| length | number | |
| location | ||
| movement | ||
| isWalkthrough | boolean | Whether this object can pass through other objects. |
| isAnchored | boolean | Whether this object is totally unmovable. |
| density | number |
RigidGroup
A RigidGroup is a bunch of objects that move together. All Ball, Brick, and Cylinder child descendants are glued together and will move as one rigid body.
If you want to add animations, you must set followSkeletonId, use a JointAnimator to animate it, and add JointAttachment objects to glue objects to the joints. There are some AI tools to automate this.
Group
Use this as a Folder. There is no special behavior, it is simply for organization.
| Field | Type | |
|---|---|---|
| id | ||
| type | 'group' | |
| name | string |
Mesh
A mesh in the world.
To animate this mesh visually, you must set followSkeletonId and use a JointAnimator to animate it.
| Field | Type | |
|---|---|---|
| id | ||
| type | 'mesh' | |
| name | string | |
| scale | ||
| meshDataId | ||
| followSkeletonId | ObjectId | null | The objectId of the Skeleton that this mesh will visually follow. |
| physicalObjectId | ObjectId | null | The objectId of the Ball, Brick, Cylinder, or RigidGroup that the mesh will use as a collider and visually follow. |
| material | MeshMaterialSettings | null | Visual Material texture settings. |
| opacity | number | 0-1. |
| color | ||
| outline | OutlineEffect | null | |
| isAlwaysOnTop | boolean | Whether to render in front even if visually blocked. |
Animation Objects
Skeleton
Use skeletons to animate all your objects. Skeletons are just a collection of Joint objects, which are just locations + rotations in space that you can glue objects to in order to animate.
| Field | Type | |
|---|---|---|
| id | ||
| type | 'skeleton' | |
| name | string |
Joint
Joints must go inside a Skeleton or another Joint.
The bindPose is the initial reference location that movements in an animation (JointAnimation) are relative to.
| Field | Type | |
|---|---|---|
| id | ||
| type | 'joint' | |
| name | string | |
| bindPose | Relative to the parent. |
JointAttachment
Use JointAttachments to glue objects in a RigidGroup to a Joint. The objects will move physically with the joint, not just visually.
| Field | Type | |
|---|---|---|
| id | ||
| type | 'jointAttachment' | |
| name | string | |
| objectId | ObjectId | null | The objectId of the object to attach to the joint. |
| followJointName | string | |
| offsetFromJoint |
JointAnimator
Use this object to play an animation.
This makes a Skeleton move, based on a JointAnimation and a Clock. Multiple of these can point to the same skeleton; they blend their animations until weight reaches 100.
Start and stop an animation by saying _________
JointAnimation
This is how you define an animation. This object contains a JointKeyframe child for each frame in the animation. Those keyframe objects have a JointPose child that says how to offset each Joint relative to its bindPose.
You play this animation using a JointAnimator.
| Field | Type | |
|---|---|---|
| id | ||
| type | 'jointAnimation' | |
| name | string | |
| duration | number | |
| interpolationStyle |
JointKeyframe
A child of JointAnimation.
| Field | Type | |
|---|---|---|
| id | ||
| type | 'jointKeyframe' | |
| name | string | |
| time | number |
JointPose
A child of JointKeyframe.
| Field | Type | |
|---|---|---|
| id | ||
| type | 'jointPose' | |
| name | string | |
| jointName | string | |
| relativePose |
Other Objects
Clock
A clock is just an internal helper object that tells us how far along we are in an JointAnimator or Sound. Clock lives on the client. It can use either client time or estimated server time as its reference.
| Field | Type | |
|---|---|---|
| id | ||
| type | 'clock' | |
| name | string | |
| reference | ClockReference | null | The time reference at which the clock started, or null when it is paused. |
| shouldLoop | boolean | Whether it should loop when done. |
| speed | number | A multiplier onto the normal speed. |
Material
An image or "texture" that is shown on an object. Albedo is the main texture. The other fields are optional PBR properties.
| Field | Type | |
|---|---|---|
| id | ||
| type | 'material' | |
| name | string | |
| albedoTextureDataId | DataId | null | This is the main texture to place on the object. Four values (RGBA) per pixel. |
| metallicTextureDataId | DataId | null | Optional metallic information. One value per pixel. |
| roughnessTextureDataId | DataId | null | Optional roughness information. One value per pixel. |
| normalTextureDataId | DataId | null | Optional normal information. Three values (XYZ) per pixel. |
| alphaMode | Says how to handle the underlying object's transparency. Only relevant when albedoTextureDataId has transparency in it. |
Player
You can never create a Player object yourself. It is automatically created and deleted when a player joins and leaves. It is important for you to set the head and controls, or the player won't be able to see or move.
| Field | Type | |
|---|---|---|
| id | ||
| type | 'player' | |
| name | string | |
| username | string | |
| userid | string | |
| headObjectId | ObjectId | null | The objectId of the Ball, Brick, Cylinder, or RigidGroup the player's camera will follow. |
| controlsObjectId | ObjectId | null | The objectId of the Ball, Brick, Cylinder, or RigidGroup this player controls. Only one player can control this object at a time. If you set two to the same thing, the last one wins, and the previous one is cleared. |
| physicsControls | Physics constants used when the player moves. |
Script
Every Script is either a Server or Client script.
- Client scripts run on every client and can only do a limited set of things like show UI and play animations.
- Server scripts run on the server so can do elevated things like access storage and leaderboards.
Imports:
- Simply write
import { functionName } from './scriptName'to use scripts as modules. - You can use
setTimeout()andsetInterval(). Scripts expose all web APIs except fetch. - Scripts and their path names are set once, when the script is created.
Server-Client:
- You should communicate between the server and client by calling functions across the network.
- Write
'use server'at the top of a Server script to make all exports accessible to Client scripts. - Write
'use client'at the top of a Client script to make all exports accessible to Server scripts.- Exports should be async functions.
- The first argument to client functions must be the player's user id.
- You should validate server function inputs and client function return values.
UI:
- We expose React-like syntax to draw UI on the screen.
- You may only use <div>, text, arrays, null, className, onClick, and onHover primitive props on divs.
- You can use common Tailwind class names. Do not use style props or unsupported HTML tags.
useState()works like usual.createState()works for state that comes from outside react, eg for 'use client' functions. This is similar to useSyncExternalStore.- Write
createState(initialValue). The.get()function automatically subscribes the relevant React components to re-render when.set()is called.
- Write
Managing Objects:
- Only the server can create objects.
- With few exceptions, only the server can modify objects (exceptions: player locations, animation clocks, etc).
- All objects in the world are replicated to all users. You cannot create an object on just one client.
| Field | Type | |
|---|---|---|
| id | ||
| type | 'script' | |
| name | string | |
| objectLocation |
Sound
WorldLighting
Controls the whole world's sun, ambient lighting, sky color, and skybox. The sunOrientation points from the world toward the sun and uses degrees.
| Field | Type | |
|---|---|---|
| id | ||
| type | 'worldLighting' | |
| name | string | |
| sunOrientation | ||
| sunColor | ||
| sunIntensity | number | |
| ambientTopColor | ||
| ambientBottomColor | ||
| ambientIntensity | number | |
| skyColor | The background sky color behind the world. | |
| skyboxTextureDataId | DataId | null | An equirectangular skybox TextureData id. Transparent pixels reveal skyColor. |
| skyboxTextureOpacity | number | 0 means the skybox texture is hidden. 1 means the skybox texture is fully visible. |
Scripting
stopScript
Use await stopScript() to hang the script forever, so use it only when you want to stop all further execution of a script. Do not use this at the end of a script unconditionally, as it will hang the script, and any imports of it.
()
Promise<never>
tick
Use await tick() to await for the next physics step. You must use this in infinite while loops, otherwise the script will stall and be killed.
()
Promise<void>
FullLiveObjectJS
Scripts usually deal with this object type.
It contains all the fields of either a Ball, Brick, Clock, Cylinder, Group, Joint, JointAnimation, JointAnimator, JointAttachment, JointKeyframe, JointPose, Material, Mesh, Player, RigidGroup, Script, Skeleton, or Sound.
And it contains the following additional fields:
| Field | Type | |
|---|---|---|
| getChild | ||
| getChildren | ||
| parent | FullLiveObjectJS | null |
ObjectInfo
This is a helper type. It contains all the fields of either a Ball, Brick, Clock, Cylinder, Group, Joint, JointAnimation, JointAnimator, JointAttachment, JointKeyframe, JointPose, Material, Mesh, Player, RigidGroup, Script, Skeleton, Sound, or WorldLighting, excluding their id and name fields.
PlayerService
This service exposes methods for managing players in the game.
Example usage: game.playerService.getAllPlayers().
PlayerJoinHandler
PlayerLeaveHandler
ObjectService
This service exposes methods for reading and modifying objects.
If you only want to operate on one object and not its children, simply write object.propery = value, and don't use the modifiers here.
| Field | Type | |
|---|---|---|
| getObjectById | Returns the object with this ObjectId. | |
| getObjectByName | Returns any object with this name. | |
| getObjectsByName | Returns all the objects with this name. | |
| getObjectsByType | Returns all the objects with this type. | |
| createObject | Creates an object. Only callable by a Server Script. | |
| deleteObject | ||
| cloneObject | ||
| createJointAttachmentsInRigidGroup | Only callable by a Server Script. | |
| scaleObject | This scales the object and all children by the multiplier with respect to the center point. Note that repeatedly calling this will grow/shrink the object multiple times. Only callable by a Server Script. | |
| rotateObject | Rotates the object by this offset in degrees around each axis, bringing children with it. Only callable by a Server Script. | |
| moveObjectBy | Moves the object by this offset, bringing children with it. Only callable by a Server Script. | |
| moveObjectTo | Moves the object to this exact position, bringing children with it. Only callable by a Server Script. | |
| setObjectWalkthrough | Gives the object and all children the given isWalkthrough value. Only callable by a Server Script. | |
| setObjectAnchored | Gives the object and all children the given isAnchored value. Only callable by a Server Script. | |
| setObjectDensity | Gives the object and all children the given density value. Only callable by a Server Script. |
AnimationService
This service exposes methods for smoothly transitioning between animations.
Easing
"Linear" | "EaseInOut" | "EaseIn" | "EaseOut"
CollisionService
- collisionService fires even when isWalkthrough=true.
- collisionService is very granular even in RigidGroups, and will fire using a subitem's object_id.
| Field | Type | |
|---|---|---|
| addCollisionListener | ||
| removeCollisionListener | ||
| addCollisionStopListener | ||
| removeCollisionStopListener |
CollisionListener
GuiService
The guiKey can be anything; it is a string you pick to identify the GUI root.
| Field | Type | |
|---|---|---|
| show | Example: | |
| hide | guiKey: string => void | Example: |
useState
Only callable by a Client Script.
initialState: T | (() => T)
[T, (nextState: T | ((prevState: T) => T)) => void]
createState
Only callable by a Client Script.
initialState: T
{ get: () => T; set: (nextState: T | ((prevState: T) => T)) => void; }
GuiAnchor
| "topLeft" | "top" | "topRight" | "left" | "center" | "right" | "bottomLeft" | "bottom" | "bottomRight"
GuiRootRenderable
GuiRenderable | (() => GuiRenderable)
GuiRenderable
This is the equivalent to a React Node.
The typical usage is <MyComponent />.
You can also use strings, numbers, booleans, null, and undefined.
Reference
ObjectLocation
"Server" | "Client"
ClockReference
| Field | Type | |
|---|---|---|
| startedAtMs | number | The wall-clock ms at which the clock started in timeReference. |
| timeReference | Whether startedAtMs is client time or estimated server time. |
BallPrimitiveSettings
| Field | Type | |
|---|---|---|
| radius | number |
CylinderPrimitiveSettings
| Field | Type | |
|---|---|---|
| radius | number | |
| length | number |
BrickPrimitiveSettings
| Field | Type | |
|---|---|---|
| size |
BallMaterialSettings
CylinderMaterialSettings
BrickMaterialSettings
MeshMaterialSettings
JointInterpolationStyle
The interpolation style of the animation. Use Step for a stop-motion effect.
"Step" | "Linear" | "EaseInOut"
AlphaMode
This only applies to Material objects whose albedoTextureDataId have transparency. Default is Opaque.
- Opaque means to render the underlying object as solid, meaning show the base color in the transparent areas.
- Mask makes the underlying object either opaque or invisible in areas, based on the transparency cutoff.
- Blend intuitively makes the object transparent where the material is transparent. More expensive to render.
"Opaque" | "Blend" | { Mask: { cutoff: number } }
PlayerPhysicsControls
| Field | Type | |
|---|---|---|
| jumpHeight | number | Target number of blocks to which the player will jump. Internally we use this to figure out what impulse to apply. |
| stepHeight | number | The max obstacle height that the player will be teleported vertically onto, instead of getting stuck on. |
| speed | number | Movement speed. |
| acceleration | number | Movement acceleration. |
Vec3
| Field | Type | |
|---|---|---|
| x | number | |
| y | number | |
| z | number |
ObjectId
Every object in the world gets a unique id that you can use to reference it. It's just a number. These object ids may change between compile time and runtime. We automatically convert most object ids, but you should not hard-code object ids into scripts as we can't parse those until runtime.
number
DataId
"Data" generally means large assets that are uploaded and given an id, like mesh data and texture data. Objects reference them using their data id.
number
UserId
The unique id of the user. This will never change, so you should use it when tracking players. It is preferred over the player's username or the Player object's id.
string
Location3D
This is called "location", but really means both position and rotation. In other words, the full information needed to place the object in 3D at snapshot in time. Can be global or local depending on context.
Movement3D
Speed information of an object. The derivative of Location3D.
PhysicsToggles3D
A helper type.
| Field | Type | |
|---|---|---|
| isWalkthrough | boolean | Whether this object can pass through other objects. |
| isAnchored | boolean | Whether this object is totally unmovable. |
| density | number |
Color3
RGB color.
| Field | Type | |
|---|---|---|
| r | number | Red on a scale of 0-1. |
| g | number | Green on a scale of 0-1. |
| b | number | Blue on a scale of 0-1. |
OutlineEffect
Use this to add an outline around an object. You must set both the color and the width of the outline.
| Field | Type | |
|---|---|---|
| color | ||
| width | number | Width in pixels. Max 8px. |
VisualSettings
A helper type.
| Field | Type | |
|---|---|---|
| opacity | number | 0-1. |
| color | ||
| outline | OutlineEffect | null | |
| isAlwaysOnTop | boolean | Whether to render in front even if visually blocked. |
PhysicsInfo3D
A helper type.
| Field | Type | |
|---|---|---|
| location | ||
| movement |
Orientation3D
A helper type.
| Field | Type | |
|---|---|---|
| theta | number | Degrees around the vertical direction. Starts at Z and goes clockwise around Y. This is what changes when you look left or right. |
| phi | number | Degrees with respect to the horizon (XZ plane). Upwards is positive. This is what changes when you look up or down. |