Home

Guide

How to script a physics simulation in JavaScript

In ThinkInsideTheBox a script is plain JavaScript that runs once per simulation frame. It reads objects from a global list and changes them through a handful of functions, so a bounce pad or a low-gravity zone takes three lines.

Updated 2026-11-02

1. Add a script

Open the editor, switch to the Scripts panel and add a new script. Press play: from then on the script runs every frame, and anything you log() shows up in the script console.

// Runs once: __state keeps values between frames.
if (!__state.started) {
  __state.started = true;
  log('Objects in the scene:', objects.length);
}

objects is every object in the scene, and __state is a plain object that survives from one frame to the next. Use it instead of global variables.

2. Read positions

Each object has an id, a name and a live currentPosition as [x, y, z].

objects.forEach(obj => {
  const [x, y, z] = obj.currentPosition;
  if (y < 0) warn(obj.name, 'fell through the floor');
});

3. Spawn objects on a timer

time is seconds since play started and delta is the length of this frame. This spawns a sphere once every two seconds:

if (Math.floor(time) % 2 === 0 && Math.floor(time) !== Math.floor(time - delta)) {
  const obj = addObject('sphere', 0, 6, 0, '#22d3ee');
  if (obj) log('Spawned', obj.name);
}

4. Build a bounce pad

An impulse is an instant push. Anything that lands near the middle of the floor gets launched back up:

objects.forEach(obj => {
  const [x, y, z] = obj.currentPosition;
  if (y < 0.6 && Math.abs(x) < 1.5 && Math.abs(z) < 1.5) {
    applyImpulse(obj.id, 0, 4, 0);
  }
});

If nothing launches, objects may rest a little higher than 0.6. Log a y value and adjust the check.

5. Add a low-gravity zone

setGravityScale changes gravity for one object: 0 floats, 1 is normal, -1 falls upward.

objects.forEach(obj => {
  const [x, y, z] = obj.currentPosition;
  setGravityScale(obj.id, z > 0 ? 0.2 : 1);
});

6. Make it tweakable

slider() adds a live control to the script card and returns its current value, so you can tune a mechanic while it runs:

const strength = slider('Bounce strength', 0, 10, 4);
objects.forEach(obj => {
  const [x, y, z] = obj.currentPosition;
  if (y < 0.6) applyImpulse(obj.id, 0, strength, 0);
});

What scripts can't do

Scripts run in a sandbox, a separate iframe and Web Worker. They can't make network requests or read your login session, cookies or browser storage. A script stuck in an endless loop is stopped without freezing the editor, and scripts that arrive in someone else's scene stay off until you confirm. The full list of functions, including torque, velocity and vertex editing, is in the scripting API reference.

Try it now

The editor opens in your browser. No setup, and no account needed to start.

Open the editor

Related