Konzeptphase. Interne Planungsfassung, Stand 04.11.2026. Pocket Planet ist noch in Entwicklung – Inhalte, Zahlen und Abläufe können sich ändern.
11.1 Engine-Entscheidung: Godot 4.7 vs. Unity 6
| Kriterium | Godot 4.7 (GDScript) | Unity 6 (C#) | Gewinner für uns |
|---|---|---|---|
| Android | [Fakt] Compatibility ab Android 7.0, Mobile/Forward+ ab 9.0 (Docs); AAB-Export, Plugin-System v2 (AAR) | sehr ausgereift | Gleichstand |
| iOS | Export vorhanden; Metal-Pfad laut Docs ab iOS 16, Compatibility per OpenGL ES; Plugin-Ökosystem dünner | sehr ausgereift | Unity |
| 3D-Grafik mobil | Für stilisierte Grafik ausreichend; keine High-End-Features im Compatibility-Renderer | URP stärker, mehr Out-of-the-box-Effekte | Unity, aber für unseren Stil nicht entscheidend |
| Leistung auf alten Geräten | Kleine Laufzeit, schneller Start, Compatibility = breiteste Abdeckung | gut, größere Builds | Godot leicht vorn |
| Animation | AnimationPlayer, Tweens, Shader – reicht für unseren Plan vollständig (09) | Timeline, Animator | Gleichstand für unseren Bedarf |
| Native SDKs | Android-Plugins einfach (Studio hat schon Analytics-Plugin); iOS-Plugins aufwendiger | Riesiges Ökosystem | Unity |
| Werbe-SDK (eigenes) | Port nötig – betrifft jede Engine, da nur Web/RN-Adapter existieren | Port nötig | Gleichstand |
| Benachrichtigungen | Community-Plugins (MIT) Android/iOS (13) | Mobile Notifications Package (offiziell) | Unity |
| Entwicklungsaufwand für uns | 6 Godot-Spiele im Studio, Muster, Skripte, Tests, Radio, Analytics vorhanden | kein Unity-Know-how im Studio [Annahme] | Godot klar |
| Build-Prozess | lokal, ohne Konto, schnell (Studio-Skripte vorhanden) | Unity Hub, Lizenz-Login | Godot |
| Wartbarkeit | MIT, keine Laufzeitgebühren, Projektdateien textbasiert (gut für Coding-Agenten) | proprietär, Editor-Binärdaten teils schlechter für Agenten | Godot |
| Kosten/Lizenz | 0 € | Personal kostenlos bis zu einer Umsatzgrenze [Annahme: Stand Unity 6] | Godot |
Entscheidung [Vorschlag]: Godot 4.7.2 mit GDScript. Unity gewinnt bei iOS-Ökosystem und High-End-Grafik. Beides ist für ein stilisiertes, Android-first Cozy-Spiel nicht entscheidend. Godot gewinnt bei dem, was für ein kleines Team zählt: vorhandenes Wissen und Bausteine, Kosten, agentenfreundliche Textformate, schnelle lokale Builds.
Renderer: Compatibility statt Mobile
| Compatibility (OpenGL ES 3) | Mobile (Vulkan) | |
|---|---|---|
| Geräte | ab Android 7, auch alte GPUs | ab Android 9 mit stabilen Vulkan-Treibern |
| Studio-Erfahrung | alle 6 Godot-Spiele | keine |
| Funktionen | keine SDFGI/SSAO/Volumetrie, begrenzte Lichter pro Objekt | mehr Effekte, bessere Partikel/Lichter |
| Für unseren Stil | ausreichend: Licht steckt in eigenen Shadern | Mehrwert gering |
Entscheidung: Compatibility für alle Stufen. Alle Shader werden so geschrieben, dass sie auch im Mobile-Renderer laufen. Ein späterer Wechsel (z. B. „Hoch“-Stufe auf Vulkan) bleibt möglich, verdoppelt aber die QA – daher erst nach dem MVP prüfen.
11.2 Projektstruktur
project.godot · export_presets.cfg
scenes/ main.tscn, planet.tscn, ui/*.tscn
scripts/
autoload/ game.gd (Einstellungen, Profil) · bus.gd (Signale) · sfx.gd (Audio+Radio, aus Bellmoor)
loc.gd (Sprache, aus Bellmoor) · analytics.gd · notify.gd · ads.gd · quality.gd
sim/ rng.gd · grid.gd · planet_state.gd · climate.gd · hydrology.gd · terrain.gd · biomes.gd
vegetation.gd · life.gd · civ.gd · events.gd · chronicle.gd · actions.gd · simulator.gd
offline.gd · names.gd
meta/ energy.gd · progression.gd · challenges.gd · achievements.gd · galaxy.gd · scenarios.gd
services/ save.gd · time_keeper.gd
view/ planet_view.gd · props_view.gd · fx_view.gd · camera_rig.gd · input_router.gd · night_lights.gd
ui/ hud.gd · tool_ring.gd · info_sheet.gd · evolution_card.gd · chronicle_view.gd · settings.gd …
shaders/ planet_surface.gdshader · ocean · atmosphere · clouds · prop_foliage · prop_creature · prop_building · fx_lava
data/ balance.json · biomes.json · events.json · evolution_cards.json · challenges.json · scenarios/*.json
names/<lang>.json · chronicle_templates/<lang>.json
assets/ models/ · textures/ · audio/ · icons/ · fonts/ · ui/
locale/ strings.csv → *.translation
addons/ pp_analytics (aus Bellmoor) · notification-Plugins · werbemodul (Port)
tests/ test_*.gd (headless) · ui_*.gd (mit Fenster) · bench_*.gd
tools/ export-wiki.mjs · tripo.mjs · audio-prep.mjs · import-gpt-art.mjs · blender/*.py
artifacts/ KI-Rohdaten (git-ignoriert)
docs/konzept/ diese Dokumente
11.3 Schichten und Abhängigkeiten
┌──────────── UI (scripts/ui) ─────────────┐
│ liest Zustand, sendet Aktionen │
▼ │
View (scripts/view) ◄── Bus-Signale ── Meta (energy, progression, challenges)
│ liest PlanetState (read-only) │
▼ ▼
┌──────────────── Sim (scripts/sim) ─────────────────────┐
│ reine RefCounted-Klassen · kein Node · kein Rendering │
└─────────────────────────────────────────────────────────┘
▲
Services (save, time_keeper) · Autoloads (sfx, ads, notify, analytics, quality)
Regeln (für Coding-Agenten verbindlich, kommen in CLAUDE.md):
scripts/sim/importiert nichts aus view/ui/autoload. Tests laufen headless.- Jede Zustandsänderung durch den Spieler ist eine Aktion (
actions.gd, Command-Muster):validate(state) → cost → apply(state). Dadurch: Rückgängig (5 s), Wiederholbarkeit in Tests, Energieprüfung an einer Stelle. - View schreibt nie in den Zustand. Sie liest
PlanetStateundTickReport.dirty_regions. - Zahlen fürs Balancing stehen in
data/*.json, nie im Code. - Zufall nur über
rng.gd(PCG32, benannte Ströme).
11.4 Module – Verantwortung und Schnittstellen
| Modul | Verantwortung | Wichtigste Schnittstelle |
|---|---|---|
sim/simulator.gd | Zyklus-Orchestrierung, Thread-Übergabe, Doppelpuffer | step(n: int) -> TickReport · queue(action) · snapshot() -> PackedByteArray |
sim/grid.gd | Ikosaeder-Raster, Nachbarn, Lat/Lon, Ankerpunkte | neighbors(r) -> PackedInt32Array · region_at(dir: Vector3) -> int |
sim/climate.gd | Temperatur, Eis, CO₂ | update(state, dt_cycles) |
sim/hydrology.gd | Feuchte, Meeresspiegel, Flüsse | update(state, dt) · rivers(state) |
sim/terrain.gd | Höhenänderungen, Erosion, Vulkane | raise(state, regions, amount) |
sim/biomes.gd | Biom-Klassifikation | classify(state, regions) |
sim/life.gd | Arten, Populationen, Mutation, Karten | update(state, dt) · pending_cards() · resolve_card(id, option) |
sim/civ.gd | Kulturen, Stufen, Ereignisse | update(state, dt) · inspire(civ, kind) |
sim/events.gd | Ereignistabelle, Vorwarnung, Wirkung | update(state) · pending() · resolve(id, choice) |
sim/chronicle.gd | Protokoll, Verdichtung | log(kind, regions, params, weight) · entries(from, to) |
sim/offline.gd | Makroschritte, Vorausberechnung | catch_up(state, steps) -> ReturnSummary · forecast(state, steps) -> Array[ForecastHit] |
meta/energy.gd | Regeneration, Kosten, Überladung | can_pay(cost) · pay(cost) · tick(seconds, health) |
meta/progression.gd | Epochen, Freischaltungen | check(state) -> Array[Unlock] |
meta/challenges.gd | Tages-/Wochenziele, Fortschritt | roll_daily(date, state) · progress(state) |
meta/galaxy.gd | Planetenplätze, Wechsel | open(planet_id) · create(scenario_id) |
services/save.gd | JSON + Binärblock, Versionen, atomar | save_planet(id, data) · load_planet(id) · migrate(v) |
services/time_keeper.gd | Zeitstempel, Rücksprung-Schutz | elapsed_since_pause() -> int |
view/planet_view.gd | Mesh, Datentexturen, Shader-Uniforms | apply(state, dirty) · set_quality(tier) |
view/props_view.gd | MultiMeshes je Asset/LOD | apply(state, dirty) |
view/input_router.gd | Gesten → Kamera oder Werkzeug | Signale tap(region), brush(regions), pinch(f) |
autoload/bus.gd | entkoppelte Signale | species_born, epoch_reached, event_announced, card_pending, energy_changed … |
autoload/sfx.gd | Audio-Busse, Pool, Radio | play(name) · tune(i) · set_radio(on) · duck(on) |
autoload/ads.gd | AdManager-Schnittstelle (14) | event(name) · show_rewarded(placement, cb) |
autoload/notify.gd | lokale Benachrichtigungen (13) | schedule_from_forecast(hits) · cancel_all() |
autoload/quality.gd | Stufenwahl, adaptive Absenkung | tier · Signal tier_changed |
autoload/analytics.gd | Firebase (nur Opt-in) | event(name, params) |
11.5 Speichersystem
- Profil:
user://profile.json– Einstellungen, Sternenstaub, Achievements, Planetenliste, Zustimmungen, Zeitstempel. - Planet:
user://planets/<id>.save– JSON-Kopf (Version, Epoche, Zyklus, Seed, Arten, Kulturen, Ziele) + Regionsfelder alsPackedByteArray, gesamt perFileAccess.open_compressed(zstd). - Atomar: schreiben nach
<id>.tmp, dann umbenennen; die vorige Datei bleibt als<id>.bak. Beim Laden: Prüfsumme (CRC32 im Kopf); bei Fehler.bak. - Wann: Epochenwechsel, nach jeder Evolutionskarte/Ereignis-Entscheidung, alle 60 s, bei
NOTIFICATION_APPLICATION_PAUSEDundWM_CLOSE_REQUEST, vor Eigenwerbung. - Version & Migration:
save_versionim Kopf,migrate()je Versionssprung, Test mit gespeicherten Beispielständen (tests/fixtures/saves/). - Kein Cloud-Save im MVP. Phase 3: Android Backup (Auto Backup) prüfen – kostet nichts, braucht nur
android:allowBackup+ Ausschlussregeln.
11.6 Tests & Debugging
- Headless-Tests (
tests/test_*.gd, Runnertools/godot-test.ps1nach Studio-Muster): Determinismus, Offline-Äquivalenz, Aktionen (Kosten/Validierung), Biom-Klassifikation, Populationsgrenzen, Speichern/Laden/Migration, Zielfortschritt, Zeitsicherheit. - Bot-Balancing (
tests/bot_balance.gd): Ein Bot spielt mit einfachen Regeln 30 Tage simulierte Zeit (aktive Sitzungen + Offline-Lücken) und protokolliert Epochen-Zeitpunkte und Energie-Engpässe → Abgleich mit der Zielkurve in 06 §6.6. - Benchmarks (
tests/bench_*.gd): Zyklus, Makroschritt, Szenen-Kamerafahrt → JSON nachartifacts/bench/. - Debug-Overlay (nur Debug-Builds, 3-Finger-Tipp): FPS, Frametime-Kurve, Draw Calls, Vertices, Sim-ms, Stufe, Zyklus, Seed; Datentextur-Ansichten (Temperatur/Feuchte/Biom/Population als Falschfarben).
- Testzustände (Studio-Muster
test_unlock.gd):-- --epoch=5 --seed=42 --energy=999setzt beliebige Startzustände, auf Android/iOS wirkungslos. - Capture-Modus (Studio-Muster
--capture): rendert Store- und Wiki-Screens deterministisch.
11.7 Plan B für die Rechenleistung
Falls GDScript die Budgets aus 12 verfehlt (Messung ab T-06), wird nur sim/ (ohne Schnittstellenänderung) als GDExtension in C++ neu geschrieben; Tests bleiben gleich und prüfen Gleichheit über Zustands-Hashes. Aufwand [Schätzung] 2–3 Wochen. Vorher ausschöpfen: Packed-Arrays, Schleifen ohne Dictionaries, Teilaktualisierung (dirty), Worker-Thread.