Script structure and lifecycle
The engine calls a script's functions at set times. This page explains when each function is called and what this refers to inside those functions.
Skeleton
// 1. Create the script type. The name appears in the SCRIPT component
var Spin = ow.createScript('spin');
// 2. Attributes: values you can change in the SCRIPT component
Spin.attributes.add('speed', { type: 'number', default: 90 });
// 3. Once, at start
Spin.prototype.initialize = function () {
this.turned = 0;
};
// 4. Every frame
Spin.prototype.update = function (dt) {
this.entity.rotate(0, this.speed * dt, 0);
this.turned += this.speed * dt;
};
On 2026-10-29, we created a script with this code in a launched game, attached it to an entity and ran it. After 1 second, turned was 90.0 and the entity's Y rotation was 90.0. Because speed (90 degrees per second) is multiplied by dt, the entity turns 90 degrees per second regardless of frame rate.
When functions are called
| Function | When it's called | Typical use |
|---|---|---|
initialize | Once, when the entity the script is attached to is first enabled. The comment in a new file says "runs once per entity" | Set up variables, connect events (on) |
postInitialize | Once, after every script's initialize has finished | Work that needs other entities' scripts to be ready |
update(dt) | Every frame. dt is the number of seconds since the last frame | Movement, input checks, timers |
postUpdate(dt) | Every frame, after every update has finished | Work that should happen after other entities move, such as a following camera |
swap(old) | When code is edited and reloaded while running | Moving the previous state into the new script. New files include it as a comment |
In our test, the four functions were first called in the order initialize → postInitialize → update → postUpdate (1 run).
Always multiply movement by dt. Otherwise, objects move faster on devices with a higher refresh rate.
What this refers to
| Code | Refers to |
|---|---|
this.entity | The entity the script is attached to. Gives you access to its components, such as this.entity.collision and this.entity.sound |
this.app | The whole game. Gives you access to input (this.app.keyboard), the top of the scene (this.app.root) and the asset list (this.app.assets) |
this.attributeName | An attribute value. If you declared attributes.add('speed', …), it's this.speed |
Events and cleanup
Scripts and entities also fire events.
this.on('enable', …),this.on('disable', …): when the script is turned on or off.this.on('destroy', …): when the entity is destroyed. Remove events you connected withthis.app.onhere usingoff. If you don't, functions on the destroyed entity may keep being called.
In our test, setting the script's enabled to false fired disable, and setting it back to true fired enable. Destroying the entity with destroy() fired disable first, followed by destroy (1 run).
Script names
You can't use names the engine has reserved in ow.createScript. In our test, ow.createScript('move') raised the error Script name 'move' is reserved, please rename the script. If you get this error, rename the script, for example to sideMove.
On 2026-10-30 we tried names one by one in a launched game. These 33 names were reserved: system, entity, create, destroy, swap, move, data, scripts, _scripts, _scriptsIndex, _scriptsData, enabled, _oldState, onEnable, onDisable, onPostStateChange, _onSetEnabled, _checkState, _onBeforeRemove, _onInitializeAttributes, _onInitialize, _onPostInitialize, _onUpdate, _onPostUpdate, _callbacks, _callbackActive, has, get, on, off, fire, once, hasEvent. Names that match function or component names, such as update, initialize, jump, player, name, app, camera, input, sound, render and collision, worked.
Order of multiple scripts
- If an entity has several scripts, they are called from top to bottom in the SCRIPT component. Reorder them with the handle on the left of each row. In a test on 2026-10-30, with
lifeBon top andlifeAbelow, the calls came in the order Binitialize→ Ainitialize→ Bupdate→ Aupdate, and later frames also ran B, then A (1 run). - The order in which files load is in SETTINGS under SCRIPTS LOADING ORDER. You only need to care about it when a script uses global variables from another file.