Aus #39 („Persistente Objekte gibt es bewusst nicht — Identität, Duplikate und Elternschaft sind eigene Fragen und gehören in ein eigenes Issue“).
Befund
Beim Load scene geht nur der SharedState hinüber (globale Variablen und Maschinen). Jedes Objekt der alten Szene wird zerstört, auch die Spielfigur, die HUD-Leiste oder ein Musik-Objekt.
Heute baut man solche Objekte in jeder Szene neu und schiebt ihren Zustand über globale Variablen.
Zu bauen (Vorschlag)
Objekt-Property Keep on scene load: Das Objekt (mit Kindern, Behaviors und deren lokalem Zustand) überlebt den Wechsel.
Tests: Objekt überlebt samt Variablenstand; On start feuert nicht erneut; Rapier-Body wird in die neue Welt übernommen.
Offen (mit Vorschlag)
Duplikate: Die neue Szene enthält dasselbe Objekt (gleiche Vorlage oder gleicher Name) auch. Vorschlag: das mitgebrachte gewinnt, das der neuen Szene wird nicht gebaut — Abgleich über die Objekt-Id der Vorlage.
Elternschaft: Ein persistentes Kind eines nicht persistenten Elternteils. Vorschlag: nur Wurzelobjekte können persistent sein.
Rückkehr in die Ursprungsszene: Vorschlag: wie Punkt 1.
Aus #39 („Persistente Objekte gibt es bewusst nicht — Identität, Duplikate und Elternschaft sind eigene Fragen und gehören in ein eigenes Issue“).
## Befund
- Beim `Load scene` geht nur der `SharedState` hinüber (globale Variablen und Maschinen). Jedes Objekt der alten Szene wird zerstört, auch die Spielfigur, die HUD-Leiste oder ein Musik-Objekt.
- Heute baut man solche Objekte in jeder Szene neu und schiebt ihren Zustand über globale Variablen.
## Zu bauen (Vorschlag)
- Objekt-Property **Keep on scene load**: Das Objekt (mit Kindern, Behaviors und deren lokalem Zustand) überlebt den Wechsel.
- Tests: Objekt überlebt samt Variablenstand; `On start` feuert nicht erneut; Rapier-Body wird in die neue Welt übernommen.
## Offen (mit Vorschlag)
1. **Duplikate:** Die neue Szene enthält dasselbe Objekt (gleiche Vorlage oder gleicher Name) auch. Vorschlag: das mitgebrachte gewinnt, das der neuen Szene wird nicht gebaut — Abgleich über die Objekt-Id der Vorlage.
2. **Elternschaft:** Ein persistentes Kind eines nicht persistenten Elternteils. Vorschlag: nur Wurzelobjekte können persistent sein.
3. **Rückkehr in die Ursprungsszene:** Vorschlag: wie Punkt 1.
meleki
added the new label 2026-09-19 11:41:51 +02:00
Done in 1aa824e, wiki b2d413b (Scenes, Architecture, Concepts, Sounds, Development).
What is new
Switch Keep on scene load, right under Enabled, on the asset and on a placed object, off by default. A top-level object with the switch survives a Load scene and moves into the next scene with everything below it:
it is the same object, with position, properties and variables as the run has them
its behaviors run on: no On destroy, no second On start, and a sound they play is not cut off
a running animation plays on
a dynamic rigidbody keeps its velocity and spin
Only top-level objects (answer to point 2): the inspector shows the row on top-level objects of a scene only. Further down the value counts for nothing.
Duplicates (points 1 and 3)
The object that was brought along wins. The next scene does not build two kinds of its own objects:
an object with the same id. That is the way back into the scene the object came from, and it gives one object, not two.
a top-level object of the same asset that is kept itself. So every level can place its own Player, and after a swap there is still exactly one. Objects of that asset without the switch are built as usual.
The second rule is my reading. The issue says "Abgleich über die Objekt-Id der Vorlage", and the id alone would have given two players as soon as level 2 places its own. Going back to the id only would be one line.
A reference in the next scene to its own object that was left out finds the one that came instead. That covers the object itself, not its children.
A finding, fixed along with it Load scene did not build a scene as it is stored, but as the run had left it. Measured before the change: a moved object stayed moved after loading the scene again, a destroyed one stayed gone. The wiki said "rebuilt".
The run now remembers each scene before it first builds it and puts it back before it builds it again. The way back into the scene an object came from needs that.
In a released game the run gives every scene back on stop. Before, spawned objects stayed for "Click to play again".
The consequence: an edit made in a scene during Play is gone the next time that scene is loaded.
Decided here
Kept objects land behind the next scene's own objects.
The switch is not offered as an animation row.
Collisions are found anew. Two kept objects that were touching get their Enter again.
In the first frame after the swap a falling body stands still for one frame, then falls on with its old velocity.
Under the hood
src/runtime/keptObjects.ts holds the rules as pure functions: keptEntities, objectsToBring, bringObjects.
World.instantiate takes a handed entity as it is instead of making one. BehaviorSystem.release and adopt hand the running instances over, PhysicsSystem.resume the movement of the bodies.
GameRun copies a scene's objects and groups before the first build, GameRun.end puts every scene back.
15 unit tests in tests/core/keep-on-scene-load.test.ts, 13 for the switch and 2 for the clean build.
Six e2e checks in module 35: the switch is set with a real mouse, the child has no row. After the swap the object is in the new scene, its counter still reads 1, and its sound plays on. After Stop the stored scenes are unchanged.
Eleven tests with fixed row lists only count the new schema row.
Screenshot looked at: the Game view shows three boxes after the swap, the child has no row in the inspector.
Counter-check
Result
16 in the unit tests
all work in the end
Browser, build went through
4 of the 6 new checks fail
One unit counter-check did not work at first (same id not left out): the world drops doubles by id, but the scene would have held the object twice. It has its own test now.
The unit counter-checks ran on stein2, not in the container.
The 1619 before this change are measured (CI run 277 for 3e8c88c is green). CI run 278 for 1aa824e was not waited for.
Not looked at in the browser: the switch as a port of the Properties node (the wiki says so from the code), and a released game with a kept object.
Done in `1aa824e`, wiki `b2d413b` (*Scenes*, *Architecture*, *Concepts*, *Sounds*, *Development*).
**What is new**
- Switch **Keep on scene load**, right under *Enabled*, on the asset and on a placed object, off by default. A top-level object with the switch survives a `Load scene` and moves into the next scene with everything below it:
- it is the same object, with position, properties and variables as the run has them
- its behaviors run on: no `On destroy`, no second `On start`, and a sound they play is not cut off
- a running animation plays on
- a dynamic rigidbody keeps its velocity and spin
- **Only top-level objects** (answer to point 2): the inspector shows the row on top-level objects of a scene only. Further down the value counts for nothing.
**Duplicates (points 1 and 3)**
The object that was brought along wins. The next scene does not build two kinds of its own objects:
- an object with **the same id**. That is the way back into the scene the object came from, and it gives one object, not two.
- a top-level object of **the same asset that is kept itself**. So every level can place its own `Player`, and after a swap there is still exactly one. Objects of that asset without the switch are built as usual.
The second rule is my reading. The issue says "Abgleich über die Objekt-Id der Vorlage", and the id alone would have given two players as soon as level 2 places its own. Going back to the id only would be one line.
A reference in the next scene to its own object that was left out finds the one that came instead. That covers the object itself, not its children.
**A finding, fixed along with it**
`Load scene` did not build a scene as it is stored, but as the run had left it. Measured before the change: a moved object stayed moved after loading the scene again, a destroyed one stayed gone. The wiki said "rebuilt".
- The run now remembers each scene before it first builds it and puts it back before it builds it again. The way back into the scene an object came from needs that.
- In a released game the run gives every scene back on stop. Before, spawned objects stayed for "Click to play again".
- The consequence: an edit made in a scene during Play is gone the next time that scene is loaded.
**Decided here**
- Kept objects land behind the next scene's own objects.
- The switch is not offered as an animation row.
- Collisions are found anew. Two kept objects that were touching get their `Enter` again.
- In the first frame after the swap a falling body stands still for one frame, then falls on with its old velocity.
**Under the hood**
- `src/runtime/keptObjects.ts` holds the rules as pure functions: `keptEntities`, `objectsToBring`, `bringObjects`.
- `World.instantiate` takes a handed entity as it is instead of making one. `BehaviorSystem.release` and `adopt` hand the running instances over, `PhysicsSystem.resume` the movement of the bodies.
- `GameRun` copies a scene's objects and groups before the first build, `GameRun.end` puts every scene back.
**Tests** (on `melektaus-atx`)
```
gate 199 files, 2944 tests, CHECK EXIT 0 (2929 + 15)
e2e (full) ALL PASSED - 1625 checks, E2E EXIT 0 (1619 + 6)
smokes 24 / 19 / 21, SMOKES EXIT 0
```
- 15 unit tests in `tests/core/keep-on-scene-load.test.ts`, 13 for the switch and 2 for the clean build.
- Six e2e checks in module 35: the switch is set with a real mouse, the child has no row. After the swap the object is in the new scene, its counter still reads 1, and its sound plays on. After Stop the stored scenes are unchanged.
- Eleven tests with fixed row lists only count the new schema row.
- Screenshot looked at: the Game view shows three boxes after the swap, the child has no row in the inspector.
| Counter-check | Result |
|---|---|
| 16 in the unit tests | all work in the end |
| Browser, build went through | 4 of the 6 new checks fail |
- One unit counter-check did not work at first (same id not left out): the world drops doubles by id, but the scene would have held the object twice. It has its own test now.
- The unit counter-checks ran on stein2, not in the container.
- The 1619 before this change are measured (CI run 277 for `3e8c88c` is green). CI run 278 for `1aa824e` was not waited for.
- Not looked at in the browser: the switch as a port of the `Properties` node (the wiki says so from the code), and a released game with a kept object.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Aus #39 („Persistente Objekte gibt es bewusst nicht — Identität, Duplikate und Elternschaft sind eigene Fragen und gehören in ein eigenes Issue“).
Befund
Load scenegeht nur derSharedStatehinüber (globale Variablen und Maschinen). Jedes Objekt der alten Szene wird zerstört, auch die Spielfigur, die HUD-Leiste oder ein Musik-Objekt.Zu bauen (Vorschlag)
On startfeuert nicht erneut; Rapier-Body wird in die neue Welt übernommen.Offen (mit Vorschlag)
Done in
1aa824e, wikib2d413b(Scenes, Architecture, Concepts, Sounds, Development).What is new
Load sceneand moves into the next scene with everything below it:On destroy, no secondOn start, and a sound they play is not cut offDuplicates (points 1 and 3)
The object that was brought along wins. The next scene does not build two kinds of its own objects:
Player, and after a swap there is still exactly one. Objects of that asset without the switch are built as usual.The second rule is my reading. The issue says "Abgleich über die Objekt-Id der Vorlage", and the id alone would have given two players as soon as level 2 places its own. Going back to the id only would be one line.
A reference in the next scene to its own object that was left out finds the one that came instead. That covers the object itself, not its children.
A finding, fixed along with it
Load scenedid not build a scene as it is stored, but as the run had left it. Measured before the change: a moved object stayed moved after loading the scene again, a destroyed one stayed gone. The wiki said "rebuilt".Decided here
Enteragain.Under the hood
src/runtime/keptObjects.tsholds the rules as pure functions:keptEntities,objectsToBring,bringObjects.World.instantiatetakes a handed entity as it is instead of making one.BehaviorSystem.releaseandadopthand the running instances over,PhysicsSystem.resumethe movement of the bodies.GameRuncopies a scene's objects and groups before the first build,GameRun.endputs every scene back.Tests (on
melektaus-atx)tests/core/keep-on-scene-load.test.ts, 13 for the switch and 2 for the clean build.3e8c88cis green). CI run 278 for1aa824ewas not waited for.Propertiesnode (the wiki says so from the code), and a released game with a kept object.