Scripts let you do what static settings can't.
A per-frame script runs every tick of the simulation. It can read object positions, set velocities, react to events, and count things. The scripting API gives you onFrame(dt, time) as the entry point. Inside, you can call getBody(name) and setVelocity(body, [vx, vy, vz]).
The pattern: a fired boolean that starts false. When time exceeds 1.0 and fired is false, set the ball's velocity and flip fired to true. The ball launches exactly once, one second into the simulation.
Open the studio with your cannon scene.
Load the scene you built in Lesson 12. Open the Script panel (the code icon in the sidebar). You'll see a text editor for per-frame JavaScript.
How do you fire exactly once?
If you set velocity every frame, the ball never accelerates under gravity because you keep resetting it. You need to fire only once. What pattern achieves this?
Reveal the pattern
let fired = false; function onFrame(dt, time) { if (!fired && time > 1.0) { fired = true; setVelocity('cannonball', [10, 5, 0]); } }
Write and run the script.
Paste or type the firing script. Press play. At t = 1 second, the ball should launch. Watch it arc into the wall.
Count fallen bricks.
Challenge: Extend the script to count how many bricks have fallen below y = 0.1 after the impact. Print the count to the console each frame (you'll see it in the script console panel). Target: more than 5 bricks down.
Hint
// After the firing logic: let fallen = 0; for (let i = 0; i < 24; i++) { const brick = getBody('brick_' + i); if (brick && brick.position.y < 0.1) fallen++; } console.log('Fallen:', fallen);
Your script fires the cannon at t = 1s and counts bricks. The physics engine handles the rest. Mark complete when your wall is satisfyingly destroyed.