Skip to content

Script API reference

Auto-generated from packages/shared/src/scripting/ScriptAPI.ts. Do not edit by hand — update the JSDoc in that file and run pnpm --filter @galatrix/docs docs:gen. The editor’s script autocomplete is fed from the same file, so this page always matches it.

Scripts attach to entities and run on the authoritative server. You implement lifecycle hooks as top-level functions; the globals below (entity, game, players, …) are always available inside your script. See Scripting basics for a walk-through.

Lifecycle hooks

Implement any of these as top-level functions in your script.

HookCalled
function onAwake(): voidCalled once before any onStart, when the entity is initialized. Set up internal state here.
function onStart(): voidCalled once when the entity is first loaded (after every entity's onAwake).
function onUpdate(dt: number): voidCalled once per rendered FRAME (Unity Update) — so it runs at the display's rate and dt varies. The place for cameras, input, UI and animation. Do NOT apply physics forces here: physics runs on a fixed step, so a force applied per-frame is multiplied by however many frames fall in one step (~3x at 60fps, ~7x at 144fps). Use onFixedUpdate for those.
function onFixedUpdate(dt: number): voidCalled exactly once per PHYSICS step, immediately before it runs (Unity FixedUpdate). dt is always Time.fixedDeltaTime, whatever the framerate. This is where forces, impulses and velocity changes belong — one call, one step, so what you ask for is what gets integrated, identically in the editor, a standalone build and on the multiplayer server. Read HELD input here (input.getKey); per-frame edges (getKeyDown/getKeyUp) can be missed or double-seen by a fixed step — handle those in onUpdate (Unity has the same caveat).
function onEnable(): voidCalled when this entity becomes active (enabled).
function onDisable(): voidCalled when this entity becomes inactive (disabled).
function onDestroy(): voidCalled when this entity is about to be destroyed.
function onCollisionEnter(other: EntityRef): voidCalled once when this solid collider first touches another entity's solid collider (Unity OnCollisionEnter).
function onCollisionStay(other: EntityRef): voidCalled every physics step while two solid colliders stay in contact (Unity OnCollisionStay).
function onCollisionExit(other: EntityRef): voidCalled when two solid colliders separate (Unity OnCollisionExit).
function onCollision(other: EntityRef): void
function onTriggerEnter(other: EntityRef): voidCalled when another entity enters this entity's trigger (a collider with isTrigger). Unity OnTriggerEnter.
function onTriggerStay(other: EntityRef): voidCalled every physics step while another entity stays inside this trigger (Unity OnTriggerStay).
function onTriggerExit(other: EntityRef): voidCalled when another entity exits this entity's trigger (Unity OnTriggerExit).
function onPlayerEnter(player: PlayerRef): voidCalled when a player enters this entity's trigger zone.
function onPlayerLeave(player: PlayerRef): voidCalled when a player leaves this entity's trigger zone.
function onInteract(player: PlayerRef): voidCalled when a player presses the USE key (E / gamepad A) while standing inside this entity's trigger zone — a Roblox ProximityPrompt-style interaction. Fires with the specific player who pressed it, so it works per-player in multiplayer (the server delivers each player's press). Put an isTrigger collider on the object to define the activation zone.
function onDeath(): voidCalled when this entity's health reaches 0 (via game.damageEntity), just before it's removed (if destroyOnDeath). Use it to drop loot, play an effect, award score, etc.
function onPlayerRespawn(player: PlayerRef): voidCalled on EVERY scripted entity when a player dies and respawns (lava, a fall, an enemy, or players.kill). Use it to reset gameplay state to the level's starting condition — e.g. warp an NPC back to its spawn, re-open a door, reset a timer.
function onMessage(key: string, data: unknown): voidCalled when another script sends a message to this entity via events.send().
function onToolEquipped(player: PlayerRef): voidCalled when a player equips this tool entity.
function onToolUnequipped(player: PlayerRef): voidCalled when a player unequips this tool entity.
function onToolActivated(player: PlayerRef): voidCalled when a player activates (left-click) this tool entity.
function onToolDeactivated(player: PlayerRef): voidCalled when a player deactivates (releases click) this tool entity.

entity

MemberDescription
entity.id: stringThis entity's ID. (read-only)
entity.name: stringThis entity's name. (read-only)
entity.tag: stringThis entity's tag — settable at runtime (Unity parity): entity.tag = 'Enemy' or setTag('Enemy').
entity.position: [number, number, number]Get/set position.
entity.rotation: [number, number, number, number]Get/set rotation. READS return a quaternion [x, y, z, w]. WRITES accept a quaternion (re-normalized if its length drifted) — or 3 values ([x, y, z] / Vector3 / {x, y, z}), which always mean Euler angles in DEGREES (what the terminal get and the Inspector show). A 3-value write used to be taken as a broken quaternion that visibly scaled/skewed the mesh.
entity.eulerAngles: [number, number, number]Get/set the rotation as Euler angles in DEGREES (Unity transform.eulerAngles).
entity.scale: [number, number, number]Get/set scale.
entity.color: stringGet/set color hex string.
entity.visible: booleanGet/set visibility.
entity.active: booleanGet/set active state. Inactive entities are hidden and skip physics/scripts.
entity.parent: ScriptEntityAPI | nullParent transform (live handle), or null if this is a root. Unity-style — use it directly, e.g. this.transform.parent.position. For the raw id use parentId. (read-only)
entity.parentId: string | nullParent entity ID, or null if this is a root. (read-only)
entity.root: ScriptEntityAPITopmost ancestor transform (live handle); returns this entity if it has no parent. (read-only)
entity.layer: numberGet/set layer number (0-31).
entity.debugString: stringGet/set a free-form debug string shown above this entity when the editor's Debug Info overlay is enabled (Editor Settings → Debug Info). Use it to surface AI state, counters, etc. Example: this.entity.debugString = 'state: ' + this.state. Set to '' to clear.
entity.forward: [number, number, number]Forward direction (unit vector, world space, -Z). Read-only. (read-only)
entity.right: [number, number, number]Right direction (unit vector, world space, +X). Read-only. (read-only)
entity.up: [number, number, number]Up direction (unit vector, world space, +Y). Read-only. (read-only)
entity.translate(offset: [number, number, number]): voidMove entity by offset [dx, dy, dz] in world space.
entity.rotate(euler: [number, number, number]): voidRotate entity by euler angles [rx, ry, rz] in degrees.
entity.lookAt(target: [number, number, number]): voidPoint this entity toward a world position.
entity.distanceTo(point: [number, number, number]): numberDistance from this entity to a point.
entity.getComponent(type: string): any | nullGet a component by type name — a write-through handle to the live DATA component (collider/rigidBody/…), OR, if type is a SCRIPT class name, that script's LIVE instance (Unity GetComponent<MyScript>()). null if neither. So enemy.getComponent('Health').takeDamage(5) works cross-entity. Special case: getComponent('NavMeshAgent') returns a Unity-shaped NavMeshAgent handle — a.setDestination(pos), a.speed = 5, a.isStopped = true, a.warp(pos), a.destination, a.remainingDistance — the instance-shaped form of the global agent API. Special case: getComponent('rigidBody') additionally carries the LIVE simulation members Unity keeps on Rigidbody — rb.velocity / rb.linearVelocity (get+set), rb.angularVelocity (rad/s), rb.AddForce(f, ForceMode.Impulse), rb.AddRelativeForce, rb.AddExplosionForce, rb.AddTorque, rb.GetPointVelocity(p), rb.friction, rb.ccd, rb.position/MovePosition, rb.Sleep()/WakeUp()/IsSleeping(). These are the physics.* verbs with this entity's id already bound; physics.getVelocity(id) still works unchanged. ⚠ rigidBody fields baked into the body at build time (mass, damping, gravityScale, freeze*, type…) THROW on write rather than silently not applying — see RigidBodyHandle.
entity.getScript(className: string): any | nullGet another script's LIVE instance on this entity by class name (Unity GetComponent<MyScript>()) — read/ write its fields, call its methods. Same as getComponent(className); this is the explicit name.
entity.addComponent(type: string, data: any): voidAdd a component to this entity. Overwrites if already present.
entity.setComponent(type: string, patch: any): voidEdit an existing component: merges the patch onto its current fields (creates it if absent). e.g. setComponent('followTarget', { target: enemy.id }) — leaves offset/smoothing untouched.
entity.removeComponent(type: string): voidRemove a component from this entity (cannot remove 'transform').
entity.hasComponent(type: string): booleanTrue if this entity has the named DATA component, or a script of that class.
entity.setParent(parentId: string | null): voidSet (or clear with null) this entity's parent in the hierarchy.
entity.compareTag(tag: string): booleanCompare this entity's tag with a string.
entity.setTag(tag: string): voidSet this entity's tag at runtime (same as entity.tag = …).
entity.getChildren(): EntityRef[]Get references to all child entities.
entity.bodyType: 'static' | 'dynamic' | 'kinematic'Physics body type (read-only). (read-only)
entity.GetComponent(type: string): any | nullUnity alias for getComponent.
entity.AddComponent(type: string, data: any): voidUnity alias for addComponent.
entity.TryGetComponent(type: string): booleanUnity: true if the named component is present.
entity.SetActive(active: boolean): voidUnity alias for active = … (enable/disable).
entity.CompareTag(tag: string): booleanUnity alias for compareTag.

game

MemberDescription
game.getTime(): numberTime since scene started (seconds).
game.getDeltaTime(): numberDelta time for this tick (seconds).
game.findEntity(name: string): EntityRef | nullFind an entity by exact name. Returns null if not found.
game.findEntityById(id: string): EntityRef | nullFind an entity by ID. Returns null if not found.
game.findEntities(namePrefix: string): EntityRef[]Find all entities with a given name prefix.
game.findEntitiesByTag(tag: string): EntityRef[]Find all entities with a given tag.
game.findEntityWithTag(tag: string): EntityRef | nullFind the first entity with a given tag. Returns null if not found.
game.spawnEntity(name: string, geometryType: string, position: [number, number, number]): EntityRefSpawn a new entity at a position. Returns a reference.
game.destroyEntity(id: string): voidDestroy an entity by ID.
game.setActive(entityId: string, active: boolean): voidEnable or disable an entity. Inactive entities are hidden and skip physics/scripts.
game.damageEntity(entityId: string, amount: number): voidDamage an entity that has a health component. Fires its onDeath() at 0 HP and removes it (unless health.destroyOnDeath is false). No-op if the entity has no health component.
game.healEntity(entityId: string, amount: number): voidHeal an entity with a health component, clamped to its max.
game.getEntityHealth(entityId: string): { current: number; max: number } | nullCurrent + max HP of an entity with a health component, or null if it has none.
game.getComponent(entityId: string, type: string): any | nullGet a component from any entity by ID and type. Returns a copy or null.
game.addComponent(entityId: string, type: string, data: any): voidAdd a component to any entity. Overwrites if already present.
game.setComponent(entityId: string, type: string, patch: any): voidEdit an existing component on any entity: merges the patch onto its current fields.
game.removeComponent(entityId: string, type: string): voidRemove a component from any entity (cannot remove 'transform').
game.hasComponent(entityId: string, type: string): booleanCheck if any entity has a component.
game.getScript(entityId: string, className: string): any | nullGet another entity's script instance by class name (Unity GetComponent<T>()). Returns null if not found.
game.getEntity(entityId: string): ScriptEntityAPI | nullGet a LIVE handle to any entity by id — read/write its transform, components, etc. Null if not found.
game.instantiate(prefabName: string, position?: [number, number, number]): EntityRef | nullSpawn a saved prefab by name (optionally at a position). Returns the root entity, or null.
game.loadScene(nameOrIndex: string | number): voidSwitch the running game to another map/scene — by NAME or by build INDEX (0 = main map, 1..N = sub-maps in the list order). Tears down the current scene and loads the target fresh; the change applies at the end of the current tick. Unity parity: SceneManager.LoadScene(name | index).
game.getActiveScene(): stringName of the scene currently running.
game.getActiveSceneIndex(): numberBuild index of the scene currently running (0 = main map, 1..N = sub-maps). Unity parity: SceneManager.GetActiveScene().buildIndex.
game.getSceneCount(): numberHow many maps this game has (main map + sub-maps). Unity parity: SceneManager.sceneCountInBuildSettings.
game.getSceneNameAt(index: number): stringName of the map at a build index (0 = main map), or '' if out of range.

time

MemberDescription
time.deltaTime: numberSeconds since the previous tick, SCALED by timeScale (Unity Time.deltaTime). (read-only)
time.unscaledDeltaTime: numberSeconds since the previous tick, UNAFFECTED by timeScale (Unity Time.unscaledDeltaTime). (read-only)
time.fixedDeltaTime: numberThe fixed physics timestep, independent of frame rate (Unity Time.fixedDeltaTime). (read-only)
time.time: numberSeconds since the scene started, scaled by timeScale (Unity Time.time). (read-only)
time.unscaledTime: numberSeconds since the scene started, UNAFFECTED by timeScale (Unity Time.unscaledTime). (read-only)
time.frameCount: numberNumber of ticks since the scene started. (read-only)
time.smoothDeltaTime: numberdeltaTime smoothed over recent frames (Unity Time.smoothDeltaTime) — use it to drive anything a single hitched frame shouldn't jolt. An approximation of Unity's filter, not the identical curve. (read-only)
time.timeScale: numberThe simulation time scale (Unity Time.timeScale) — a settable property. Assign it to pause or slow-mo: time.timeScale = 0 pauses (physics, NPCs, animations, and deltaTime freeze), = 1 resumes, = 0.5 is slow motion. Client-only: a no-op on the multiplayer server (it can't pause time for everyone). Scripts keep ticking while paused, so a pause menu can read input and set it back to 1 — drive that menu with unscaledDeltaTime, which ignores timeScale.

input

MemberDescription
input.getKey(key: string): booleanReturns true while the key is held down. Key names: 'w','a','s','d','space','shift','e','q','1'-'9','arrowup', etc.
input.getKeyDown(key: string): booleanReturns true on the frame the key was first pressed.
input.getKeyUp(key: string): booleanReturns true on the frame the key was released.
input.getAxis(axis: 'horizontal' | 'vertical'): numberReturns a value from -1 to 1 for the given axis. 'horizontal' = A/D or Left/Right, 'vertical' = W/S or Up/Down.
input.getMouseButton(button: number): booleanReturns true if the mouse button is held. 0=left, 1=middle, 2=right.
input.getMouseButtonDown(button: number): booleanReturns true on the frame the mouse button was pressed.
input.getMouseButtonUp(button: number): booleanReturns true on the frame the mouse button was released.
input.getMousePosition(): [number, number]Mouse position in screen coords [x, y] from 0-1.
input.getMouseDelta(): [number, number]Mouse movement since last frame [dx, dy] in pixels (Unity's 'Mouse X'/'Mouse Y'). Works under pointer lock — use this for scripted look.
input.getMouseScrollDelta(): [number, number]Mouse wheel scroll this frame [x, y]; y > 0 = scroll up (Unity's Input.mouseScrollDelta). Browser-scaled magnitude.
input.getTouchCount(): numberNumber of active touches this frame (Unity's Input.touchCount). 0 on a device with no touch.
input.getTouch(index: number): TouchInfo | nullThe active touch at index, or null if out of range (Unity's Input.GetTouch).
input.getTouches(): TouchInfo[]All active touches this frame (Unity's Input.touches). Empty array when none.
input.getScreenSize(): [number, number]Render surface size [width, height] in PIXELS (Unity's Screen.width/height). [0, 0] on a host with no canvas (the MP server). This is the scale factor between our 0-1 screen coords and Unity's pixels.
input.getAnyKey(): booleanTrue while ANY key or mouse button is held (Unity's Input.anyKey).
input.getAnyKeyDown(): booleanTrue on the frame any key or mouse button was first pressed (Unity's Input.anyKeyDown).
input.getInputString(): stringCharacters typed this frame, in order (Unity's Input.inputString). Printable text plus '\b' for backspace and '\n' for enter; empty when nothing was typed.
input.getDeviceInfo(): DeviceInfoDevice + display facts behind Unity's Input.mousePresent / touchSupported and Screen.dpi/orientation/ safeArea/fullScreen. Zeroed on a host with no DOM (the MP server).
input.getGamepads(): GamepadInfo[]Connected gamepads (Unity's Input.GetJoystickNames). Empty when none.

cursor

MemberDescription
cursor.lock(): voidLock the cursor to the game (pointer lock — hides it and feeds raw mouse to look). Unity: CursorLockMode.Locked.
cursor.unlock(): voidRelease the cursor so the player can move it freely. Unity: CursorLockMode.None.
cursor.setVisible(visible: boolean): voidShow or hide the cursor. Unity: Cursor.visible.
cursor.isLocked(): booleanTrue while the cursor is locked to the game.
cursor.isVisible(): booleanTrue while the cursor is visible.

camera

MemberDescription
camera.setType(type: 'custom' | 'scriptable' | 'default'): voidWho drives the camera — Roblox's Camera.CameraType. 'custom' / 'default' (two names for the SAME mode — 'custom' pairs with Roblox, 'default' says what it is): the engine drives. With the built-in player that's the player rig (orbit / follow / fixed / cinematic per the camera component) and pose writes are overwritten the next frame — detach first. With the built-in player DISABLED it's Unity mode: the main Camera ENTITY is the camera's transform, and setPosition/setRotation/lookAt write through to that entity, so a single call moves the camera and it stays. 'scriptable': the script owns the render camera outright — nothing drives it until you switch back. The cutscene / kill-cam / orbit-menu pattern over the default player: camera.setType('scriptable'); camera.setPosition(...); … camera.setType('default'). Resets every play session. Client-only: a no-op on the multiplayer server.
camera.getType(): 'custom' | 'scriptable'The current camera drive mode ('default' reads back as 'custom' — same mode).
camera.setPosition(position: [number, number, number]): voidMove the render camera to a world position (Unity: camera.transform.position). With the built-in player active this only sticks in 'scriptable' mode — see setType.
camera.setRotation(rotation: [number, number, number, number]): voidSet the render camera's rotation: a quaternion [x, y, z, w] (auto-normalized), or 3 values ([x,y,z]) = Euler DEGREES.
camera.lookAt(target: [number, number, number]): voidPoint the camera at a world position.
camera.setFov(degrees: number): voidSet the vertical field of view in degrees.
camera.getFov(): numberThe camera's current vertical field of view in degrees (Unity: Camera.fieldOfView).
camera.getRotation(): [number, number, number, number]The camera's current rotation as a quaternion [x, y, z, w] (Unity: camera.transform.rotation).
camera.getProjection(): CameraProjectionHow the camera projects: orthographic / orthographicSize / near+farClipPlane / aspect.
camera.setProjection(patch: { orthographicSize?: number; nearClipPlane?: number; farClipPlane?: number }): voidChange the writable part of the projection. orthographicSize is the 2D zoom knob (HALF the vertical view height) — a pixel-perfect camera derives its own size and ignores it, as in Unity. Whether the camera is orthographic at all is authored on the camera component, not set from scripts.
camera.getPosition(): [number, number, number]The camera's current world position.
camera.getForward(): [number, number, number]The direction the camera is facing (unit vector) — handy for shooting / raycasts.
camera.screenPointToRay(point?: [number, number]): { origin: [number, number, number]; direction: [number, number, number] }World ray through a screen point ([x, y] in 0-1 screen coords, top-left origin — the same space as input.getMousePosition / touches). Omit the point to use the current mouse position. Works for perspective AND orthographic cameras — aim clicks, place objects under the cursor, 2D picking: const r = this.camera.screenPointToRay(); const hit = this.physics.raycast(r.origin, r.direction). On the multiplayer server (no camera) it falls back to the camera position + facing.
camera.screenToWorldPoint(point?: [number, number] | [number, number, number], distance?: number): [number, number, number]The world position under a screen point, distance units from the camera (Unity's Camera.ScreenToWorldPoint — pass the distance as the point's 3rd element or the 2nd arg; default 10). With an orthographic camera this is THE way to get the mouse's 2D world position.
camera.worldToScreen(worldPoint: [number, number, number] | { x: number; y: number; z: number }): { x: number; y: number; z: number; behind: boolean }Project a world position to a screen point (the inverse of screenPointToRay). Returns x,y in 0-1 screen coords with a top-left origin (the same space as screenPointToRay's input, ready for HUD placement), z = distance in front of the camera in world units (negative when the point is behind the camera), and behind = z <= 0. Use it to pin a label/marker/off-screen arrow to a world entity; guard on behind (or z <= 0) to hide the marker when the target is behind you. On the multiplayer server (no camera) it returns { x: 0.5, y: 0.5, z: 0, behind: true }.
camera.shake(strength?: number, duration?: number): voidKick off a transient screen shake — a decaying random camera offset for duration seconds. Great for explosions, big hits, landings. strength is in world units (~0.2 subtle … ~0.8 violent); defaults strength 0.3, duration 0.3s. Re-calling restarts it (a new blast overrides a fading one). Client-only: a no-op on the multiplayer server (no camera).
camera.getEntity(): ScriptEntityAPI | nullThe Camera entity backing the active render camera (a live game-object handle, Unity's Camera.main.gameObject), or null when the built-in follow camera is active (it has no entity). Client-only: returns null on the multiplayer server, where there is no camera.

characterController

MemberDescription
characterController.move(entityId: string, motion: [number, number, number]): { grounded: boolean; collided: boolean }Move a characterController entity by a world-space motion for this frame (include your own gravity, Unity-style). Collide-and-slide + auto-step + ground-snap. Returns grounded + whether it hit anything.
characterController.isGrounded(entityId: string): booleanWhether the controller was on the ground as of its last move().

physics

MemberDescription
physics.applyForce(entityId: string, force: [number, number, number]): voidPush a dynamic body through its CENTRE OF MASS for one physics step — Unity's AddForce(ForceMode.Force). Call it every frame to push continuously; it does not linger. Newtons.
physics.applyForceAtPoint(entityId: string, force: [number, number, number], point: [number, number, number]): voidPush at a WORLD point rather than the centre of mass, for one step. The off-centre part becomes torque, so this is what tilts, rolls and spins a body — and it's the primitive a scripted vehicle is built on: a spring force at each wheel's contact point IS the suspension, and it's what gives weight transfer and body roll. applyForce cannot express any of that.
physics.applyImpulseAtPoint(entityId: string, impulse: [number, number, number], point: [number, number, number]): voidInstant velocity change at a WORLD point (Unity AddForceAtPosition + ForceMode.Impulse) — a hit or kick that also spins the body. N·s.
physics.applyTorque(entityId: string, torque: [number, number, number]): voidSpin a body for one step (N·m) — anti-roll bars, air control, self-righting.
physics.applyTorqueImpulse(entityId: string, torque: [number, number, number]): voidInstant spin change (N·m·s).
physics.getPointVelocity(entityId: string, point: [number, number, number]): [number, number, number]How fast a WORLD point ON a body is really moving: v + ω × (point − centreOfMass). A spinning body's edge moves even when its centre doesn't, so suspension damping and tyre slip need THIS, not getVelocity. Scripts can't derive it — the centre of mass isn't otherwise reachable.
physics.getMass(entityId: string): numberBody mass in kg — spring and drive forces are meaningless until scaled to it.
physics.getCenterOfMass(entityId: string): [number, number, number]Body centre of mass, world space.
physics.setFriction(entityId: string, friction: number): voidSet the entity collider's friction at runtime — 0 = frictionless (ice), higher = grippier (Unity PhysicMaterial.dynamicFriction). Unlike the authored collider.friction (applied only when the collider is built), this changes it live — an icy floor, a sticky zone. Note: the physics engine uses a single friction coefficient, so there's no separate static vs dynamic friction.
physics.getFriction(entityId: string): numberThe entity collider's current friction coefficient.
physics.setRestitution(entityId: string, restitution: number): voidSet the entity collider's restitution (bounciness) at runtime, 0..1 — 0 = no bounce, 1 = fully elastic (Unity PhysicMaterial.bounciness). Live, unlike the authored collider.restitution.
physics.getRestitution(entityId: string): numberThe entity collider's current restitution (bounciness).
physics.sleep(entityId: string): voidForce a dynamic body to sleep NOW (Unity Rigidbody.Sleep) — it stops simulating until a contact, an impulse, or wakeUp disturbs it. Authored counterpart: rigidBody.startAsleep.
physics.wakeUp(entityId: string): voidWake a sleeping body (Unity Rigidbody.WakeUp).
physics.isSleeping(entityId: string): booleanWhether the body is currently asleep (Unity Rigidbody.IsSleeping).
physics.setCcd(entityId: string, enabled: boolean): voidTurn continuous collision detection on/off for a body at runtime (Unity Rigidbody.collisionDetectionMode = Continuous/Discrete). Physics steps at a fixed 20 Hz, so a body moving faster than its own thickness per step can tunnel through a thin wall between steps; CCD sweeps its path and stops it at the surface instead. Enable it on projectiles / fast props. Authored counterpart: the rigidBody.ccd field (Inspector ▸ RigidBody ▸ Continuous Collision). Costs a little CPU, so it's off by default and best reserved for the few bodies that need it.
physics.setDamping(entityId: string, linear?: number, angular?: number): voidDrag (Unity Rigidbody.linearDamping / angularDamping). Authored rigidBody.linearDamping and angularDamping only reach the body when it is BUILT — this is what changes it mid-play. Pass undefined for either to leave that one alone.
physics.getDamping(entityId: string): [number, number]Current [linear, angular] damping straight off the body.
physics.setGravityScale(entityId: string, scale: number): voidHow strongly world gravity pulls this body — 1 normal, 0 weightless, negative floats it up (Unity has no direct equivalent; useGravity = false is setGravityScale(id, 0)).
physics.getGravityScale(entityId: string): number
physics.setMass(entityId: string, mass: number): voidChange the body's EXACT mass mid-play (Unity rb.mass = x), independent of collider size/density — the same Unity-authoritative model the authored rigidBody.mass uses. Ignored for values <= 0.
physics.setFreeze(entityId: string, freezePosition?: [boolean, boolean, boolean], freezeRotation?: [boolean, boolean, boolean]): voidFreeze/unfreeze axes at runtime (Unity RigidbodyConstraints). true means FROZEN, matching the authored rigidBody.freezePosition / freezeRotation. Pass undefined to leave one alone.
physics.setBodyType(entityId: string, type: 'static' | 'dynamic' | 'kinematic'): voidSwap a body between dynamic / kinematic / static mid-play (Unity rb.isKinematic = true). This is how a ragdoll activates, a carried prop goes inert, or an enemy freezes in place. Switching to kinematic stops the solver moving it — drive it with warpBody / rb.MovePosition from then on.
physics.getBodyType(entityId: string): 'static' | 'dynamic' | 'kinematic'
physics.setDetectCollisions(entityId: string, enabled: boolean): voidUnity Rigidbody.detectCollisions — turn the body's COLLIDERS off while it keeps simulating, so it still falls but passes through everything (no-clip / ghost / phase-through effects). Distinct from disabling the body, which would freeze it in place.
physics.getDetectCollisions(entityId: string): boolean
physics.isCcdEnabled(entityId: string): booleanWhether continuous collision detection is currently on for this body.
physics.applyImpulse(entityId: string, impulse: [number, number, number]): voidApply an impulse (instant velocity change) to a dynamic rigid body.
physics.setVelocity(entityId: string, velocity: [number, number, number]): voidSet the linear velocity of a dynamic rigid body.
physics.getVelocity(entityId: string): [number, number, number]Get the linear velocity of a rigid body.
physics.setAngularVelocity(entityId: string, velocity: [number, number, number]): voidSet the angular velocity of a dynamic rigid body.
physics.getAngularVelocity(entityId: string): [number, number, number]Get the angular velocity of a rigid body.
physics.warpBody(entityId: string, position: [number, number, number], rotation?: [number, number, number, number]): voidTeleport a dynamic/kinematic body to a world position (and optional rotation quaternion [x,y,z,w], default upright), zeroing its velocity — a respawn/reset for vehicles, crates, ragdolls, etc. Unlike setting entity.position (which the physics sim overrides for a dynamic body), this moves the BODY.
physics.raycast(origin: [number, number, number], direction: [number, number, number], maxDistance?: number, layerMask?: number, ignoreEntities?: string[]): RaycastHit | nullCast a ray from origin in direction, returns the first hit or null. Optional layerMask is a bitmask of layers to hit — bit L set = hit layer L (e.g. 1 &lt;&lt; 3 for layer 3 only); omit/-1 = all layers. Optional ignoreEntities is a list of entity ids to skip (the ray passes through them) — pass [this.entity.id] to ignore yourself. Unity has no such list (it uses layers + result-filtering); this is a convenience on top of layerMask.
physics.raycastAll(origin: [number, number, number], direction: [number, number, number], maxDistance?: number, layerMask?: number, ignoreEntities?: string[]): RaycastHit[]Cast a ray and return ALL hits along it, sorted nearest-first (Unity Physics.RaycastAll). Optional layerMask filters which layers are hit (bit L set = layer L; omit/-1 = all). Optional ignoreEntities = entity ids to skip (e.g. [this.entity.id] for self).
physics.sphereCast(origin: [number, number, number], radius: number, direction: [number, number, number], maxDistance?: number, layerMask?: number, ignoreEntities?: string[]): RaycastHit | nullThick raycast — sweep a sphere of radius along the ray and return the first entity it would touch (Unity Physics.SphereCast), as a RaycastHit (see Value types) or null. More reliable than a thin ray for ground checks and projectiles: a ray slips through gaps and off ledge edges a real body wouldn't. distance is how far the sphere's CENTRE travelled before contact; point/normal are on the surface it hit. ⚠ distance is 0 when the sphere already overlaps a collider at origin (contact-at-start), and the returned hit sets overlapping: true so you can detect it — start the cast clear of geometry (or offset origin back along -direction) when you need the gap distance. layerMask and ignoreEntities (entity ids to skip, e.g. [this.entity.id]) as in raycast.
physics.overlapSphere(center: [number, number, number], radius: number, layerMask?: number): EntityRef[]All entities within radius of center (proximity query, by entity position — not exact collider intersection). Includes the caller; filter by tag/component as needed. layerMask filters by layer the same way raycast does (bit L = layer L; omit or -1 for every layer).
physics.overlapBox(center: [number, number, number], halfExtents: [number, number, number], orientation?: [number, number, number, number], layerMask?: number): EntityRef[]All entities inside a box at center with halfExtents (proximity query by entity position). An optional orientation quaternion makes it an oriented box; default is axis-aligned (Unity OverlapBox). layerMask filters by layer as in raycast.
physics.setGravity(gravity: [number, number, number]): voidSet gravity for the physics world.
physics.getGravity(): [number, number, number]The physics world's current gravity (Unity: Physics.gravity). Reflects the map's own gameSettings.gravity, not a constant — read it before computing jump heights or drag.
physics.createRagdoll(position: [number, number, number], options?: RagdollSpawnOptions): RagdollHandleSpawn a physics ragdoll — a humanoid skeleton of jointed dynamic capsules that flops under gravity. position is the BASE (feet). Returns live limb handles; apply an impulse to root (the pelvis) to launch it. e.g. const r = physics.createRagdoll([x,y,z]); physics.applyImpulse(r.root.id, [0,5,8]).

animation

MemberDescription
animation.play(entityId: string, clipName: string, options?: { loop?: boolean; speed?: number }): voidPlay an animation clip on an entity.
animation.stop(entityId: string, clipName?: string): voidStop a specific animation clip (or all if clipName is omitted).
animation.isPlaying(entityId: string, clipName: string): booleanReturns true if the entity is currently playing the given clip.
animation.getClips(entityId: string): string[]Get list of available animation clip names on an entity.
animation.crossFade(entityId: string, clipName: string, duration?: number): voidCrossfade from the current animation to a new one over duration seconds.
animation.setBool(entityId: string, name: string, value: boolean): voidSet a bool parameter on an entity's animator controller (drives state transitions).
animation.setFloat(entityId: string, name: string, value: number): voidSet a float parameter (e.g. a speed value that crosses a transition threshold).
animation.setInt(entityId: string, name: string, value: number): voidSet an int parameter.
animation.setTrigger(entityId: string, name: string): voidPulse a trigger parameter — fires a transition once, then auto-resets.
animation.getFloat(entityId: string, name: string): numberRead a float (or bool-as-0/1) parameter.
animation.getBool(entityId: string, name: string): booleanRead a bool parameter.

timer

MemberDescription
timer.delay(delaySeconds: number, fn: () => void): numberCall fn after delaySeconds. Returns timer ID.
timer.interval(intervalSeconds: number, fn: () => void): numberCall fn every intervalSeconds. Returns timer ID.
timer.cancel(timerId: number): voidCancel a timer by ID.

math

MemberDescription
math.lerp(a: number, b: number, t: number): numberLinear interpolation from a to b by t (0-1).
math.clamp(value: number, min: number, max: number): numberClamp value between min and max.
math.remap(value: number, inMin: number, inMax: number, outMin: number, outMax: number): numberTake value from one range and return its equivalent position in another: math.remap(75, 0, 100, -1, 1) → 0.5. Output ranges may be inverted (outMin > outMax) to flip direction. Values outside the input range are EXTRAPOLATED, not clamped — wrap the call in math.clamp if you need it bounded. If inMin === inMax the result is outMin.
math.randomRange(min: number, max: number): numberRandom float between min and max.
math.randomInt(min: number, max: number): numberRandom integer between min and max (inclusive).
math.randomSeed(seed: number): voidSeed the script RNG that randomRange/randomInt/Random draw from. Same seed ⇒ same sequence in the editor play-test, the server and a standalone build — the basis for reproducible runs.
math.damp(current: number, target: number, lambda: number, dt: number): numberFrame-rate-independent approach: target + (current - target) * exp(-lambda * dt). Use this instead of lerp(current, target, 0.1) in an update loop, which converges faster the higher the frame rate. Larger lambda = snappier.
math.snap(value: number, increment: number): numberRound to the nearest multiple of increment (grid snapping). increment 0 returns value unchanged.
math.wrap(value: number, min: number, max: number): numberWrap value into [min, max) — the general form of repeat(), which only covers 0..length.
math.smootherstep(edge0: number, edge1: number, x: number): numberPerlin's smoothstep: same 0→1 shape but with a continuous second derivative, so motion driven by it has no visible kick at the ends.
math.distance(a: [number, number, number], b: [number, number, number]): numberDistance between two 3D points.
math.normalize(v: [number, number, number]): [number, number, number]Normalize a 3D vector to unit length.
math.dot(a: [number, number, number], b: [number, number, number]): numberDot product of two 3D vectors.
math.cross(a: [number, number, number], b: [number, number, number]): [number, number, number]Cross product of two 3D vectors.
math.add(a: [number, number, number], b: [number, number, number]): [number, number, number]Add two 3D vectors.
math.sub(a: [number, number, number], b: [number, number, number]): [number, number, number]Subtract vector b from a.
math.mul(v: [number, number, number], scalar: number): [number, number, number]Multiply a 3D vector by a scalar.
math.div(v: [number, number, number], scalar: number): [number, number, number]Divide a 3D vector by a scalar. Dividing by 0 returns [0,0,0] rather than Infinity.
math.negate(v: [number, number, number]): [number, number, number]Flip a vector's direction (−v).
math.scaleVec(a: [number, number, number], b: [number, number, number]): [number, number, number]Component-wise multiply, for non-uniform scaling (Unity Vector3.Scale).
math.minVec(a: [number, number, number], b: [number, number, number]): [number, number, number]Component-wise minimum — the low corner of the AABB around both (Unity Vector3.Min).
math.maxVec(a: [number, number, number], b: [number, number, number]): [number, number, number]Component-wise maximum — the high corner of the AABB around both (Unity Vector3.Max).
math.length(v: [number, number, number]): numberLength (magnitude) of a 3D vector.
math.sqrLength(v: [number, number, number]): numberSquared length — skips the sqrt (Unity sqrMagnitude). Compare against radius*radius.
math.sqrDistance(a: [number, number, number], b: [number, number, number]): numberSquared distance between two points — skips the sqrt. Compare against range*range.
math.smoothstep(edge0: number, edge1: number, x: number): numberSmooth-step interpolation (ease in-out).
math.deg2rad(degrees: number): numberConvert degrees to radians.
math.rad2deg(radians: number): numberConvert radians to degrees.
math.moveTowards(current: number, target: number, maxDelta: number): numberMove a value toward target by at most maxDelta.
math.lerpVec3(a: [number, number, number], b: [number, number, number], t: number): [number, number, number]Lerp a 3D vector from a to b by t.
math.clamp01(value: number): numberClamp value to [0, 1] (Unity Mathf.Clamp01).
math.sign(value: number): numberSign of value: +1 for ≥0, −1 otherwise (Unity Mathf.Sign — note +1 at 0, unlike Math.sign).
math.inverseLerp(a: number, b: number, value: number): numberWhere value falls between a and b, as 0..1 (Unity Mathf.InverseLerp).
math.repeat(t: number, length: number): numberWrap t into [0, length) (Unity Mathf.Repeat).
math.pingPong(t: number, length: number): numberBounce t between 0 and length (Unity Mathf.PingPong).
math.approximately(a: number, b: number): booleanTrue if a and b are within a tiny epsilon (Unity Mathf.Approximately).
math.deltaAngle(a: number, b: number): numberShortest signed difference between two angles in degrees, in [−180, 180] (Unity Mathf.DeltaAngle).
math.lerpAngle(a: number, b: number, t: number): numberInterpolate between two angles in degrees the short way (Unity Mathf.LerpAngle).
math.moveTowardsAngle(current: number, target: number, maxDelta: number): numberMove a degrees angle toward target by at most maxDelta, short way (Unity Mathf.MoveTowardsAngle).
math.angle(a: [number, number, number], b: [number, number, number]): numberUnsigned angle in degrees between two vectors (Unity Vector3.Angle).
math.project(v: [number, number, number], onto: [number, number, number]): [number, number, number]Project vector v onto onto (Unity Vector3.Project).
math.reflect(v: [number, number, number], normal: [number, number, number]): [number, number, number]Reflect v off a surface with the given normal (Unity Vector3.Reflect).
math.clampMagnitude(v: [number, number, number], max: number): [number, number, number]Clamp a vector's length to max (Unity Vector3.ClampMagnitude).
math.moveTowardsVec3(current: [number, number, number], target: [number, number, number], maxDelta: number): [number, number, number]Move a point toward target by at most maxDelta (Unity Vector3.MoveTowards).
math.dampVec3(current: [number, number, number], target: [number, number, number], lambda: number, dt: number): [number, number, number]Frame-rate-independent approach for a point — the vector form of {@link ScriptMathAPI.damp}.
math.smoothDamp(current: number, target: number, velocity: number[], smoothTime: number, deltaTime: number, maxSpeed?: number): numberCritically-damped spring (Unity Mathf.SmoothDamp). velocity is a 1-element in/out array you keep between frames — e.g. this.vel = [0] in onStart, then pass this.vel each update; it is mutated. ⚠ Argument order differs from Mathf.SmoothDamp: deltaTime comes BEFORE the optional maxSpeed, because omitting dt (and silently getting a fixed 0.02 step) is the mistake worth preventing.
math.smoothDampVec3(current: [number, number, number], target: [number, number, number], velocity: number[], smoothTime: number, deltaTime: number, maxSpeed?: number): [number, number, number]Critically-damped spring for a point (Unity Vector3.SmoothDamp). velocity is a 3-element in/out array you keep between frames ([0,0,0]); it is mutated. Same argument-order note as smoothDamp.
math.projectOnPlane(v: [number, number, number], normal: [number, number, number]): [number, number, number]Drop the part of v pointing into a surface, keep the part along it (Unity Vector3.ProjectOnPlane). The slope primitive for character controllers: projectOnPlane(moveDir, groundNormal).
math.signedAngle(a: [number, number, number], b: [number, number, number], axis: [number, number, number]): numberAngle from a to b in degrees, signed by which side of axis the turn goes (Unity Vector3.SignedAngle). Pass [0,1,0] for a yaw turn. Unlike angle(), this tells you WHICH WAY.
math.geo: ScriptMathGeoAPIRay/point/segment queries against pure geometry — see {@link ScriptMathGeoAPI}.
math.curve: ScriptMathCurveAPIArc and spline interpolation — see {@link ScriptMathCurveAPI}.

events

MemberDescription
events.send(entityId: string, key: string, data?: unknown): voidSend a message to a specific entity's scripts.
events.broadcast(key: string, data?: unknown): voidSend a message to ALL entities' scripts.
events.sendToTag(tag: string, key: string, data?: unknown): voidSend a message to all entities with a given tag.

scene

MemberDescription
scene.getName(): stringGet the name of the current scene.
scene.getLayers(): string[]The project's layer names, index = layer id (0 = 'Default'), exactly like Unity's Layers. Holes in the list are '' (unnamed). Backs the Unity-compat LayerMask.NameToLayer / LayerToName / GetMask.
scene.loadScene(nameOrIndex: string | number): voidLoad a scene by name OR build index (0 = main map, 1..N = sub-maps). Triggers a full scene reload.
scene.setEnvironment(env: SceneEnvironment): voidChange the live ENVIRONMENT (sky/fog/lighting/day-night/shadows) at runtime — e.g. go dark when a boss spawns: scene.setEnvironment({ skyColor:'#0a0a14', ambientIntensity:0.1, fogEnabled:true, fogColor:'#05050a' }). Merges (set only what you want); broadcasts to all clients to re-apply. Per-map. Shadow keys: shadowsEnabled, shadowType ('soft'|'hard'), shadowMapSize (512-4096), shadowCameraSize (coverage radius around the viewer, 10-200), shadowCameraNear/Far — see the Lighting & shadows guide.

players

MemberDescription
players.getAll(): PlayerRef[]Get all connected players.
players.getById(id: string): PlayerRef | nullGet a player by ID.
players.getLocal(): PlayerRef | nullThe local player (this client's own player) on client runtimes — editor play-test, standalone, and offline play. On the authoritative multiplayer server there is no single local player, so this returns null there: use getAll()/getById() or the onPlayer* hooks to act per-player instead.
players.getPosition(playerId: string): [number, number, number] | nullGet a player's current position. Returns null if player not found.
players.getVehicle(playerId: string): string | nullThe entity id of the vehicle the player is driving (its chassis), or null when on foot — so a camera script can detect driving: const car = players.getVehicle(players.getLocal().id). Resolve the id with getEntity(car) for its .position / .forward. Client-only (null on the MP server).
players.teleport(playerId: string, position: [number, number, number]): voidTeleport a player to a position.
players.launch(playerId: string, velocity: [number, number, number]): voidLaunch/knock the player with an instant velocity — bounce pads, jump pads, knockback, explosion pushes. The player is a kinematic controller, so physics.applyImpulse(player.id, …) does NOTHING to it; use this instead. velocity[1] (Y) is the upward launch speed, velocity[0]/[2] (X/Z) a horizontal knockback that decays. e.g. a bounce pad: players.launch(player.id, [0, 18, 0]).
players.kill(playerId: string): voidKill a player (respawn at spawn point).
players.damage(playerId: string, amount: number): voidDeal damage to a player (kills + respawns them if health reaches 0).
players.heal(playerId: string, amount: number): voidHeal a player by amount, clamped to their max health (the inverse of damage — for health pickups).
players.getHealth(playerId: string): numberGet a player's current health. This is the authoritative value that damage(), hazard zones, and falls reduce, and that respawn restores to max. Read it to drive a HUD health bar or a game-over check — do NOT keep your own player-HP variable (it desyncs from real damage sources).
players.getMaxHealth(playerId: string): numberGet a player's maximum health (default 100, or whatever setMaxHealth set).
players.setMaxHealth(playerId: string, max: number): voidSet a player's maximum health AND restore them to full. Call it at game start to give the player a custom amount of HP (e.g. setMaxHealth(id, 200) for a tankier hero).
players.setInputEnabled(playerId: string, enabled: boolean): voidEnable or disable a player's movement input. Use it to freeze the player during a level transition, cutscene, or dialog (re-enable it before handing control back).
players.setInvulnerable(playerId: string, invulnerable: boolean): voidMake a player invulnerable (true) or vulnerable again (false). While invulnerable, damage() and kill() — and hazard zones, falls, enemy hits — are no-ops for that player. Use it for spawn protection, power-ups, or to stop deaths during a level-complete overlay / cutscene.
players.respawn(playerId: string): voidRespawn a player at the spawn point.
players.setScore(playerId: string, score: number): voidSet a player's score (for leaderboard).
players.getScore(playerId: string): numberGet a player's score.
players.setSpeed(speed: number): voidSet player movement speed (units/sec). Pass a playerId first to target ONE player in multiplayer: setSpeed(player.id, 10) (e.g. from onInteract). Without an id it sets the local/current player.
players.setSpeed(playerId: string, speed: number): void
players.getSpeed(): numberGet current player movement speed.
players.setJumpForce(force: number): voidSet player jump force.
players.getJumpForce(): numberGet current player jump force.

vehicles

MemberDescription
vehicles.getAll(): string[]Every vehicle (chassis) entity id in the running scene.
vehicles.getSpeed(vehicleId: string): numberSigned forward speed (m/s) — positive when driving forward. 0 if unknown.
vehicles.isGrounded(vehicleId: string): booleanTrue if any wheel is touching the ground (gate throttle/steer on this).
vehicles.getConfig(vehicleId: string): Record<string, number> | nullThe EFFECTIVE tuning (component overrides merged over the engine defaults) — real numbers, e.g. { engineForce, brakeForce, maxSteerAngleDeg, steerRate, gripAssist, ... }. null if not a vehicle.
vehicles.setConfig(vehicleId: string, patch: Record<string, number | boolean>): voidOverride tuning at runtime (partial — only the given fields change; the physics reads them next step). e.g. vehicles.setConfig(car, { engineForce: 1400, gripAssist: 0 }).
vehicles.setInput(vehicleId: string, input: { throttle?: number; steer?: number; brake?: boolean; handbrake?: boolean }): voidDrive the car: throttle −1..1 (reverse..forward), steer −1..1 (right..left), brake, handbrake. Only the given fields change. Takes effect when the car has scriptedControl (or no built-in driver).
vehicles.setThrottle(vehicleId: string, throttle: number): voidConvenience: set throttle only (−1..1). Composes with setSteer/setBrake.
vehicles.setSteer(vehicleId: string, steer: number): voidConvenience: set steer only (−1..1, left positive).
vehicles.setBrake(vehicleId: string, brake: boolean): voidConvenience: set the service brake only (all wheels).
vehicles.setHandbrake(vehicleId: string, handbrake: boolean): voidConvenience: set the handbrake only — locks + slides the REAR wheels for e-brake turns / drifts.

ui

MemberDescription
ui.showMessage(text: string, playerId?: string): voidShow a message to all players (or specific player).
ui.createLabel(options: HudLabelOptions): HudElementHandleCreate a text label on screen. Returns a handle to update/remove it.
ui.createBar(options: HudBarOptions): HudElementHandleCreate a progress/health bar on screen. Returns a handle.
ui.createPanel(options: HudPanelOptions): HudElementHandleCreate a background panel on screen. Returns a handle.
ui.createImage(options: HudImageOptions): HudElementHandleCreate an image on screen from a project texture asset (by name or id). Returns a handle.
ui.createButton(options: HudButtonOptions): HudElementHandleCreate a clickable button on screen; options.onClick fires when the player clicks it. Returns a handle.
ui.createSlider(options: HudSliderOptions): HudElementHandleCreate a slider; options.onValueChanged fires with the new number when the player drags it. Returns a handle.
ui.createScrollbar(options: HudScrollbarOptions): HudElementHandleCreate a scrollbar (Unity Scrollbar) — a draggable sized handle; options.onValueChanged fires with the new 0..1 position as the player drags. Returns a handle.
ui.createToggle(options: HudToggleOptions): HudElementHandleCreate a checkbox toggle; options.onValueChanged fires with the new boolean. Returns a handle.
ui.createInput(options: HudInputOptions): HudElementHandleCreate a text input; options.onValueChanged fires with the new string on commit (blur/Enter). Returns a handle.
ui.createDropdown(options: HudDropdownOptions): HudElementHandleCreate a dropdown; options.onValueChanged fires with the newly-selected index when the player picks. Returns a handle.
ui.createContainer(options?: HudContainerOptions): HudElementHandle & { add(...children: HudElementHandle[]): HudElementHandle }Create a layout container (Unity LayoutGroup + ScrollRect). Its handle has add(...children) to nest existing HUD elements inside; the container's layout (vertical/horizontal/grid) + scroll arranges them.
ui.removeElement(id: string): voidRemove a HUD element by ID.

audio

MemberDescription
audio.play(soundId: string, position?: [number, number, number]): voidPlay a sound at a position.
audio.setGroupVolume(group: 'master' | 'music' | 'sfx' | 'ui', volume: number): voidSet a mixer group's volume (0+). Groups: 'master' | 'music' | 'sfx' | 'ui'. 'master' scales everything. Use it for music/SFX sliders and ducking (lower 'music' while dialogue plays).

tools

MemberDescription
tools.give(playerId: string, toolEntityId: string): voidGive a tool to a player. toolEntityId is an entity with a tool component.
tools.remove(playerId: string, instanceId: string): voidRemove a tool from a player's backpack by instance ID.
tools.equip(playerId: string, slotIndex: number): voidEquip a tool for a player by slot index.
tools.unequip(playerId: string): voidUnequip the player's current tool.
tools.getBackpack(playerId: string): BackpackToolRef[]Get the player's backpack contents.
tools.getEquipped(playerId: string): BackpackToolRef | nullGet the player's currently equipped tool, or null.
tools.clearBackpack(playerId: string): voidClear a player's entire backpack.

data

Generic per-player data store for any custom values.

MemberDescription
data.get(playerId: string, key: string): unknownGet a value for a player. Returns undefined if not set.
data.set(playerId: string, key: string, value: unknown): voidSet a value for a player.
data.increment(playerId: string, key: string, amount?: number): numberIncrement a numeric value. Returns the new value.
data.decrement(playerId: string, key: string, amount?: number): numberDecrement a numeric value (clamped to 0). Returns the new value.
data.getAll(playerId: string): Record<string, unknown>Get all data for a player as a record.
data.has(playerId: string, key: string): booleanCheck if a key exists for a player.
data.delete(playerId: string, key: string): voidDelete a key for a player.

economy

Currency management.

MemberDescription
economy.getCoins(playerId: string): numberGet a player's coin balance.
economy.setCoins(playerId: string, amount: number): voidSet a player's coin balance.
economy.addCoins(playerId: string, amount: number): numberAdd coins to a player. Returns new balance.
economy.removeCoins(playerId: string, amount: number): numberRemove coins from a player (clamped to 0). Returns new balance.
economy.canAfford(playerId: string, coins: number): booleanCheck if player can afford a cost.
economy.getCrystals(playerId: string): numberGet a player's crystal balance.
economy.setCrystals(playerId: string, amount: number): voidSet a player's crystal balance.
economy.addCrystals(playerId: string, amount: number): numberAdd crystals to a player. Returns new balance.
economy.removeCrystals(playerId: string, amount: number): numberRemove crystals (clamped to 0). Returns new balance.

agent

NavMesh agent control (pathfinding + steering) — drive AI from your script.

MemberDescription
agent.setDestination(entityId: string, position: [number, number, number]): voidPath to and steer toward a world position.
agent.getDestination(entityId: string): [number, number, number] | nullThe agent's current destination, or null.
agent.stop(entityId: string): voidStop the agent in place (keeps the destination; resume() continues).
agent.resume(entityId: string): voidResume movement after stop().
agent.isStopped(entityId: string): booleanWhether the agent is currently stopped.
agent.resetPath(entityId: string): voidClear the destination + path; the agent coasts to a halt.
agent.rebuildNavMesh(): voidRebuild the NavMesh walkability grid from the current scene (call after spawning/destroying an obstacle at runtime) and invalidate every agent's path so they repath. No entity id — it is global.
agent.hasPath(entityId: string): booleanWhether the agent has an active destination.
agent.remainingDistance(entityId: string): numberRemaining distance to the destination (Infinity when there is none).
agent.getVelocity(entityId: string): [number, number, number]The agent's current velocity (x, y, z).
agent.setSpeed(entityId: string, speed: number): voidOverride the agent's move speed at runtime (units/sec, Unity NavMeshAgent.speed).
agent.setAcceleration(entityId: string, accel: number): voidOverride acceleration at runtime (units/s², Unity NavMeshAgent.acceleration).
agent.setAngularSpeed(entityId: string, degPerSec: number): voidOverride turn rate at runtime (degrees/sec, Unity NavMeshAgent.angularSpeed).
agent.setAngularAcceleration(entityId: string, degPerSec2: number): voidOverride the turn-rate ramp at runtime (degrees/sec²; 0 = instant). Galatrix extra beyond Unity.
agent.setStoppingDistance(entityId: string, dist: number): voidOverride stopping distance at runtime (units, Unity NavMeshAgent.stoppingDistance).
agent.setAvoidancePriority(entityId: string, priority: number): voidOverride avoidance priority at runtime (0 most important … 99 least, Unity NavMeshAgent.avoidancePriority).
agent.setObstacleAvoidanceType(entityId: string, type: 'none' | 'low' | 'med' | 'good' | 'high'): voidOverride avoidance quality at runtime; 'none' disables avoidance (Unity NavMeshAgent.obstacleAvoidanceType).
agent.setRadius(entityId: string, radius: number): voidOverride the agent radius at runtime (Unity NavMeshAgent.radius).
agent.setAutoBraking(entityId: string, enabled: boolean): voidToggle arrival auto-braking at runtime (Unity NavMeshAgent.autoBraking).
agent.setAutoRepath(entityId: string, enabled: boolean): voidToggle periodic auto-repath at runtime (Unity NavMeshAgent.autoRepath).
agent.setUpdateRotation(entityId: string, enabled: boolean): voidWhen false, your script controls the agent's facing instead of the engine (Unity NavMeshAgent.updateRotation).
agent.setAreaMask(entityId: string, mask: number): voidSet which nav areas this agent may traverse (Unity NavMeshAgent.areaMask, a bitmask; -1 = all).
agent.setStopped(entityId: string, stopped: boolean): voidStop or resume the agent without clearing its path (settable Unity NavMeshAgent.isStopped).
agent.setVelocity(entityId: string, velocity: [number, number, number]): voidDrive the agent's velocity directly for one step (Unity NavMeshAgent.velocity setter).
agent.move(entityId: string, offset: [number, number, number]): voidMove the agent by a relative offset, clamped to the navmesh (Unity NavMeshAgent.Move).
agent.knockback(entityId: string, direction: [number, number, number] | { x: number; y: number; z: number }, force: number): voidKnock the agent back: launch it along direction (a Vector3 or [x,y,z]; y ignored) at force units/sec for a brief decaying window that overrides steering (a mini stun), then it resumes its path. For melee/explosion recoil. Halts against walls/navmesh edges so a hit can't punt it off the map. force ≤ 0 clears any active knockback.
agent.getSpeed(entityId: string): numberCurrent move-speed cap (Unity NavMeshAgent.speed).
agent.getAcceleration(entityId: string): numberCurrent acceleration (Unity NavMeshAgent.acceleration).
agent.getAngularSpeed(entityId: string): numberCurrent turn rate in degrees/sec (Unity NavMeshAgent.angularSpeed).
agent.getAngularAcceleration(entityId: string): numberCurrent turn-rate ramp in degrees/sec² (0 = instant). Galatrix extra beyond Unity.
agent.getStoppingDistance(entityId: string): numberCurrent stopping distance (Unity NavMeshAgent.stoppingDistance).
agent.getRadius(entityId: string): numberCurrent agent radius (Unity NavMeshAgent.radius).
agent.getAvoidancePriority(entityId: string): numberCurrent avoidance priority 0-99 (Unity NavMeshAgent.avoidancePriority).
agent.getObstacleAvoidanceType(entityId: string): 'none' | 'low' | 'med' | 'good' | 'high'Current avoidance quality (Unity NavMeshAgent.obstacleAvoidanceType).
agent.getAutoBraking(entityId: string): booleanWhether arrival auto-braking is on (Unity NavMeshAgent.autoBraking).
agent.getAutoRepath(entityId: string): booleanWhether periodic auto-repath is on (Unity NavMeshAgent.autoRepath).
agent.getUpdateRotation(entityId: string): booleanWhether the engine owns facing (Unity NavMeshAgent.updateRotation).
agent.getAreaMask(entityId: string): numberThe agent's nav-area bitmask (Unity NavMeshAgent.areaMask; -1 = all).
agent.getDesiredVelocity(entityId: string): [number, number, number]The velocity the agent WANTS this tick, before avoidance/accel limiting (Unity desiredVelocity).
agent.getSteeringTarget(entityId: string): [number, number, number] | nullThe next corner the agent steers toward (Unity NavMeshAgent.steeringTarget), or null.
agent.getNextPosition(entityId: string): [number, number, number]The simulated position the agent will move to (Unity NavMeshAgent.nextPosition).
agent.getPathCorners(entityId: string): [number, number, number][]The current path's corners as world points (Unity NavMeshAgent.path).
agent.getPathStatus(entityId: string): 'complete' | 'partial' | 'invalid'Route status: 'complete' | 'partial' | 'invalid' (Unity NavMeshAgent.pathStatus).
agent.pathPending(entityId: string): booleanWhether a path is still being computed — always false here, pathing is synchronous (Unity pathPending).
agent.isPathStale(entityId: string): booleanWhether the current path is stale — always false on a static navmesh (Unity isPathStale).
agent.isOnNavMesh(entityId: string): booleanWhether the agent stands on a walkable navmesh cell (Unity NavMeshAgent.isOnNavMesh).
agent.isOnOffMeshLink(entityId: string): booleanWhether the agent is mid-jump across an off-mesh / jump link (Unity NavMeshAgent.isOnOffMeshLink).
agent.hasAgent(entityId: string): booleanWhether an agent with this id exists (has a navMeshAgent component the engine is tracking). Call this before other agent.* methods — they return benign defaults for unknown/deleted entities.
agent.getMovementState(entityId: string): 'idle' | 'walk'The animation movement state the engine chose ('idle' | 'walk').
agent.calculatePath(entityId: string, target: [number, number, number]): { corners: [number, number, number][]; status: 'complete' | 'partial' | 'invalid'; links: number[] }Compute a path to a target WITHOUT moving the agent (Unity NavMeshAgent.CalculatePath). links lists the indices of corners that are off-mesh-link LANDINGS (the segment entering them is a jump).
agent.raycast(entityId: string, target: [number, number, number]): { blocked: boolean; point: [number, number, number] }Trace a straight navmesh line toward a target (Unity NavMeshAgent.Raycast).
agent.warp(entityId: string, position: [number, number, number]): voidTeleport the agent to a position and clear its current path.

Agent-less navmesh queries (Unity static NavMesh.* — sample/raycast/path against the grid).

MemberDescription
nav.samplePosition(position: [number, number, number]): [number, number, number] | nullNearest walkable point on the navmesh to position (Unity NavMesh.SamplePosition), or null.
nav.findClosestEdge(position: [number, number, number]): { point: [number, number, number]; distance: number } | nullClosest navmesh boundary (wall edge) point to position (Unity NavMesh.FindClosestEdge), or null.
nav.calculatePath(from: [number, number, number], to: [number, number, number]): { corners: [number, number, number][]; status: 'complete' | 'partial' | 'invalid'; links: number[] }Compute a path between two world points without an agent (Unity NavMesh.CalculatePath). links lists the indices of corners that are off-mesh-link LANDINGS — the segment from corner i-1 into corner i is a jump/drop across a gap, not a walked step, so a custom movement controller should arc that segment instead of ground-steering it.
nav.raycast(from: [number, number, number], to: [number, number, number]): { blocked: boolean; point: [number, number, number] }Trace a straight navmesh line (Unity NavMesh.Raycast); blocked = it hit a wall, point = last walkable spot.
nav.isWalkable(position: [number, number, number]): booleanWhether a world point is on the walkable navmesh.

particles

One-shot particle effects (explosions, hit sparks) at a world point. Client-side visual.

MemberDescription
particles.burst(position: [number, number, number] | { x: number; y: number; z: number }, options?: { count?: number // number of particles (default 24, capped ~400) color?: string // start color hex (default '#ffaa33') endColor?: string // fade-to color over lifetime size?: number // particle size (default 0.25) speed?: number // outward speed (default 6) lifetime?: number // seconds each particle lives (default 0.8) gravity?: number // Y acceleration (default -4) blending?: 'normal' | 'additive' // additive = glowy (default) }): voidSpawn a self-disposing particle burst at a world position — explosions, hit sparks, pickups — without authoring a prefab. All options are optional; the burst cleans itself up once the particles fade.

storage

Simple key-value store that persists across ticks (but not across sessions).

Type: Record<string, unknown>

debug

Debug logging — debug.log/warn/error (Unity Debug.Log/LogWarning/LogError route here too). Shows in the editor Console panel while play-testing (and standalone's browser console); STRIPPED from the published platform. Use it to trace map logic. (console.log is separate — native console, ships.)

MemberDescription
debug.log(...args: unknown[]): void
debug.warn(...args: unknown[]): void
debug.error(...args: unknown[]): void
debug.setEnabled(on: boolean): voidTurn debug logging on/off at runtime — affects standalone + the published platform (the editor is always on). Backed by the map's gameSettings.debugMode.
debug.enabled: booleanWhether debug logging is currently active for this runtime. (read-only)
debug.drawLine(start: unknown, end: unknown, color?: unknown, duration?: number): voidDraw a world-space debug line (backs Unity Debug.DrawRay/DrawLine). color = a hex string/number or a Color; duration in seconds (0 = one frame). Drawn in the editor + standalone, gated like the log sink.

Vector3

Unity Vector3 (also a [x,y,z] array): new Vector3(x,y,z), v.x, v.magnitude, Vector3.Distance(a,b).

Type: typeof Vector3

Quaternion

Unity Quaternion (also [x,y,z,w]): Quaternion.Euler(0,90,0), Quaternion.LookRotation(dir), Quaternion.Slerp.

Type: typeof Quaternion

Color

Unity Color (also [r,g,b,a], 0..1): new Color(1,0,0), Color.red, Color.fromHex('#ff8800').

Type: typeof Color

Mathf

Unity Mathf: Mathf.Clamp/Lerp/Sin/PI/Deg2Rad/PingPong/….

Type: typeof Mathf

Random

Unity Random: Random.Range(a,b), Random.value, Random.insideUnitSphere (seeded → deterministic).

Type: UnityRandom

Value types

The object shapes returned or accepted by the API above.

BackpackToolRef

FieldTypeDescription
instanceIdstring
toolEntityIdstring
namestring
toolTypestring
slotIndexnumber

CameraProjection

How the camera projects the world — the read side of Unity's Camera.orthographic / orthographicSize / nearClipPlane / farClipPlane / aspect.

FieldTypeDescription
orthographicbooleanTrue when the camera is orthographic (2D games, the pixel-perfect pipeline).
orthographicSizenumberHALF the vertical view height in world units (Unity's definition). 0 on a perspective camera.
nearClipPlanenumberDistance to the near clip plane.
farClipPlanenumberDistance to the far clip plane.
aspectnumberViewport width / height.

DeviceInfo

Device + display capabilities, read live from the host each frame.

FieldTypeDescription
mousePresentbooleanA fine pointer (mouse/trackpad) is present — Unity's Input.mousePresent.
touchSupportedbooleanThe display accepts touch — Unity's Input.touchSupported.
maxTouchPointsnumberSimultaneous touch points the hardware reports (0 = no touch). Unity: >1 ⇒ multiTouchEnabled.
dpinumberPixels per inch — Unity's Screen.dpi (0 when unknown).
orientation'portrait' | 'landscape'Unity's Screen.orientation, collapsed to the two that matter on the web.
fullScreenbooleanUnity's Screen.fullScreen.
safeArea[number, number, number, number]Unity's Screen.safeArea as [x, y, width, height] in PIXELS, bottom-left origin — the display area not covered by a notch or rounded corner. Equals the full screen rect when there are no insets.
isEditorbooleanTrue when running inside the editor's play-test rather than a published/standalone game (Unity's Application.isEditor).

EntityRef

FieldTypeDescription
idstring
namestring
tagstring
compareTag(tag: string): booleanbooleanCompare this ref's tag (Unity-style). The other in onCollision/onTriggerEnter is an EntityRef; for the player it is tagged 'Player', so onTriggerEnter(other){ if (other.compareTag('Player')) … }.
parentIdstring | null
layernumber
position[number, number, number]
rotation[number, number, number, number]
scale[number, number, number]
colorstring
visibleboolean
activebooleanWhether this entity is active (enabled). Inactive entities are hidden and skip updates.
bodyType'static' | 'dynamic' | 'kinematic'

GamepadInfo

A connected gamepad (Unity's Input.GetJoystickNames + joystick axes/buttons).

FieldTypeDescription
indexnumberSlot index — Unity's joystick number, 0-based.
namestringHardware id string (Unity's GetJoystickNames entry).
axesnumber[]Axis values −1..1, in the browser's standard-gamepad order (0/1 = left stick, 2/3 = right stick).
buttonsboolean[]Pressed state per button, in the browser's standard-gamepad order (0 = A/cross, 1 = B/circle, …).

HudBarOptions

FieldTypeDescription
playerIdstringMULTIPLAYER: scope to ONE player (Roblox PlayerGui parity — see HudLabelOptions.playerId).
valuenumber
position[number, number]
anchor[number, number]
barColorstring
barBgColorstring
widthnumber
heightnumber

HudButtonOptions

FieldTypeDescription
playerIdstringMULTIPLAYER: scope to ONE player (Roblox PlayerGui parity — see HudLabelOptions.playerId).
textstring
onClick() => void
position[number, number]
anchor[number, number]
widthnumber
heightnumber
fontSizenumber
fontColorstring
bgColorstring
borderRadiusnumber
highlightedColorstringBackground while hovered / pressed (Unity Button ColorTint). Unset → an automatic brightness tint.
pressedColorstring

HudContainerOptions

FieldTypeDescription
playerIdstringMULTIPLAYER: scope to ONE player (Roblox PlayerGui parity — see HudLabelOptions.playerId).
layout'vertical' | 'horizontal' | 'grid' | 'none'Child arrangement (Unity LayoutGroup). 'vertical'/'horizontal' = flex column/row; 'grid' uses columns; 'none' = children position themselves absolutely inside. Default 'vertical'.
gapnumberGap between children (px).
paddingnumberInner padding (px).
align'start' | 'center' | 'end' | 'stretch'Cross-axis alignment of children (flex align-items).
justify'start' | 'center' | 'end' | 'between' | 'around'Main-axis distribution of children (flex justify-content).
columnsnumberColumn count when layout='grid'.
scroll'none' | 'x' | 'y' | 'both'Overflow scrolling (Unity ScrollRect) — give the container a fixed width/height to scroll within.
clipbooleanClip children to the container box (Unity RectMask2D) — composes with borderRadius for rounded clips.
position[number, number]
anchor[number, number]
widthnumber
heightnumber
bgColorstring
borderRadiusnumber
opacitynumber
groupAlphanumberCanvasGroup: fade the whole group (multiplies opacity) — animate it to fade a panel in/out.
interactablebooleanCanvasGroup: false makes the group non-interactive (its children can't be clicked).
blocksRaycastsbooleanCanvasGroup: false lets clicks pass through the group to whatever is behind it.
fitContent'none' | 'width' | 'height' | 'both'Content Size Fitter: shrink-wrap the container to its children on the chosen axis.
aspectRationumberAspect Ratio Fitter: keep this width : height ratio.
minWidthnumberLayout Element: min size + flex-grow weight when this container is nested in another layout group.
minHeightnumber
flexGrownumber
parentstringNest this container inside another container.

HudDropdownOptions

FieldTypeDescription
playerIdstringMULTIPLAYER: scope to ONE player (Roblox PlayerGui parity — see HudLabelOptions.playerId).
optionsstring[]The choices shown in the dropdown.
onValueChanged(index: number) => voidFires with the newly-selected index (0-based) when the player picks an option.
valuenumberInitially-selected index (default 0).
position[number, number]
anchor[number, number]
widthnumber
fontSizenumber
fontColorstring
bgColorstring

HudElementHandle

FieldTypeDescription
idstring
set(props: Record<string, unknown>): voidvoidUpdate one or more properties of this HUD element.
remove(): voidvoidRemove this HUD element from the screen.
textstring
fontSizenumber
fontColorstring
fontWeight'normal' | 'bold'
textAlign'left' | 'center' | 'right'
richTextboolean
outlineColorstring
outlineWidthnumber
textShadowboolean
verticalAlign'top' | 'middle' | 'bottom'
valuenumber
barColorstring
bgColorstring
highlightedColorstring
pressedColorstring
visibleboolean
imageType'simple' | 'sliced' | 'tiled' | 'filled'
fillAmountnumber
fillMethod'horizontal' | 'vertical' | 'radial'
fillClockwiseboolean
preserveAspectboolean
sliceBordernumber | [number, number, number, number]
tileSizenumber
raycastTargetboolean
groupAlphanumber
interactableboolean
blocksRaycastsboolean
aspectRationumber
fitContent'none' | 'width' | 'height' | 'both'
minWidthnumber
minHeightnumber
flexGrownumber
onPointer((event: string) => void) | nullUnity EventTrigger — assign a handler to receive pointer + drag events over this element. The event name is the argument: 'enter' | 'exit' | 'down' | 'up' | 'click', plus the drag cycle 'beginDrag' | 'drag' | 'endDrag' and 'drop' (fired on the element under the cursor at release). Works on any element: const slot = ui.createPanel(...); slot.onPointer = (e) =&gt; { if (e === 'drop') acceptItem() }. Set to null to remove. Opting in makes the element receive pointer events (decorative UI stays click-through).

HudImageOptions

FieldTypeDescription
playerIdstringMULTIPLAYER: scope to ONE player (Roblox PlayerGui parity — see HudLabelOptions.playerId).
texturestringA project TEXTURE asset, by name or id — resolved client-side to the embedded image bytes.
urlstringRaw image src escape hatch (used when texture is absent).
position[number, number]
anchor[number, number]
widthnumber
heightnumber
mask'circle' | 'rounded'Clip to a shape (Unity's Mask): 'circle' = round crop, 'rounded' = borderRadius corners.
borderRadiusnumberCorner radius (px) when mask is 'rounded'. Default 8.
imageType'simple' | 'sliced' | 'tiled' | 'filled'Unity Image.Type — 'simple' (default) / 'sliced' (9-slice, corners keep their size while the middle stretches) / 'tiled' (repeat) / 'filled' (reveal only fillAmount via fillMethod — cooldowns, fill bars).
sliceBordernumber | [number, number, number, number]9-slice inset in px: a uniform number, or [top,right,bottom,left]. Default 12.
tileSizenumber'tiled': repeat tile size in px (default = the sprite's natural size).
fillMethod'horizontal' | 'vertical' | 'radial''filled': fill direction. Default 'horizontal'.
fillAmountnumber'filled': 0-1 fraction shown (Unity Image.fillAmount). Default 1.
fillClockwiseboolean'filled': reverse the fill origin/sweep (radial: counter-clockwise; linear: from the far edge).
preserveAspectbooleanKeep the sprite's aspect ratio (letterbox) instead of stretching to the rect (Preserve Aspect).
raycastTargetbooleanIntercept pointer rays — block clicks to whatever's behind it (Unity raycastTarget). Default false.

HudInputOptions

FieldTypeDescription
playerIdstringMULTIPLAYER: scope to ONE player (Roblox PlayerGui parity — see HudLabelOptions.playerId).
valuestringInitial text value.
placeholderstringPlaceholder shown when empty.
onValueChanged(value: string) => voidFires with the new string when the player commits the edit (blur / Enter).
position[number, number]
anchor[number, number]
widthnumber
fontSizenumber
fontColorstring
bgColorstring
contentType'standard' | 'integer' | 'decimal' | 'alphanumeric' | 'email' | 'password'Content type (Unity InputField) — filters typing / sets the field kind.
characterLimitnumberMax characters (Unity Character Limit).
multilinebooleanRender a multi-line textarea instead of a single line.

HudLabelOptions

FieldTypeDescription
textstring
playerIdstringMULTIPLAYER: a player ID to scope this element to (Roblox PlayerGui parity). Pass the id you get from players.getLocal().id, players.getAll()[i].id, or a server hook like onInteract(playerId) — the server then sends this element only to THAT player, so only they see it. It is an id string, not a username or index. Leave it out — or pass any falsy value (undefined, null, or '') — for a GLOBAL HUD shown to everyone (Roblox StarterGui). In single-player / standalone there is one local player, so it just renders. Every ui.createX option accepts playerId; label is the common case.
position[number, number]
anchor[number, number]
fontSizenumber
fontColorstring
fontWeight'normal' | 'bold'
textAlign'left' | 'center' | 'right'
wrapbooleanWrap into multiple lines within maxWidth px instead of one nowrap line.
maxWidthnumber
fontFamilystringCSS font-family stack, e.g. "Georgia, serif" or "monospace". Default system-ui.
richTextbooleanParse Unity rich-text markup in the text: &lt;b&gt;, &lt;i&gt;, &lt;u&gt;, &lt;color=#f00&gt;, &lt;size=24&gt;.
outlineColorstringDraw a filled outline behind the text in this colour (Unity's Outline effect).
outlineWidthnumberOutline thickness in px (default 1).
textShadowbooleanDrop shadow, on by default for readability; set false to remove it.
verticalAlign'top' | 'middle' | 'bottom'Vertical placement within the element's box (needs a height/frame to show).
bestFitbooleanBest Fit (Unity Text): shrink the font so the text fits the label's box, between bestFitMin and bestFitMax (or fontSize). Needs a bounded box — set width AND height for it to have an effect.
bestFitMinnumber
bestFitMaxnumber
widthnumberBox size in px — used by Best Fit as the bounded rect the text shrinks to fit.
heightnumber

HudPanelOptions

FieldTypeDescription
playerIdstringMULTIPLAYER: scope to ONE player (Roblox PlayerGui parity — see HudLabelOptions.playerId).
position[number, number]
anchor[number, number]
widthnumber
heightnumber
bgColorstring
borderRadiusnumber
opacitynumber

HudScrollbarOptions

FieldTypeDescription
playerIdstringMULTIPLAYER: scope to ONE player (Roblox PlayerGui parity — see HudLabelOptions.playerId).
valuenumberInitial handle position 0..1 (default 0).
onValueChanged(value: number) => voidFires with the new 0..1 position as the player drags the handle.
handleSizenumberHandle length as a fraction of the track 0..1 (Unity Scrollbar.size). Default 0.2.
direction'horizontal' | 'vertical'Scrollbar axis. Default 'horizontal'.
position[number, number]
anchor[number, number]
widthnumber
heightnumber
bgColorstring
barColorstring

HudSliderOptions

FieldTypeDescription
playerIdstringMULTIPLAYER: scope to ONE player (Roblox PlayerGui parity — see HudLabelOptions.playerId).
valuenumberInitial value (within [min, max]).
onValueChanged(value: number) => voidFires with the new number when the player drags the slider.
minnumber
maxnumber
stepnumber
position[number, number]
anchor[number, number]
widthnumber
bgColorstring
barColorstring

HudToggleOptions

FieldTypeDescription
playerIdstringMULTIPLAYER: scope to ONE player (Roblox PlayerGui parity — see HudLabelOptions.playerId).
valuebooleanInitial on/off state.
onValueChanged(value: boolean) => voidFires with the new boolean when the player toggles it.
labelstringOptional label shown next to the checkbox.
position[number, number]
anchor[number, number]
fontSizenumber
fontColorstring
barColorstring
groupstringA ToggleGroup id — toggles sharing it act like radio buttons (exactly one on).

PlayerRef

FieldTypeDescription
idstring
usernamestring
position[number, number, number]

RagdollHandle

What physics.createRagdoll returns — live handles to the spawned limbs.

FieldTypeDescription
partsEntityRef[]Every limb, parent-first (parts[0] is the pelvis).
rootEntityRef | nullThe pelvis (root) limb — apply impulses/forces here to move the whole ragdoll. Null if spawn failed.
idsstring[]The entity ids of every limb.
destroy(): voidvoidRemove the entire ragdoll (destroys every limb).

RagdollSpawnOptions

Tuning for physics.createRagdoll.

FieldTypeDescription
heightnumberTotal height in world units (a normal humanoid ≈ 1.8). Default 1.8.
massnumberTotal mass spread across the limbs. Default 70.
colorstringLimb colour (hex). Default a neutral skin grey.
tagstringTag applied to every limb. Default 'Ragdoll'.
layernumberCollision layer (0-31) for every limb. Default 0.

RaycastHit

What a physics.raycast / raycastAll / sphereCast hit returns. null (or an empty array for raycastAll) means nothing was hit within maxDistance.

FieldTypeDescription
entityIdstringThe entity id of the collider that was hit.
entityNamestringThe name of the hit entity (convenience — same as game.getEntity(entityId)?.name).
point[number, number, number]World-space point of contact [x, y, z].
normal[number, number, number]World-space surface normal at the contact [x, y, z] (unit length).
distancenumberHow far along the ray/sweep the hit is: for raycast the distance from origin to point; for sphereCast how far the sphere's CENTRE travelled before contact. 0 when the cast already overlaps a collider at origin (see overlapping) — a shape starting inside/touching geometry reports contact-at-start, so distance is a free-space gap ONLY when the cast begins clear.
overlappingbooleansphereCast only: true when the sphere was already touching/overlapping this collider at origin, so distance is 0 because of contact-at-start — NOT a measured gap. Lets you tell "already inside it" apart from a genuine zero gap (the reason a raw distance reads as hit/no-hit only). When true, offset origin back along -direction and cast again for the real gap, or treat it as blocked. normal still points away from a shallow contact surface (useful for backing off); on a DEEP overlap the normal degrades toward zero. Undefined for raycast.

ScriptMathCurveAPI

math.curve — interpolation along an arc or a spline, for the cases straight lerp gets visibly wrong.

FieldTypeDescription
slerpVec3(a: [number, number, number], b: [number, number, number], t: number): [number, number, number][number, number, number]Interpolate through the arc between two vectors instead of across it (Unity Vector3.Slerp); magnitude interpolates linearly. lerpVec3 on two directions shortens the vector mid-way.
catmullRom(p0: [number, number, number], p1: [number, number, number], p2: [number, number, number], p3: [number, number, number], t: number): [number, number, number][number, number, number]Catmull-Rom spline point at t (0..1) on the p1→p2 segment; p0/p3 are the neighbouring waypoints that shape the tangents. The curve passes THROUGH its control points — use it for camera rails.

ScriptMathGeoAPI

math.geo — ray/point/segment queries against pure geometry. Unlike physics.raycast, which hits COLLIDERS, these hit maths: use them for AI, targeting, gizmos and anything with no body in the scene.

FieldTypeDescription
closestPointOnSegment(p: [number, number, number], a: [number, number, number], b: [number, number, number]): [number, number, number][number, number, number]Nearest point to p on the segment a→b (clamped to the segment, not the infinite line).
rayPlane(origin: [number, number, number], dir: [number, number, number], planePoint: [number, number, number], planeNormal: [number, number, number]): MathRayHit | nullMathRayHit | nullWhere a ray meets an infinite plane, or null if parallel or behind the origin.
raySphere(origin: [number, number, number], dir: [number, number, number], center: [number, number, number], radius: number): MathRayHit | nullMathRayHit | nullWhere a ray meets a sphere, or null if it misses. An origin INSIDE the sphere returns the exit point.
rayAABB(origin: [number, number, number], dir: [number, number, number], boxMin: [number, number, number], boxMax: [number, number, number]): MathRayHit | nullMathRayHit | nullWhere a ray meets an axis-aligned box, or null if it misses. An origin inside the box gives distance 0 (matching Unity's Bounds.IntersectRay). Corners may be passed in either order.
pointInBox(p: [number, number, number], boxMin: [number, number, number], boxMax: [number, number, number]): booleanbooleanIs the point inside (or on) an axis-aligned box? Corners may be passed in either order.

TouchInfo

A single active touch — the engine's Unity-parity Touch. position/deltaPosition are in 0-1 screen coords (top-left origin), consistent with the rest of the input API (a swipe across the screen ≈ 1.0). Multiply by sensitivity for look/drag.

FieldTypeDescription
fingerIdnumberStable id for this finger across frames (Unity Touch.fingerId).
position[number, number]Touch position this frame, [x, y] in 0-1 screen coords (top-left origin).
deltaPosition[number, number]Movement since last frame, [dx, dy] in 0-1 screen units (Unity Touch.deltaPosition).
phase'began' | 'moved' | 'stationary' | 'ended' | 'canceled'Lifecycle this frame (Unity TouchPhase, lowercased): a touch is 'began' the frame it lands, 'moved'/'stationary' while held, then 'ended' (lifted) or 'canceled'.
tapCountnumberNumber of taps in quick succession (Unity Touch.tapCount).
pressurenumberFinger pressure 0..1 (Unity Touch.pressure / maximumPossiblePressure=1). 1 when the device can't measure it — matching Unity, which reports 1.0 on hardware without pressure support.
radiusnumberContact radius in PIXELS (Unity Touch.radius). 0 when the device doesn't report a contact size.
deltaTimenumberSeconds since this finger last moved (Unity Touch.deltaTime).