# 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//.fbx` und `.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`.