State machine: Ereignisse „On state entered“ / „On state exited“ #53

Closed
opened 2026-09-12 18:02:39 +02:00 by meleki · 1 comment
Owner

Aus #51, Folgeschritt: Ereignis-Nodes im Behavior, die feuern, wenn eine Maschine einen Zustand betritt oder verlässt.

Was heute ist: Set state schreibt nur ctx.states[machine] = entry und läuft weiter – niemand erfährt vom Wechsel. Die Event-Nodes (OnStart, OnKeyDown, OnTimer, OnCollisionEnter …) werden vom BehaviorSystem ausgelöst, nicht aus einem Node heraus.

Zu bauen:

  • On state entered / On state exited: machine-Eingang wie bei State branch (Picker oder State machine-Literal), ein Exec-Ausgang pro Zustand (abgeleitet wie statePorts), oder ein fester Ausgang plus state-Ausgang als Text.
  • Auslösung: Der Interpreter muss den Wechsel erkennen (Set state meldet ihn an den Kontext, das System feuert danach die passenden Events der gleichen Instanz – Zustand ist pro Behavior-Instanz).
  • Regeln: Feuert entered auch beim ersten Set state (aus „kein Zustand“)? Feuert bei Set state in den selben Zustand nichts (Vorschlag: nichts)?
  • Reihenfolge festlegen: erst exited des alten, dann entered des neuen, jeweils nach Abschluss des laufenden Exec-Flusses (kein Re-Entry mitten im Fluss).

Folge-Issue zu #51 (State machine, Commit e7d82bd, 2026-09-12).

Aus #51, Folgeschritt: Ereignis-Nodes im Behavior, die feuern, wenn eine Maschine einen Zustand betritt oder verlässt. **Was heute ist:** `Set state` schreibt nur `ctx.states[machine] = entry` und läuft weiter – niemand erfährt vom Wechsel. Die Event-Nodes (`OnStart`, `OnKeyDown`, `OnTimer`, `OnCollisionEnter` …) werden vom `BehaviorSystem` ausgelöst, nicht aus einem Node heraus. **Zu bauen:** - `On state entered` / `On state exited`: `machine`-Eingang wie bei `State branch` (Picker oder `State machine`-Literal), **ein Exec-Ausgang pro Zustand** (abgeleitet wie `statePorts`), oder ein fester Ausgang plus `state`-Ausgang als Text. - Auslösung: Der Interpreter muss den Wechsel erkennen (`Set state` meldet ihn an den Kontext, das System feuert danach die passenden Events der **gleichen** Instanz – Zustand ist pro Behavior-Instanz). - Regeln: Feuert `entered` auch beim ersten `Set state` (aus „kein Zustand“)? Feuert bei `Set state` in den **selben** Zustand nichts (Vorschlag: nichts)? - Reihenfolge festlegen: erst `exited` des alten, dann `entered` des neuen, jeweils nach Abschluss des laufenden Exec-Flusses (kein Re-Entry mitten im Fluss). --- Folge-Issue zu #51 (State machine, Commit `e7d82bd`, 2026-09-12).
meleki added the state-machine label 2026-09-12 18:02:39 +02:00
admin added the low-priority label 2026-09-12 18:13:26 +02:00
admin added this to the Development project 2026-09-13 13:29:59 +02:00
admin removed this from the Development project 2026-09-13 13:30:59 +02:00
admin added this to the Development project 2026-09-13 13:45:43 +02:00
admin moved this to Next in Development on 2026-09-14 21:44:14 +02:00
Author
Owner

Done in 7babf88.

On state entered and On state exited, each with a machine input and one exec output per state, the shape State branch and Set state already use. Underneath, every change now goes through a single setState that reports the move — before this, the two writers set the bag themselves and nobody could have heard it.

The decisions this needed, all of them in the wiki (84df59c) as well:

  • Who hears it follows the scope. A local machine is heard by the instance that moved it alone. A global one is heard by every instance with a matching event node — that is the point of sharing a state, and the issue's original "the same instance" was written before global existed.
  • The start state counts as entered (#55). Local: per instance, right after that instance's On start. Global: once for the whole run, before the first instance exists, so every instance created with the scene hears that one entry and an instance spawned later joins the machine where it already is, without an entered of its own.
  • A Set state into the state the machine is already in is no move — nothing written, nothing fired. That is what keeps a Set state that runs every frame from firing entered every frame.
  • Order and timing: exited of the old state, then entered of the new, and both after the exec flow that caused the move has finished, never in the middle of it. Moves the events themselves cause are delivered the same way, round after round until none are left; a graph whose events keep moving the machine stops the run with an endless-loop error, like the step limit.
  • A move a nested Run behavior makes to a local machine dies with the call and is not reported (that call has its own context); a move to a global one is a move like any other.

exited coming out of no state runs nothing — there is nothing to leave.

Covered by unit tests and by e2e step 26, which grew from 50 to 61 checks.

Done in 7babf88. **`On state entered`** and **`On state exited`**, each with a `machine` input and **one exec output per state**, the shape `State branch` and `Set state` already use. Underneath, every change now goes through a single `setState` that reports the move — before this, the two writers set the bag themselves and nobody could have heard it. The decisions this needed, all of them in the wiki (84df59c) as well: - **Who hears it follows the scope.** A local machine is heard by the instance that moved it alone. A global one is heard by **every** instance with a matching event node — that is the point of sharing a state, and the issue's original "the same instance" was written before `global` existed. - **The start state counts as entered** (#55). Local: per instance, right after that instance's `On start`. Global: **once for the whole run**, before the first instance exists, so every instance created with the scene hears that one entry and an instance spawned later joins the machine where it already is, without an `entered` of its own. - **A `Set state` into the state the machine is already in is no move** — nothing written, nothing fired. That is what keeps a `Set state` that runs every frame from firing `entered` every frame. - **Order and timing:** `exited` of the old state, then `entered` of the new, and both **after** the exec flow that caused the move has finished, never in the middle of it. Moves the events themselves cause are delivered the same way, round after round until none are left; a graph whose events keep moving the machine stops the run with an endless-loop error, like the step limit. - A move a nested `Run behavior` makes to a **local** machine dies with the call and is not reported (that call has its own context); a move to a global one is a move like any other. `exited` coming out of *no* state runs nothing — there is nothing to leave. Covered by unit tests and by e2e step 26, which grew from 50 to 61 checks.
admin moved this to Done in Development on 2026-09-15 06:21:35 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: meleki/feuerwerk#53