Behaviors: lifecycle events On enable, On disable, On destroy (#42)

admin committed 2026-09-12 21:21:24 +02:00
1 parent 293cc2b4ca
commit e3e65b951a
3 files changed
+18 -4

No files matched your search

+15 -2
@@ -88,7 +88,7 @@ shown on the node and editable in the inspector.
sideways slide of a Tetris piece, or a held arrow walking a menu. The browser's own key repeat is sideways slide of a Tetris piece, or a held arrow walking a menu. The browser's own key repeat is
deliberately not used: its delay and rate are an operating-system setting, not a game's. Both deliberately not used: its delay and rate are an operating-system setting, not a game's. Both
rows stay off the node body while the delay is 0, so a plain key node keeps its single line. rows stay off the node body while the delay is 0, so a plain key node keeps its single line.
- **Node set** (`src/core/graph/nodes/`, one file per node): events `On start`, `On update`, `On key down/up/held`, - **Node set** (`src/core/graph/nodes/`, one file per node): events `On start`, `On enable`, `On update`, `On disable`, `On destroy` (see *Lifecycle*), `On key down/up/held`,
`On timer`, `On collision enter/stay/exit`, `On click` (the mouse pressed on the owner — anywhere when it has none), `On animation finished`, `Start` · flow `Branch`, `Sequence`, `Repeat`, `Run behavior`, `End` · data `Self`, `Owner`, `Parent`, `Object by name`, `Name of`, `On timer`, `On collision enter/stay/exit`, `On click` (the mouse pressed on the owner — anywhere when it has none), `On animation finished`, `Start` · flow `Branch`, `Sequence`, `Repeat`, `Run behavior`, `End` · data `Self`, `Owner`, `Parent`, `Object by name`, `Name of`,
`Is asset` (is this object an instance of asset X — how you tell what you collided with), `Is asset` (is this object an instance of asset X — how you tell what you collided with),
`Variables`, `Properties`, `Get position` (local and world), `Is enabled`, literals `Number`/`Text`/`Boolean`/`Texture`, `Add/Subtract/Multiply/Divide`, `Variables`, `Properties`, `Get position` (local and world), `Is enabled`, literals `Number`/`Text`/`Boolean`/`Texture`, `Add/Subtract/Multiply/Divide`,
@@ -247,7 +247,20 @@ shown on the node and editable in the inspector.
running the same behavior it is the one that produced last; in a loop, the last round. An running the same behavior it is the one that produced last; in a loop, the last round. An
output nothing has asked for yet shows nothing. The graph stays editable meanwhile: the interpreter reads the runtime output nothing has asked for yet shows nothing. The graph stays editable meanwhile: the interpreter reads the runtime
copy's graph on every pulse, so an edit takes effect on the next frame and is discarded with copy's graph on every pulse, so an edit takes effect on the next frame and is discarded with
the run. A new `On start` node does not fire for a behavior that has already started. the run. A new `On start` node does not fire for a behavior that has already started: `On start`
is asked once, when the instance comes to be (see *Lifecycle*).
- **Lifecycle**: a behavior gets its instance when it is effectively on — itself and every parent
switched on (and, in the editor run, "run in editor" set): at play start, when spawned, or the
moment a hidden screen is shown. The events come in this order: `On start` → `On enable` →
`On update` … → `On disable` → `On destroy`. `On start` runs once per instance. `On enable` runs
right after it and again every time the behavior comes back on; `On disable` runs in the frame it
goes off, a parent's switch included. Off, the instance is frozen, not gone: variables, timers and
states survive, and switching it on again is `On enable`, not `On start`. `On destroy` runs when
the object leaves the world — through `Destroy`, as a child of a destroyed object, and when the
game stops or restarts; a restart is therefore `On disable` → `On destroy` → (new world) `On start`
→ `On enable`. The frame that destroys an object still runs to its end, the two farewell events
follow at the end of it; an object destroyed while off gets `On destroy` alone. Off and on again
within one frame is no edge: neither event fires.
- **Runtime**: `BehaviorSystem` creates one `GraphInterpreter` per behavior entity; graphs only - **Runtime**: `BehaviorSystem` creates one `GraphInterpreter` per behavior entity; graphs only
touch world entities. A runaway pulse throws (see *Loops* for the two limits) and stops play touch world entities. A runaway pulse throws (see *Loops* for the two limits) and stops play
with a notice. with a notice.
+1 -1
@@ -4,7 +4,7 @@
| **Texture** | An uploaded image. Scenes, textures, animations and state machines are the four types that cannot be placed: a texture has no position, it is *worn* by a sprite through the ordinary property `texture`. See [Textures](Textures). | | **Texture** | An uploaded image. Scenes, textures, animations and state machines are the four types that cannot be placed: a texture has no position, it is *worn* by a sprite through the ordinary property `texture`. See [Textures](Textures). |
| **State machine** | A named set of **states**, edited as nodes in its own tab. A behavior puts it into a state with `Set state` and branches on it with `State branch`; each behavior instance keeps its own current state. See [State machines](State-machines). | | **State machine** | A named set of **states**, edited as nodes in its own tab. A behavior puts it into a state with `Set state` and branches on it with `State branch`; each behavior instance keeps its own current state. See [State machines](State-machines). |
| **Text** | An asset that draws a line of text (`text`, `fontSize`, `color`, `align`) — titles, HUD readouts, button labels. Its content is an ordinary property, so a `Properties` node of type Text with `text` switched to Set changes it while playing. | | **Text** | An asset that draws a line of text (`text`, `fontSize`, `color`, `align`) — titles, HUD readouts, button labels. Its content is an ordinary property, so a `Properties` node of type Text with `text` switched to Set changes it while playing. |
| **Enabled** | Every placeable asset has the switch `enabled` (default on). A disabled object is not drawn, does not collide and its behavior does not run — **and neither does anything parented below it**. Switching one instance off is a normal override, which makes a container a *screen*: switch it on to show it, off to hide it. From a graph, `Properties` with `enabled` switched to Set does it, and `Is enabled` asks (including the parents). | | **Enabled** | Every placeable asset has the switch `enabled` (default on). A disabled object is not drawn, does not collide and its behavior does not run — **and neither does anything parented below it**. Switching one instance off is a normal override, which makes a container a *screen*: switch it on to show it, off to hide it. From a graph, `Properties` with `enabled` switched to Set does it, and `Is enabled` asks (including the parents); a behavior hears the switch as `On enable` / `On disable`. |
| **Scene object** | An asset placed into a scene: a link to the asset + a **position** (`x`, `y`, `z`) + sparse **overrides** of the asset's properties + an optional **parent** (another object of the scene). Scenes cannot be placed. | | **Scene object** | An asset placed into a scene: a link to the asset + a **position** (`x`, `y`, `z`) + sparse **overrides** of the asset's properties + an optional **parent** (another object of the scene). Scenes cannot be placed. |
| **Container** | A reusable group ("prefab"): the asset holds a **template** of objects (asset link, local position, overrides, parent links) centred on its origin. Placing a container stores the container object **and nothing else** — its content is resolved from the template on every read, so a template edit reaches every instance at once. **Create container** turns the current selection into such an asset: the selected objects move into the template and the scene keeps one placed container at their centre (world positions unchanged). The template is edited in the **Container** tab (see [Containers](Containers)) or from an instance through **Apply to container**. | | **Container** | A reusable group ("prefab"): the asset holds a **template** of objects (asset link, local position, overrides, parent links) centred on its origin. Placing a container stores the container object **and nothing else** — its content is resolved from the template on every read, so a template edit reaches every instance at once. **Create container** turns the current selection into such an asset: the selected objects move into the template and the scene keeps one placed container at their centre (world positions unchanged). The template is edited in the **Container** tab (see [Containers](Containers)) or from an instance through **Apply to container**. |
| **Selection** | One or more scene objects. Click selects, `Ctrl`/`Shift`-click adds/removes, dragging on empty scene space draws a rubber band (objects whose position lies inside are selected). Dragging a selected object moves the whole selection; `Delete` removes it; the inspector offers **Create container** and **Remove** for several objects. | | **Selection** | One or more scene objects. Click selects, `Ctrl`/`Shift`-click adds/removes, dragging on empty scene space draws a rubber band (objects whose position lies inside are selected). Dragging a selected object moves the whole selection; `Delete` removes it; the inspector offers **Create container** and **Remove** for several objects. |
+2 -1
@@ -56,7 +56,8 @@ switched on and off. It keeps working while it is off in one important way: `Obj
still finds it, so a graph can switch it back on. A behavior inside a disabled screen has no still finds it, so a graph can switch it back on. A behavior inside a disabled screen has no
interpreter yet — it gets one, and its `On start`, the moment the screen is switched on, which interpreter yet — it gets one, and its `On start`, the moment the screen is switched on, which
makes "the screen initialises itself when shown" the default. Its variables survive being makes "the screen initialises itself when shown" the default. Its variables survive being
switched off and on again. A switched-off object is hidden in the Scene tab as well, so the switched off and on again; every later show fires `On enable`, every hide `On disable` (see
[Behaviors](Behaviors), *Lifecycle*). A switched-off object is hidden in the Scene tab as well, so the
editor shows what the game shows — selected, it keeps a faint outline, so where it sits is still editor shows what the game shows — selected, it keeps a faint outline, so where it sits is still
visible, but it cannot be dragged. It stays listed in the hierarchy panel, which is where it is visible, but it cannot be dragged. It stays listed in the hierarchy panel, which is where it is
selected and switched back on. selected and switched back on.