Dynamic Bodies fallen, prallen ab und liegen. Aus dem Graph lassen sie sich aber nur versetzen: Move ohne Kollision setzt die Position, der Body behält dabei seine Geschwindigkeit.
PhysicsSystem hat schon velocityOf(owner) und setVelocity(owner, v), beides in Welteinheiten pro Sekunde. Bisher nutzen das nur die Unit-Tests.
Move mit „Collide with solids“ läuft weiter über das eigene Move-and-Slide (runtime/systems/solids.ts). Ein Dynamic Body blockiert es wie eine Wand, schieben lässt er sich damit also nicht.
Zu bauen
Nodes:Apply force, Apply impulse, Set velocity, Get velocity, Set angular velocity, Set gravity (Scene). Alle Größen in Welteinheiten, die Umrechnung macht engine.ts.
Move mit „Collide with solids“ läuft über Rapiers KinematicCharacterController: Gleiten an Wänden, Schrägen, Stufen, und Dynamic Bodies, die dabei im Weg stehen, bekommen einen Stoß. Ohne Rigidbody und bei Kinematic wie bisher (#146, Antwort 3 in #144).
Move auf einem Dynamic Body (Antwort 3 in #146): Das Objekt wird versetzt, die Geschwindigkeit bleibt. Beim ersten Mal steht ein Hinweis in der Console, dass Force, Impulse und Velocity der Weg sind.
Offen
Welche Unterschiede zu Move-and-Slide der Character-Controller im Nachkommabereich macht (Smokes, e2e 08/40). Jede umgestellte Zahl kommt in den Abschlusskommentar.
Zweiter Teil von #146 (Aufteilung laut Antwort 1 dort). Voraussetzung: #146 (Rigidbody, Material, Schwerkraft, `PhysicsSystem`).
## Stand nach #146
- Dynamic Bodies fallen, prallen ab und liegen. Aus dem Graph lassen sie sich aber nur versetzen: `Move` ohne Kollision setzt die Position, der Body behält dabei seine Geschwindigkeit.
- `PhysicsSystem` hat schon `velocityOf(owner)` und `setVelocity(owner, v)`, beides in Welteinheiten pro Sekunde. Bisher nutzen das nur die Unit-Tests.
- `Move` mit „Collide with solids“ läuft weiter über das eigene Move-and-Slide (`runtime/systems/solids.ts`). Ein Dynamic Body blockiert es wie eine Wand, schieben lässt er sich damit also nicht.
## Zu bauen
- **Nodes:** `Apply force`, `Apply impulse`, `Set velocity`, `Get velocity`, `Set angular velocity`, `Set gravity` (Scene). Alle Größen in Welteinheiten, die Umrechnung macht `engine.ts`.
- **`Move` mit „Collide with solids“** läuft über Rapiers `KinematicCharacterController`: Gleiten an Wänden, Schrägen, Stufen, und Dynamic Bodies, die dabei im Weg stehen, bekommen einen Stoß. Ohne Rigidbody und bei Kinematic wie bisher (#146, Antwort 3 in #144).
- **`Move` auf einem Dynamic Body** (Antwort 3 in #146): Das Objekt wird versetzt, die Geschwindigkeit bleibt. Beim ersten Mal steht ein Hinweis in der Console, dass Force, Impulse und Velocity der Weg sind.
## Offen
- Welche Unterschiede zu Move-and-Slide der Character-Controller im Nachkommabereich macht (Smokes, e2e 08/40). Jede umgestellte Zahl kommt in den Abschlusskommentar.
admin
added this to the Development project 2026-09-18 18:01:02 +02:00
admin
moved this to Next in Development on 2026-09-18 18:01:18 +02:00
Umgesetzt – Repo 0ff3c8b + 328f978 + d931e66, Wiki d6190ec
Abweichung vom Issue: Move läuft nicht über Rapiers Character-Controller
Gemessen mit Wegwerf-Sonden gegen Rapier 0.20:
Fall
Rapiers Controller
eigenes Move-and-Slide
Boden aus 12 Kisten, 100 Schritte mit Schwerkraft
10× hängen, Lücke bis 1,7 px
hängt nie, bündig
dasselbe mit normalNudgeFactor 5e-4
0× hängen, Lücke ~0,1 px
–
Wand aus 3 gestapelten Rechtecken, 60 Schritte daran entlang
2× hängen (auch mit Tuning)
hängt nie
Der Controller sieht nur den Stand des letzten Physik-Steps: eine danach versetzte Wand durchquert er (250 px).
Auffrischen per Step mit dt = 0 verändert die Simulation (Drehung einer fliegenden Kiste ging verloren, ein Kontakt-Event fehlte).
Die Rückfrage dazu lief ins Timeout, entschieden wurde nach Empfehlung: eigenes Move-and-Slide behalten, Schieben selbst dazubauen.
Was drin ist
Sechs Nodes, nur im Play und nur auf Dynamic Bodies:
Apply force wirkt über die Dauer des Frames, gemessen unabhängig von 30/60/144 fps
Apply impulse, Set velocity, Set angular velocity
Get velocity (Data-Node, inkl. Drehgeschwindigkeit in °/s)
Set gravity gilt für den restlichen Lauf, die Scene im Projekt bleibt unverändert
Hinweis einmal pro Objekt in Log und Console: Node auf ein Objekt ohne Dynamic Body; Dynamic Body direkt versetzt (Antwort 3 in #146).
Move mit Kollision schiebt Dynamic Bodies: Mover bleibt bündig stehen, die Kiste bekommt einen Stoß (unelastisch, abhängig von beiden Massen).
Selbst entschieden:
Bei Fixed rotation setzt Set angular velocity nichts – Rapier würde den Wert sonst halten, nach dem Entsperren schnellte die Kiste gemessen 133° herum.
On start kommt vor dem ersten Physik-Schritt; damit ein Startschuss wirkt, wird der fehlende Body in dem Moment angelegt.
Tests
npm run check → 104 Files, 1454 Tests (vorher 1430), CHECK EXIT 0
GM_STEPS=1-8,39,40,41 (frisch geseedet) → ALL PASSED – 320 checks
CI zu d931e66 (Tasks 136/137) → CHECK EXIT 0, ALL PASSED – 1055 checks, Smokes 24/19/21
In CI misst 41b jetzt peaks: [99.8, 61.8, 37.9, 23.2], dieselben Werte wie lokal.
24 neue Unit-Tests (15 Node-Katalog, 9 gegen die Engine). Schieben in 1 s: gleich schwere Kiste 133 Einheiten, 39× schwerere 0,2, statische 0; Kinematic-Mover mit Mass 40 schiebt die schwere Kiste 142.
Alle bisherigen Kollisionstests laufen unverändert ohne Toleranz gegen beide Systeme.
Gegenprobe mit 8 eingebauten Fehlern, alle gefangen.
e2e 41c (3 Checks im echten Play): Kiste gleitet mit 100,8 Einheiten/s (erwartet 100), Move schiebt eine Kiste 229,9 Einheiten weit, Console ohne [physics]-Hinweis.
Zwei Nachbesserungen nach rotem CI
328f978 – echter Bug: Die Suite zu 0ff3c8b hatte 2 FAILs in 41c. Ursache: Jedes project-Event während Play ließ World.syncFromModel() die Scene-Props neu kopieren und setzte damit die Schwerkraft aus Set gravity auf die gespeicherten 980 zurück; der zweite FAIL (Walker 0,11 px in der Kiste) war nur die Folge – die geschobene Kiste fiel und flog in X neben dem Walker her. Fix: World.setSceneProp() merkt sich, was der Lauf selbst an der Scene gesetzt hat, und syncFromModel legt es wieder darüber. Unit-Test liest das Modell mitten im Lauf neu (ohne Fix rot), 41c erzwingt direkt nach Play ein project-Event (gegen den alten Build lokal beide Checks rot, wie in CI).
d931e66 – flatternder Test: Die Suite zu 328f978 war rot in 41b (Bounce), peaks: [61.8, 37.9]. Der Check suchte Landungen über „Ball näher als 1 px am Boden“; der Ball landet mit ~9 px pro Frame, ob ein gezeichneter Frame das trifft, hängt an der Phase zwischen zwei Physik-Schritten. CI hat die erste Landung verpasst und den zweiten Abprall als ersten gelesen – die Physik selbst stimmte (Verhältnisse 0,62/0,61 bei Bounciness 0,8). Der Check sucht jetzt Umkehrpunkte. Gegenprobe am nachgebauten Sprung über 50 Phasen: alt 15/50 grün, neu 50/50; lokal 3 Läufe GM_STEPS=39,40,41 grün mit 99,8 → 61,8 → 37,9 → 23,2.
Offen / Folge
#150 (umgeschrieben): Move-and-Slide entlang der Kontaktnormale mit Friction, Ausgänge hit/normal, ohne Stufen und ohne Character-Controller.
Nebenbefund, nicht angefasst: Move mit Kollision bewegt ein Objekt ohne eigenen Collider gar nicht (schon vor #147, in beiden Systemen).
Doku: Wiki Physics (neu: Moving bodies from a graph, Schieben), Behaviors, Colliders, Architecture, Development; Check-Summe 1055.
## Umgesetzt – Repo `0ff3c8b` + `328f978` + `d931e66`, Wiki `d6190ec`
### Abweichung vom Issue: `Move` läuft **nicht** über Rapiers Character-Controller
Gemessen mit Wegwerf-Sonden gegen Rapier 0.20:
| Fall | Rapiers Controller | eigenes Move-and-Slide |
|---|---|---|
| Boden aus 12 Kisten, 100 Schritte mit Schwerkraft | 10× hängen, Lücke bis 1,7 px | hängt nie, bündig |
| dasselbe mit `normalNudgeFactor` 5e-4 | 0× hängen, Lücke ~0,1 px | – |
| Wand aus 3 gestapelten Rechtecken, 60 Schritte daran entlang | 2× hängen (auch mit Tuning) | hängt nie |
- Der Controller sieht nur den Stand des letzten Physik-Steps: eine danach versetzte Wand durchquert er (250 px).
- Auffrischen per Step mit `dt = 0` verändert die Simulation (Drehung einer fliegenden Kiste ging verloren, ein Kontakt-Event fehlte).
Die Rückfrage dazu lief ins Timeout, entschieden wurde nach Empfehlung: eigenes Move-and-Slide behalten, Schieben selbst dazubauen.
### Was drin ist
- **Sechs Nodes**, nur im Play und nur auf Dynamic Bodies:
- **Apply force** wirkt über die Dauer des Frames, gemessen unabhängig von 30/60/144 fps
- **Apply impulse**, **Set velocity**, **Set angular velocity**
- **Get velocity** (Data-Node, inkl. Drehgeschwindigkeit in °/s)
- **Set gravity** gilt für den restlichen Lauf, die Scene im Projekt bleibt unverändert
- **Hinweis einmal pro Objekt** in Log und Console: Node auf ein Objekt ohne Dynamic Body; Dynamic Body direkt versetzt (Antwort 3 in #146).
- **`Move` mit Kollision schiebt Dynamic Bodies:** Mover bleibt bündig stehen, die Kiste bekommt einen Stoß (unelastisch, abhängig von beiden Massen).
**Selbst entschieden:**
- Bei Fixed rotation setzt `Set angular velocity` nichts – Rapier würde den Wert sonst halten, nach dem Entsperren schnellte die Kiste gemessen 133° herum.
- `On start` kommt vor dem ersten Physik-Schritt; damit ein Startschuss wirkt, wird der fehlende Body in dem Moment angelegt.
### Tests
```
npm run check → 104 Files, 1454 Tests (vorher 1430), CHECK EXIT 0
GM_STEPS=1-8,39,40,41 (frisch geseedet) → ALL PASSED – 320 checks
CI zu d931e66 (Tasks 136/137) → CHECK EXIT 0, ALL PASSED – 1055 checks, Smokes 24/19/21
```
- In CI misst 41b jetzt `peaks: [99.8, 61.8, 37.9, 23.2]`, dieselben Werte wie lokal.
- 24 neue Unit-Tests (15 Node-Katalog, 9 gegen die Engine). Schieben in 1 s: gleich schwere Kiste 133 Einheiten, 39× schwerere 0,2, statische 0; Kinematic-Mover mit Mass 40 schiebt die schwere Kiste 142.
- Alle bisherigen Kollisionstests laufen unverändert **ohne Toleranz** gegen beide Systeme.
- Gegenprobe mit 8 eingebauten Fehlern, alle gefangen.
- e2e 41c (3 Checks im echten Play): Kiste gleitet mit 100,8 Einheiten/s (erwartet 100), `Move` schiebt eine Kiste 229,9 Einheiten weit, Console ohne `[physics]`-Hinweis.
### Zwei Nachbesserungen nach rotem CI
- **`328f978` – echter Bug:** Die Suite zu `0ff3c8b` hatte 2 FAILs in 41c. Ursache: Jedes `project`-Event während Play ließ `World.syncFromModel()` die Scene-Props neu kopieren und setzte damit die Schwerkraft aus `Set gravity` auf die gespeicherten 980 zurück; der zweite FAIL (Walker 0,11 px in der Kiste) war nur die Folge – die geschobene Kiste fiel und flog in X neben dem Walker her. Fix: `World.setSceneProp()` merkt sich, was der Lauf selbst an der Scene gesetzt hat, und `syncFromModel` legt es wieder darüber. Unit-Test liest das Modell mitten im Lauf neu (ohne Fix rot), 41c erzwingt direkt nach Play ein `project`-Event (gegen den alten Build lokal beide Checks rot, wie in CI).
- **`d931e66` – flatternder Test:** Die Suite zu `328f978` war rot in 41b (Bounce), `peaks: [61.8, 37.9]`. Der Check suchte Landungen über „Ball näher als 1 px am Boden“; der Ball landet mit ~9 px pro Frame, ob ein gezeichneter Frame das trifft, hängt an der Phase zwischen zwei Physik-Schritten. CI hat die erste Landung verpasst und den zweiten Abprall als ersten gelesen – die Physik selbst stimmte (Verhältnisse 0,62/0,61 bei Bounciness 0,8). Der Check sucht jetzt Umkehrpunkte. Gegenprobe am nachgebauten Sprung über 50 Phasen: alt 15/50 grün, neu 50/50; lokal 3 Läufe `GM_STEPS=39,40,41` grün mit 99,8 → 61,8 → 37,9 → 23,2.
### Offen / Folge
- #150 (umgeschrieben): Move-and-Slide entlang der Kontaktnormale mit Friction, Ausgänge hit/normal, ohne Stufen und ohne Character-Controller.
- Nebenbefund, nicht angefasst: `Move` mit Kollision bewegt ein Objekt **ohne eigenen Collider** gar nicht (schon vor #147, in beiden Systemen).
Doku: Wiki *Physics* (neu: *Moving bodies from a graph*, Schieben), *Behaviors*, *Colliders*, *Architecture*, *Development*; Check-Summe 1055.
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.
Zweiter Teil von #146 (Aufteilung laut Antwort 1 dort). Voraussetzung: #146 (Rigidbody, Material, Schwerkraft,
PhysicsSystem).Stand nach #146
Moveohne Kollision setzt die Position, der Body behält dabei seine Geschwindigkeit.PhysicsSystemhat schonvelocityOf(owner)undsetVelocity(owner, v), beides in Welteinheiten pro Sekunde. Bisher nutzen das nur die Unit-Tests.Movemit „Collide with solids“ läuft weiter über das eigene Move-and-Slide (runtime/systems/solids.ts). Ein Dynamic Body blockiert es wie eine Wand, schieben lässt er sich damit also nicht.Zu bauen
Apply force,Apply impulse,Set velocity,Get velocity,Set angular velocity,Set gravity(Scene). Alle Größen in Welteinheiten, die Umrechnung machtengine.ts.Movemit „Collide with solids“ läuft über RapiersKinematicCharacterController: Gleiten an Wänden, Schrägen, Stufen, und Dynamic Bodies, die dabei im Weg stehen, bekommen einen Stoß. Ohne Rigidbody und bei Kinematic wie bisher (#146, Antwort 3 in #144).Moveauf einem Dynamic Body (Antwort 3 in #146): Das Objekt wird versetzt, die Geschwindigkeit bleibt. Beim ersten Mal steht ein Hinweis in der Console, dass Force, Impulse und Velocity der Weg sind.Offen
Umgesetzt – Repo
0ff3c8b+328f978+d931e66, Wikid6190ecAbweichung vom Issue:
Moveläuft nicht über Rapiers Character-ControllerGemessen mit Wegwerf-Sonden gegen Rapier 0.20:
normalNudgeFactor5e-4dt = 0verändert die Simulation (Drehung einer fliegenden Kiste ging verloren, ein Kontakt-Event fehlte).Die Rückfrage dazu lief ins Timeout, entschieden wurde nach Empfehlung: eigenes Move-and-Slide behalten, Schieben selbst dazubauen.
Was drin ist
Movemit Kollision schiebt Dynamic Bodies: Mover bleibt bündig stehen, die Kiste bekommt einen Stoß (unelastisch, abhängig von beiden Massen).Selbst entschieden:
Set angular velocitynichts – Rapier würde den Wert sonst halten, nach dem Entsperren schnellte die Kiste gemessen 133° herum.On startkommt vor dem ersten Physik-Schritt; damit ein Startschuss wirkt, wird der fehlende Body in dem Moment angelegt.Tests
peaks: [99.8, 61.8, 37.9, 23.2], dieselben Werte wie lokal.Moveschiebt eine Kiste 229,9 Einheiten weit, Console ohne[physics]-Hinweis.Zwei Nachbesserungen nach rotem CI
328f978– echter Bug: Die Suite zu0ff3c8bhatte 2 FAILs in 41c. Ursache: Jedesproject-Event während Play ließWorld.syncFromModel()die Scene-Props neu kopieren und setzte damit die Schwerkraft ausSet gravityauf die gespeicherten 980 zurück; der zweite FAIL (Walker 0,11 px in der Kiste) war nur die Folge – die geschobene Kiste fiel und flog in X neben dem Walker her. Fix:World.setSceneProp()merkt sich, was der Lauf selbst an der Scene gesetzt hat, undsyncFromModellegt es wieder darüber. Unit-Test liest das Modell mitten im Lauf neu (ohne Fix rot), 41c erzwingt direkt nach Play einproject-Event (gegen den alten Build lokal beide Checks rot, wie in CI).d931e66– flatternder Test: Die Suite zu328f978war rot in 41b (Bounce),peaks: [61.8, 37.9]. Der Check suchte Landungen über „Ball näher als 1 px am Boden“; der Ball landet mit ~9 px pro Frame, ob ein gezeichneter Frame das trifft, hängt an der Phase zwischen zwei Physik-Schritten. CI hat die erste Landung verpasst und den zweiten Abprall als ersten gelesen – die Physik selbst stimmte (Verhältnisse 0,62/0,61 bei Bounciness 0,8). Der Check sucht jetzt Umkehrpunkte. Gegenprobe am nachgebauten Sprung über 50 Phasen: alt 15/50 grün, neu 50/50; lokal 3 LäufeGM_STEPS=39,40,41grün mit 99,8 → 61,8 → 37,9 → 23,2.Offen / Folge
Movemit Kollision bewegt ein Objekt ohne eigenen Collider gar nicht (schon vor #147, in beiden Systemen).Doku: Wiki Physics (neu: Moving bodies from a graph, Schieben), Behaviors, Colliders, Architecture, Development; Check-Summe 1055.