champions-of-luneraria/docs/port/U2-WORLD.md
Martin Stickelbroeck 8a72cb165a U2B World Geometry
G1-Karte in Unity (Assets/Luneraria/Scenes/G1_Map.unity), reproduzierbar
gebaut aus dem Godot-Weltgenerator (gebacken), den FBX-Modellen aus U2A und der
Karte des C#-Kerns.

- tools/godot-golden/world_export.gd: backt Gelände (Raster, Farben, Lauf- und
  Standhöhen), Lanebeläge, Plattform, Brücke, Randsteine, Basen, Landmarken,
  Vegetation, Adern, Grottentreppen, Aufstellungsbereiche und Licht. Braucht
  einen echten Renderer (HEADLESS=0); prüft auf Headless-Einheitstransformationen.
- LuneWorldBuilder: Meshes (GUID-stabil), Szene, Licht, Himmel, Post-Processing,
  16 Türme, 2 Ancients und die Grotte aus LuneMap mit Teammaterialien.
- Materialsystem: Luneraria/Surface (Gelände, Kluft-Oberflächen, Fluss, Adern,
  Kristall, G2-Werte mit Teamvarianten und Vertex-AO) und Luneraria/Pad;
  LuneMaterialSet.Dress wie Godots dress.
- View-Assembly: LuneSpace (Unity = (-x, h, y)), LuneGround, LuneCameraMath,
  LuneBuildingView (Zustände intakt bis Ruine).
- Vergleichsbilder mit den Kameraeinstellungen der Godot-G2-Aufnahmen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 16:01:25 +02:00

230 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# U2 · Unity-Spielwelt
Stand: 30. September 2026.
| Teil | Inhalt | Zustand |
| --- | --- | --- |
| U2A | Blender→FBX-Pipeline, sechs repräsentative Assets vollständig geprüft | **fertig** |
| U2B | Weltgeometrie (G1-Karte, Türme, Ancients, Grotte, Aufstellungsbereiche), Materialsystem | **fertig** |
| U2C | Simulation/Darstellung: fester Takt, Interpolation, Bildraten-Unabhängigkeit | offen |
| U2D | spielbare Unity-Partie, Vertical Function Test | offen |
Voraussetzung U1.5 ist erfüllt ([U1.5-UNITY.md](U1.5-UNITY.md)).
## Ziel
Die bestehende Partie läuft sichtbar in Unity (URP). Das ist noch keine grafische Neugestaltung; die kommt erst mit U5.
Zuerst kommen:
- die G1-Drei-Lane-Karte,
- die G2-Türme (Grenzwacht, Bastion, Kernwacht),
- die G2-Ancients,
- die Bossgrotte und die Schlundkrone,
- repräsentative vorhandene Einheiten.
## Vorgaben
- **Adapter:** Unity treibt `LuneMatch` im festen Takt (0,05 s) über einen Akkumulator, unabhängig von der Bildrate. Ansichten lesen nur; sie schreiben nie in die Regeln. Beispiel: `Gebäude-HP = 0` führt zu Einsturz und Ruine, nie umgekehrt eine Animation zu einer Regelwirkung.
- **Gemeinsames Materialsystem** (URP): Stein, Metall, Holz, Vegetation, Kristall, Runen, Wasser. Die G2-Shader aus Godot (stone, metal, crystal, rune, cloth, vein, water_glow, hide) dienen als fachliche Vorlage.
- **Assets:** Quelle sind die Blender-Dateien und Generatoren im Referenz-Repository. Ein zentraler, reproduzierbarer Blender-Export erzeugt FBX; GLB nur, wo keine bearbeitbare Quelle existiert.
- **Reihenfolge:** Erst sechs repräsentative Assets vollständig prüfen, dann die Welt und eine vollständige Bot-Partie. Den Batchlauf über alle Assets gibt es erst nach dem Vertical Function Test.
## U2A · Blender→FBX-Pipeline
### Aufbau
| Datei | Aufgabe |
| --- | --- |
| `tools/blender/export_manifest.json` | Asset-Liste: Blender-Quelle, Art (statisch, starre Teile, Skelett), Exportregeln und Verweis auf den Godot-Manifesteintrag des GLB, das die Referenz benutzt |
| `tools/blender/lune_fbx_export.py` | Blender im Hintergrund: Quelle öffnen, Regeln anwenden, prüfen, FBX schreiben, FBX wieder einlesen und erneut prüfen |
| `tools/blender/export_fbx.sh` | Einstieg; macht die FBX-Dateien byteidentisch reproduzierbar |
| `Assets/Luneraria/Art/<Gruppe>/<id>.fbx` und `<id>.export.json` | Ergebnis: Modell und Protokoll (Blender-Fakten und Prüfungen) |
| `Assets/Luneraria/Editor/Art/LuneModelPostprocessor.cs` | Importregeln in Unity |
| `Assets/Luneraria/Editor/Art/LuneAssetVerifier.cs` | Unity-Prüfung jedes importierten Modells gegen das Blender-Protokoll |
| `Assets/Luneraria/Editor/Art/LuneAssetPreview.cs` | Vorschaubilder in URP |
```bash
sh tools/blender/export_fbx.sh
```
```bash
/Applications/Unity/Hub/Editor/6000.3.20f1/Unity.app/Contents/MacOS/Unity -batchmode -projectPath "$PWD" -executeMethod Luneraria.EditorTools.LuneAssetVerifier.VerifyAll -logFile -
```
Weitere Einstiege: `LuneAssetVerifier.ReimportArt` (nach geänderten Importregeln) und `LuneAssetPreview.RenderAll`.
### Exportregeln
Die Regeln wiederholen, was die Godot-Pipeline beim GLB-Export getan hat. Sonst entstünde ein anderes Modell:
- **Phase-4-Einheiten:** Die Modifikatoren „HIGH RES“ (Unterteilung und Mikrorelief) kamen erst *nach* dem Laufzeitexport in die `.blend`-Datei. Sie werden nicht angewendet (bei `g01`: 36 Stück).
- **Logische Namen:** Die Namen stammen aus den Eigenschaften `part_name` und `material_name`; Blender hatte teils Suffixe wie `.004` ergänzt.
- **Figuren mit Skelett:** Die `.blend`-Datei ist vor dem Zusammenfügen gespeichert. Der Export fügt die Teile wie in Godot zu einem Skin-Mesh zusammen (Funkenlanze: 104 Teile → `FunkenBody`).
- **Achsen:** Die FBX-Datei behält Blenders Z-oben-Achsen; Unity rechnet sie beim Import mit „Bake Axis Conversion“ um, also ohne Wurzelrotation. Blender (x, y, z) wird dabei Unity (x, z, y); die Vorderseite (Blender −Y) läge auf Unity −Z.
- Deshalb dreht der Export jedes Asset vorher um 180° um die Hochachse und wendet die Drehung an. Danach gilt Unity = (−x, y, z) der Godot-/glTF-Koordinaten, und die Vorderseite liegt auf +Z wie in Godot.
- Blenders „Apply Transform“ ist für Skelette als fehlerhaft dokumentiert und wird nicht benutzt.
- **Maßstab und Inhalt:** 1 Blender-Einheit = 1 m; Normalen, Tangenten (MikkTSpace, wo UVs existieren), lineare Vertexfarben; nur Deform-Bones, keine Leaf-Bones; jede Action wird ein Clip.
- **Reproduzierbarkeit:** Blenders FBX-Schreiber stempelt die Uhrzeit ein und leitet Objekt-IDs aus Pythons String-Hash ab. Der Export fixiert beides (feste Uhrzeit, `PYTHONHASHSEED=0` mit `--python-use-system-env`). Zwei Läufe liefern byteidentische FBX-Dateien und identische Protokolle.
### Prüfungen
Blender-Seite, vor und nach dem Schreiben (Rundreise durch einen FBX-Import):
| Prüfpunkt | Wie |
| --- | --- |
| Einheiten, Maßstab | metrisch, `scale_length` 1, keine Objektskalierung, keine negative Skalierung |
| Achsen, Vorderseite | Drehung angewendet; Vorwärtsmarker (Phase 4: Empty `Forward`) liegt in Unity auf +Z |
| Mesh-Namen | eindeutig; gleich den Knoten des Godot-GLB |
| Dreiecke | gleich dem Godot-GLB, auch nach dem Wiedereinlesen |
| Materialslots | keine leeren Slots; Materialien gleich dem Godot-GLB |
| Normalen | Einheitslänge an allen Ecken |
| Tangenten | Voraussetzungen (UVs, keine N-Ecke); Meshes ohne UVs sind vermerkt und werden triplanar oder unbeleuchtet schattiert |
| Maße | Ruhelage gleich den `bounds_godot` des Godot-Manifests (Türme und Ancient: ohne Schadens- und Ruinenteile, wie dort gemessen) |
| Skelett | genau eine Armature, ein Root Bone `Root`, Bone-Namen und -Anzahl wie im Godot-GLB, portable Namen |
| Clips | Namen und Längen wie im Godot-GLB; Pflichtclips vorhanden; Loop-Flag und Kontaktzeit aus den Action-Eigenschaften |
| Blend Shapes | keine in den Quellen |
Unity-Seite (`LuneAssetVerifier`, gegen das Blender-Protokoll):
| Prüfpunkt | Wie |
| --- | --- |
| Importregeln | Maßstab 1, Dateieinheiten, Achsen-Bake, Normalen und Tangenten aus der Datei |
| Achsen | Wurzel und alle Nicht-Bone-Knoten ohne Rotation und Skalierung |
| Mesh-Namen, Dreiecke | Menge und Anzahl je Mesh gleich |
| Maße | aus den Vertices berechnet, Abweichung höchstens 2 mm; gemessen höchstens 0,05 mm |
| Materialslots | Namen je Renderer gleich den Blender-Slots |
| Normalen, Tangenten, UVs, Vertexfarben | vorhanden und gültig, wo Blender sie hat; Tangenten mit w = ±1 |
| Vorderseite | Vorwärtsmarker auf +Z |
| Skelett | Root Bone, Bone-Namen, gültiger Generic-Avatar |
| Clips | Namen, Längen (auf einen halben Frame genau), Loop-Flags, Kontakt-Events (`OnLuneContact`) |
### Ergebnis: sechs repräsentative Assets und drei Szenenbauten
| Asset | vertritt | Dreiecke (= Godot-GLB) | Blender-Prüfungen | Unity-Prüfungen |
| --- | --- | ---: | --- | --- |
| `g01` Kohlenbeißer | normale Einheit, 131 benannte Teile | 79.780 | 18/18 | 14/14 |
| `funkenlanze` | Einheit mit Skelett (Held), 26 Bones, 9 Clips | 24.036 | 26/26 | 18/18 |
| `grenzwacht` | Turm (mit Schadens- und Ruinenteilen) | 6.516 | 18/18 | 13/13 |
| `ancient` Mondherz | Ancient | 19.032 | 18/18 | 13/13 |
| `schlundkrone` | Schlundkrone (Boss), 24 Bones, 11 Clips | 5.712 | 28/28 | 18/18 |
| `map_props` | Vegetation und Kartenrequisiten (Eichen, Kiefern, Sträucher, Felsen, Brücke, Randsteine) | 7.338 | 14/14 | 13/13 |
| `bastion`, `kernwacht`, `bossgrotte` | für die Szene in U2B (Innen- und Basisturm, Mondschlund) | 9.364, 9.224, 15.182 | je 18/18 | je 13/13 |
Summe: 176 Blender-Prüfungen und 128 Unity-Prüfungen, alle bestanden. Protokolle:
- `Assets/Luneraria/Art/*/*.export.json` (Blender).
- `docs/port/logs/u2a/unity-verify.json` (Unity).
Bilder unter `docs/port/screenshots/u2a/`:
- je Asset eine Ansicht von vorn-rechts,
- die Grenzwacht zusätzlich als Ruine,
- Funkenlanze und Schlundkrone zusätzlich im Kontaktframe von `attack_a` (Clips laufen).
### Bekannte Grenzen
- **Materialien:** Die Vorschau benutzt URP-Lit-Materialien, die Unity aus den FBX-Materialbeschreibungen erzeugt (Blender-Palettenfarben). Das eigentliche Materialsystem (Stein, Metall, Kristall, Runen, Stoff, Wasser; Teamfarben; Vertex-AO) folgt in U2B.
- Stoff (Wimpel, Banner) ist einseitig modelliert und braucht dort doppelseitiges Rendern; in der Vorschau fehlt er deshalb.
- **Ohne UVs:** Diese Meshes haben keine Tangenten (Unity meldet das beim Import): Kristalle, Trümmer, Felsen, Kartenrequisiten und einige Phase-4-Kleinteile. Sie brauchen triplanare oder unbeleuchtete Materialien.
- **Starre Einheiten:** Die Phase-4-Einheiten werden in Godot aus benannten Teilen prozedural animiert. Die Teile kommen mit, die Animation folgt mit den Einheitenansichten.
- **Größe:** Die FBX-Dateien liegen direkt im Repository (9 Dateien, 16 MB). Für den Batchlauf über alle Assets ist Git LFS zu erwägen.
### Batchlauf (nach dem Vertical Function Test)
Das Manifest enthält bisher die 9 Assets der Szene. Die übrigen Assets kommen erst nach U2D in das Manifest und werden dann mit denselben Regeln und Prüfungen exportiert:
- 58 weitere Phase-4-Modelle.
- 5 Figuren mit Skelett.
- 7 Völker-Modelle. Für Zwerg und Troll fehlt die `.blend`-Datei im Referenz-Repository; sie entsteht aus dem Generator `build_peoples.py`.
Bauten aus einer GLB ohne Quelle folgen nur nach Einzelfallprüfung.
## U2B · Weltgeometrie
### Quellen
Die Szene `Assets/Luneraria/Scenes/G1_Map.unity` entsteht reproduzierbar aus drei Quellen, ohne Handarbeit:
| Quelle | liefert | Weg nach Unity |
| --- | --- | --- |
| Godot-Generator der G1-Welt (`lune_world.gd`, `lune_terrain.gd`) | Gelände, Wasser, Lanebeläge, Plattform, Brücke, Randsteine, Basen, Landmarken, Vegetation, Adern, Grottentreppen, Aufstellungsbereiche, Licht | `tools/godot-golden/world_export.gd` backt die Welt nach `Assets/Luneraria/World/Bake/` (JSON und Binärdaten); `LuneWorldBuilder` baut daraus Meshes und Szene |
| Blender-Pipeline (U2A) | Türme, Ancients, Grotte, Requisiten | FBX-Modelle, in der Szene als Prefab-Instanzen |
| C#-Kern | Gebäude-IDs, Positionen, Ausrichtung | `LuneMap` direkt; die Szene enthält keine eigenen Kartendaten |
Warum gebacken statt portiert:
- Gelände und Vegetation hängen an Godots FastNoiseLite und Zufallsgenerator. Ein Nachbau wäre nicht nachweisbar exakt; der Bake ist es.
- Es gibt für diese Welt keine Blender-Quelle; ihre Quelle ist der Generator. Der Bake ist dessen reproduzierbarer Export, kein GLB-Umweg.
- U5 bekommt ohnehin eine neue Weltquelle.
```bash
HEADLESS=0 sh tools/godot-golden/run_godot.sh world_export --out="$PWD/Assets/Luneraria/World/Bake"
```
```bash
/Applications/Unity/Hub/Editor/6000.3.20f1/Unity.app/Contents/MacOS/Unity -batchmode -projectPath "$PWD" -executeMethod Luneraria.EditorTools.LuneWorldBuilder.BuildScene -logFile -
```
Der Bake braucht einen echten Renderer (`HEADLESS=0`). Godots Headless-Renderer liefert für MultiMesh-Instanzen Einheitstransformationen; so lag im ersten Versuch die ganze Vegetation im Kartenmittelpunkt. Das Werkzeug bricht jetzt ab, wenn es so einen Bake erkennt.
### Inhalt
| Teil | Umfang |
| --- | --- |
| Gelände | 121 × 121 Punkte (1 m) plus Bergring 67 × 67 (4 m), Zonenfarbe und Felsanteil als Vertexfarbe, Dreiecksmuster wie in Godot |
| Welt | 59 Knoten: 35 Einzelmeshes, 98 MultiMesh-Instanzen (Randsteine ausgenommen), 532 Requisiten (372 Vegetation und Felsen, 159 Randsteine, Brücke) |
| Bauten | 16 Türme (Grenzwacht, Bastion, Kernwacht), 2 Ancients, Bossgrotte; Positionen und Blickrichtung aus dem Kern; Teammaterialien |
| Aufstellungsbereiche | 3 je Team und Grotteneingänge, ausgeblendet (Planungsphase schaltet sie ein) |
| Höhen | `LuneGround`: Lauf-Höhe (1-m-Raster) und Standhöhe mit Plaza, Stufen und Grottenterrasse (0,5-m-Raster) für Figuren |
| Licht | Sonne und Aufhellung aus dem Bake, flaches Umgebungslicht, prozeduraler Himmel, ACES, Bloom, Kontrast/Sättigung wie `lighting.gd`; kein Nebel (wie in Godot) |
Koordinaten: Unity = (−x, Höhe, y) der Kartenpunkte. Mit dem Wechsel der Händigkeit bleiben Bild und Vorderseiten der Dreiecke erhalten; die Indexfolge bleibt deshalb unverändert. Gemeinsame Umrechnung: `Assets/Luneraria/View/LuneSpace.cs`.
Reproduzierbarkeit:
- Der Bake ist deterministisch (Godot-Generator mit festen Seeds).
- Der Builder aktualisiert Meshes und Materialien an Ort und Stelle; ihre GUIDs bleiben über Builds gleich.
- Nur die Datei-IDs der Szenenobjekte wechseln; das ist bei per Skript erzeugten Szenen unvermeidlich.
### Materialsystem
Alle Materialien verwenden `Luneraria/Surface` (URP, HLSL, SRP-Batcher-fähig) oder `Luneraria/Pad`. Portiert sind:
- das Gelände (`lune_terrain.gdshader`),
- die Kluft-Oberflächen (`sanctuary.gdshader`: Stein, Pflaster, Erde, Rinde, Laub mit Wind),
- der Fluss (`river.gdshader`),
- die Energieadern (`lune_vein.gdshader`),
- die Aufstellungsbereiche (`lune_pad.gdshader`).
Mit dabei sind jeweils triplanarer Kalkstein und Relief aus Bildschirmableitungen, wie in Godot.
Die G2-Oberflächen (`LN_*`) haben Werte und Teamvarianten aus `lune_materials.gd`: Kristall, Rune, Teammetall, Stoff; Blau, Rot und neutral. Vertex-AO wird mit verrechnet. `LuneMaterialSet.Dress` tauscht die Importmaterialien wie Godots `dress` gegen die geteilten Materialien.
Vereinfacht gegenüber Godot, bis U5 die Oberflächen neu macht:
- Quaderfugen der Steinshader, Runenglyphen (stattdessen ein schwach leuchtendes Band), Kristalltiefe, Stoffembleme.
- Beschädigungs- und Einsturzparameter der Materialien.
Befund beim Einrichten: Unity reicht `[HDR]`-Farben unverändert als linear weiter, gewöhnliche Farben konvertiert es aus Gamma. Das war am blassen Kristall zu sehen. Emission wird deshalb als linearer Wert gesetzt (`LuneMaterialFactory.Hdr`).
### Vergleich mit Godot
`LuneWorldCapture.CaptureAll` fotografiert die Szene mit den Kameraeinstellungen der Godot-G2-Aufnahmen (`g2_views.gd`: Fokus, Zoom, Drehung; Kamera wie `lune_camera.gd`). Die Bilder liegen unter `docs/port/screenshots/u2b/`, das Gegenstück unter `../saumwacht-godot/docs/luneraria/screenshots/g2/nachher/`.
| Bild | Befund |
| --- | --- |
| `15-gesamtkarte` | Anordnung gleich: Blau unten links, Rot oben rechts, Grotte links, Kluft von der Quelle unter der Plattform zum Delta mit Brücke; Waldinseln, Randsteine, Mauern, Runensteine an denselben Stellen |
| `01-ancient-100`, `07-basistuerme` | Ancient und Basistürme in gleicher Lage und Ausrichtung, Teamfarben richtig |
| `05-tower1-grenzwacht`, `06-tower2-bastion` | Turm, Tür, Wimpel, Randsteine und Plattformsteine decken sich im Bildausschnitt |
| `10-grotte` | Arena, Tor, Säulen und Treppen gleich; der schlafende Boss und die Grottenzustände kommen mit der Anbindung (U2C/U2D) |
Unterschiede:
- Godot zeigt in allen Bildern das HUD (U3) und in der Planungsphase die Aufstellungsbereiche.
- Die Materialien sind vereinfacht (siehe oben).
- Die Beleuchtung ist ähnlich, aber nicht identisch abgestimmt.
## U2C bis U2D
Folgen in diesem Dokument.
## Abnahme (gesamt)
- Die Partie läuft sichtbar.
- Die Kamera entspricht der Godot-Kamera.
- Screenshots neben den Godot-G2-Bildern mit vergleichbarer Kamera.
- Leistung gemessen, einschließlich Mono-Simulationszeit.
- Bekannte Unterschiede dokumentiert.
- Commits U2A bis U2D auf `luneraria/u2`.