| F-1 |
KRITISCH |
Rest-Sim-Unterbudget ≤3 ms ist ein Restmüll-Posten ohne Validierungs-Gate. Es muss Kampf (Zielsuche, Projektile ≤2.000, Schadensereignisse), Wirtschaft (Harvester-Routen, Aetherium-Ausbreitung), Produktion und die gesamte KI-Command-Verarbeitung abdecken – letztere explizit ohne eigenes Budget („vorläufig im Rest-Sim-Posten enthalten"). Von den vier Phase-0-Gates V1–V4 validiert keines den Rest-Sim: V1 = Determinismus, V2 = Rendering, V3 = Animation, V4 = nur Pathfinding. Das riskanteste Unterbudget hat also kein Mess-Gate. Gegenrechnung Zielsuche: 500 Einheiten mit Auto-Angriff ohne dedizierte Spatial-Struktur = 500² = 250.000 Paarprüfungen/Tick ≈ 1–5 ms managed allein für Targeting; mit Spatial Hash (der nur im Pathfinding-Modul spezifiziert ist, nicht im Kampf) wären es ~10.000 Prüfungen – trivial. Es geht also, aber nur mit einer Struktur, die nirgends verbindlich spezifiziert ist. |
PerformanceBudget.md:38 (Rest-Sim ≤3 ms), :116 (V4 deckt nur PF), :125 (KI ohne Budget); MemoryBudget.md:78 (Projektile ≤2.000); tech/Pathfinding.md:70 (Spatial Hash existiert nur dort) |
Fünftes Phase-0-Gate V5 definieren: P95 Sim.Combat + Sim.Economy + Sim.AI ≤3 ms im Massenschlacht-Szenario (500 Einheiten, beide Seiten KI-gesteuert) auf dem Managed-Pfad. Kampf-Subsystem-TDD muss Zielsuch-Datenstruktur (Spatial Hash, Re-Query-Intervall) verbindlich festlegen, bevor Sprint 7 beginnt. |
| F-2 |
KRITISCH |
D-037-Hash-Parität Managed ↔ Burst ist technisch nicht garantiert und erzeugt Messblindheit. (a) Bit-identische Ergebnisse zwischen Burst-compiliertem Code (LLVM, FMA-Kontraktion, aggressive Optimierung) und Mono/IL2CPP-Managed-Code sind für float-MVP-Code nicht gesichert; die Paritäts-Hash-CI wird entweder dauerhaft rot (und wird dann ignoriert) oder erzwingt künstlich pessimisierten Burst-Code. (b) Asymmetrie: SimRunner/CI-Trend-Historie (Regression >10 % = Warnung) misst den Managed-Pfad; das ausgelieferte Spiel läuft auf Burst. Fällt das Budget nur im Managed-Pfad durch, entscheidet D-037 „Burst bleibt" – dann misst die CI dauerhaft einen Codepfad, den kein Spieler ausführt, und Regressionen im Burst-Pfad sind unsichtbar. (c) V1 (ARM↔x86, 10.000 Ticks) prüft nicht die Kombinationsmatrix Managed/Burst × ARM/x86. |
DecisionLog.md:346–352 (D-037, „Pflicht-Hash-Parität", „hält der Managed-Pfad das Budget, kann Burst ganz entfallen"), :402 (V4 explizit Managed-Pfad); PerformanceBudget.md:65 (SimRunner-Trend-CI) |
Sprint 4: Paritäts-Matrix festlegen – V1 auf 4 Konfigurationen erweitern (Managed/Burst × ARM/x86, jeweils 21.000 Ticks = längstes Match). Klären, welcher Pfad der Budget-referenzielle ist (Empfehlung: Managed, da CI-messbar) und ob Budget-Überschreitung im Managed-Pfad dann nicht „Burst rettet schon", sondern ein Release-Blocker ist. Integer-/Fixed-Point-first für alle paritätspflichtigen Hotspots, float nur wo beweisbar bit-stabil. |
| F-3 |
HOCH |
KI-Subsystem hat keinerlei Performance-Budget und keine Architektur-Verankerung in den Performance-Dokumenten. Utility-Director + HTN + Squad-BTs für bis zu 8 KI-Spieler (SimRunner-KI-vs-KI) laufen im Sim-Tick; Literature-Erfahrung: Utility-Scoring über alle Einheiten × alle Optionen wächst quadratisch, wenn Optionen einheitenbezogen sind. Ohne Unterbudget und ohne Messmarker (Sim.AI ist als Marker genannt, aber ohne ms-Zahl) ist ein Budget-Bruch erst am fertigen System sichtbar. |
PerformanceBudget.md:63 (Marker Sim.AI ohne Unterbudget), :125 (Offener Punkt: „hängt vom KI-TDD ab, vorläufig im Rest-Sim") |
KI-TDD (Sprint 3/4) muss eigenes Unterbudget aus dem Rest-Sim-Posten herauslösen (Vorschlag: KI ≤1 ms, davon Director 0,5 / Squad-BTs 0,5) plus Skalierungsregel (Anzahl KI-Spieler × Einheiten). Influence-/Bedrohungskarten-Update-Frequenz deckeln (s. F-13). |
| F-4 |
HOCH |
Flow-Field-Cache-Deckel (32 Felder) unterdeckt den Wirtschafts- und KI-Mikro-Fall. Cache-Schlüssel ist (ZielCluster, RadienKlasse): 8 Spieler × 3 Angriffsgruppen × 3 Clearance-Klassen = 72 > 32 – und das ignoriert Harvester. Das Research warnt explizit: „viele gleichzeitige Einzelziele (z. B. KI-Mikro, verstreute Sammler) sind teurer". Harvester pendeln Feld↔Raffinerie: bei 8 Spielern à 10–20 Sammlern drohen 80–160 aktive Ziele, sofern das Ziel-Clustering „gleiche Raffinerie = gleiches Cluster" nicht greift. LRU-Eviction erzwingt dann Neu-Fills: Dijkstra-Fill über 65.536 Zellen ≈ 0,5–2 ms managed; 2–3 Thrash-Fills/Tick brechen das ≤4-ms-PF-Budget bereits ohne jede Armeebewegung. |
tech/Pathfinding.md:30 (32 Felder), :52 (Cache-Schlüssel); MemoryBudget.md:117 (selbst als Annahme markiert); research/Pathfinding.md:56 (Warnung Einzelziele) |
Ziel-Clustering-Regeln für Wirtschaft explizit spezifizieren (Raffinerie/Feld = feste Cluster-Anker, Harvester teilen 2 Felder pro Spieler). Spike V4 erweitern: Szenario „8 KI-Spieler Vollwirtschaft + 3 Angriffe" statt nur „500 Agenten, 1 Ziel". Cache-Deckel nach Messung fixieren, Eviction-Thrash-Metrik (Fills/Tick) in den Budget-Monitor. |
| F-5 |
HOCH |
Kampf-Subsystem fehlt als Performance-Thema vollständig. Kein geprüftes Dokument spezifiziert: Datenstruktur der Zielsuche, Re-Query-Intervalle, Projektil-Update-Kosten (Pool ≤2.000), Schadensereignis-Volumen (500 Einheiten × Feuerrate), AoE-Schaden (Superwaffen: Flächenschaden über Einheiten im Radius = weitere O(n)-Scans). Der Marker Sim.Combat existiert, ohne ms-Budget oder Designquelle. Die versteckte O(n²)-Falle des Projekts sitzt hier, nicht im Pathfinding. |
PerformanceBudget.md:63 (Marker ohne Budget); MemoryBudget.md:78 (Projektil-Pool 2.000, ohne Tick-Kosten); kein Combat-TDD in docs/tech |
Combat/Weapons-TDD (oder Abschnitt im Sim-TDD) mit verbindlichen Kostenmodellen: Zielsuch-Intervall (z. B. Re-Query alle 3–5 Ticks gestaffelt nach UnitId), Spatial-Hash-Wiederverwendung aus dem Pathfinding, AoE über Grid-Buckets. Budget-Split des Rest-Sim-Postens dokumentieren. |
| F-6 |
HOCH |
GPU-Budget ≤8 ms ohne Referenz-Auflösung und ohne Unterposten ist nicht falsifizierbar. Eigene Summenschätzung auf RTX 3060 @ 1440p: Forward-Basis 1,26 M Tris ≈ 2–3 ms, Shadow 2048²/2 Cascades mit ~500 Werfern ≈ 1–2 ms, FoW-Fullscreen-Pass (Depth-Rekonstruktion + 3×3-Blur + Ping-Pong-Easing) ≈ 0,5–1,5 ms, Bloom ≈ 0,5–1 ms, STP-Upsampling ≈ 1–2 ms, Minimap-RT + Overlay ≈ 0,5 ms → 5,5–10 ms: das Budget ist je nach Auflösung erfüllt oder gebrochen. „Premium SP-first" impliziert 1440p/4K-Ambitionen; bei 4K ist 8 ms mit diesem Stack unrealistisch. |
PerformanceBudget.md:40 (GPU ≤8 ms, keine Auflösung), :124 (Unterposten erst Sprint 6); Rendering.md:81 (Fullscreen-Pass + Blur + Ping-Pong), :117 (RenderScale 1,0 + STP) |
Referenz-Auflösung ins Budget aufnehmen (Empfehlung: 1440p Hoch / 1080p Mittel) und 4K explizit als Nicht-Ziel für 60 FPS deklarieren oder Qualitätsstufe dafür definieren. GPU-Unterposten-Schätzung bereits in Sprint 4 statt Sprint 6 (Shadows / FoW-Pass / Post / STP), um den Rendersequenzen-TDD nicht auf Sand zu bauen. |
| F-7 |
HOCH |
Ausführungsmodell des Sim-Ticks (Main Thread vs. Worker) ist nicht festgelegt – bei synchroner Ausführung ist die Frame-Summe kritisch. Tick-Frame: Sim 8,0 + Render-CPU 4,0 + UI 1,0 + Audio 0,5 = 13,5 ms seriell, Reserve 3,1 ms. Die Messregel erlaubt P95 = volle Budget-Auslastung aller Posten gleichzeitig; dann bleiben exakt 3,1 ms für OS-Jitter, GC und Unity-internen Overhead (Job-Scheduling, Render-Thread-Sync) – auf Windows mit Hintergrundlast wird das der spürbare Mikro-Ruckler alle 600 ms. Die naheliegende Alternative – Sim-Tick auf Worker-Threads, View rendert Snapshot n−1 (die View liest ohnehin nur Snapshots, D-033 Regel 5) – ist nirgends geprüft; stattdessen verbietet das Dokument „implizites Spreading", ohne die Worker-Option zu diskutieren. |
PerformanceBudget.md:34 („kein implizites Spreading"), :36–43 (Tabellensumme), :45 (P95-Regel); Rendering.md:21 (View liest Snapshot) |
Architektur-Entscheidung einfordern (D-Kandidat): synchroner Tick auf Main Thread vs. Worker-Tick mit 1-Frame-Snapshot-Latenz. Letzteres entkoppelt Sim-Budget vom Frame-Budget fast vollständig und ist durch D-033 bereits vorbereitet. Bis zur Entscheidung Reserve im Tick-Frame als hartes Budget (nicht „≥", sondern bewacht) führen. |
| F-8 |
HOCH |
Healthbar-Overlay: dynamisches Mesh „pro Frame (bzw. pro Änderung)" ohne Puffer-Strategie kollidiert frontal mit dem View-GC-Ziel ≤1 KB/Frame. Naiver Mesh-Rebuild bei 500 sichtbaren Einheiten: 500 × (HP-Quad + Selektionsquad) × 4 Vertices × ~32 B ≈ 64–128 KB transienter Array-Allokation pro Frame – Faktor 64–128 über dem eigenen View-Budget und damit ein Gen-0-/Gen-1-GC-Generator genau in Massenschlachten. Die 0-B-Regel gilt nur für die Sim; die View-Regel ist der schwächere Deckel, und genau hier wird er gebrochen, wenn die Implementierung dem Text folgt. |
Rendering.md:49 (Overlay-Design); MemoryBudget.md:80 (View ≤1 KB/Frame transient), :78 (foreach-/Allokations-Verbote nur Sim) |
Verbindlich machen: Mesh.AllocateWritableMeshData + persistente Max-Kapazitäts-Puffer, Double-Buffering, Upload nur geänderter Ranges (Mesh.SetSubMesh/partial update). Ins Rendering-TDD als Muss-Anforderung aufnehmen und ins V2-Spike-Kriterium integrieren (Allokationsprobe auch im View-Pfad). |
| F-9 |
MITTEL |
FoW-Einheiten-Culling per SetActive/Layer-Swap bei 500 Einheiten × Sicht-Tick invalidiert GPU-Resident-Drawer-Batches. Der Resident Drawer ist für stabile Renderer-Mengen ausgelegt; Sichtwechsel-Wellen (Scout fliegt über Basis → hunderte Toggles in einem Sicht-Tick) erzeugen Batch-Rebuilds genau im Lastmoment. Das Dokument markiert das als offenen Punkt, beziffert aber weder Fallback-Kosten (eigener UnitRenderBatcher = Neuentwicklung des Render-Pfads) noch die Toggle-Frequenz. |
Rendering.md:33 (Resident-Drawer-Warnung), :82 (Layer-Swap/Deaktivierung), :131 (offen) |
Im V2-Spike zusätzlich messen: Toggles/Sicht-Tick im FoW-Stress-Szenario (d) und Batch-Rebuild-Kosten. Fallback-Kosten grob schätzen (PT-Aufwand UnitRenderBatcher), damit ein Resident-Drawer-Ausfall nicht die Sprint-7-Planung sprengt. |
| F-10 |
MITTEL |
Dirty-Region-Stürme sind mengenmäßig unbegrenzt modelliert. Aetherium-Ausbreitung (Alien-Welt +50 %, „jede Wachstumsstufe meldet ihre Tile-Region"), Vegetationsbrände, Trümmer-Verfall und Mauerbau können im selben Tick dutzende Regionen melden; partielles Recompute kostet O(aktive Felder × betroffene Regionen). Der Amortisierungs-Deckel („Max. N Feld-Fills pro Tick") hat keinen Zahlenwert; der Deferred-Pfad („Einheiten folgen 1–2 Ticks dem alten Feld") kollidiert bei anhaltender Region-Flut mit der Frischegarantie – einstalende Ausbreitung kann Felder dauerhaft veralten lassen. |
tech/Pathfinding.md:58–66 (Quellenliste), :155 (N unbeziffert); gamedesign-Anker +50 % (Lighting.md:101) |
N beziffern (Empfehlung: ≤2 Voll-Fills + ≤8 Teil-Recomputes pro Tick) und Region-Koaleszierung (Merge überlappender AABBs pro Tick) verbindlich machen. Staleness-Obergrenze (Ticks) definieren, ab der Einheiten gestoppt statt falsch geführt werden. Dirty-Stresstest (existiert in :162) mit konkreter Regionen-Rate versehen. |
| F-11 |
MITTEL |
ORCA-Eigenbau in Fixed-Point ab Alpha trägt dreifache Paritätslast (Managed ↔ Burst ↔ Fixed-Point) und ist algorithmisch die fehleranfälligste Komponente. RVO2-Implementierungen sind notorisch empfindlich gegenüber Reihenfolge-/Rundungsdetails; die Anforderung „Iterationsreihenfolgen über Spatial-Hash-Buckets sind stabil zu definieren" ist notwendig, aber bei weitem nicht hinreichend (ORCA-LP-Lösung, Tie-Breaks). Alpha-Zeitpunkt + Beta-Fixed-Point-Umstellung bedeuten zwei nachträgliche Heart-Surgery-Eingriffe am laufenden System. |
tech/Pathfinding.md:71–72; DecisionLog.md:346–352 (D-037); PerformanceBudget.md:113 (V1 Fixed-Point erst Beta) |
ORCA-Paritätsstrategie jetzt festlegen: entweder ORCA von Anfang an Integer-/Fixed-Point-nah designen (kein Float-Provisorium) oder Beta-Umstellung als eigenen Mini-Spike mit eigenem Gate einplanen. Referenz-Testvektoren (RVO2-Standard-Szenarien) in die Golden-Paths aufnehmen. |
| F-12 |
MITTEL |
Native/Engine-Deckel ≤1,0 GB ist eine unbegründete Wunschzahl. URP mit HDR, STP, 2048²-Shadowmaps (2–3 Cascades), FoW-Ping-Pong-RTs, Minimap-RT, Bloom-Pyramide und IL2CPP-Runtime liegt erfahrungsgemäß bei 0,8–1,4 GB je nach Auflösung – der Deckel kann schon durch Engine-Defaults reißen, bevor ein einziges Asset geladen ist. Gleichzeitig ist das macOS-8-GB-Verhalten (Unified Memory, GPU teilt RAM) ungemessen: Auf 8-GB-Macs stehen nach OS ~5 GB zur Verfügung; 1,8 GB Assets + 1 GB Engine + 0,5 GB Heap + 0,6 Reserve ≈ 3,9 GB lässt praktisch keinen Swap-Spielraum. |
MemoryBudget.md:24 (Deckel, „Messbasis Phase-0"), :120 (macOS ungemessen); Rendering.md (HDR/STP/Shadow-Setup) |
Native-Baseline-Messung aus Phase 0 vorziehen (leere URP-Szene mit Ziel-Setup auf Referenz-PC + 8-GB-Mac) und Deckel ggf. vor Asset-Produktionsstart korrigieren. Mindest-RAM-Anforderung (8 vs. 16 GB) als Sprint-4-Entscheidung, nicht nach Phase 0. |
| F-13 |
MITTEL |
KI-Einfluss-/Bedrohungskarten haben weder Speicher- noch Tick-Budget. MemoryBudget führt „Einflusskarten für den KI-Director" als offenen Punkt innerhalb der 100-MB-Kappe, DecisionLog listet „KI-Bedrohungskarten-Auflösung" als Folgepunkt. N Influence-Maps à 65.536 Zellen à 2–4 B, aktualisiert pro Tick oder Sicht-Tick, sind der klassische schleichende Speicher-/CPU-Fresser (10 Karten à 4 B = 2,6 MB, Update 10 × 65 k Zellen = 650 k Zell-Operationen). |
MemoryBudget.md:58, :116; DecisionLog.md:403 (offener Folgepunkt) |
Im KI-TDD verbindlich: Anzahl Karten, Datentyp, Auflösung (1 m vs. 4 m – Vierfach-Reduktion der Kosten), Update-Frequenz (≤1 Hz reicht für Strategie-Ebene). In die 100-MB-Kappen-Tabelle als eigene Zeile aufnehmen. |
| F-14 |
NIEDRIG |
Inkonsistente Animations-Budgets: V3-Spike-Kriterium verlangt Animations-Anteil ≤1,5 ms am Rendering-CPU-Posten; AnimationSystem.md definiert ≤2 ms Animations-CPU. Zwei Zahlen für dieselbe Größe ohne Verweis, welche führend ist. |
PerformanceBudget.md:115; AnimationSystem.md:109 |
Eine Zahl als führend markieren (Empfehlung: 1,5 ms als Budget, 2 ms als P99-Deckel), Dokumente angleichen. |
| F-15 |
NIEDRIG |
Divergierende Kartengrößen-Annahmen in den Kostenmodellen: research/FogOfWar.md und research/Pathfinding.md rechnen mit 512×512 m (262 k Zellen), die tech-TDDs mit maximal 256 m (65 k Zellen). Die FoW-/PF-Kostenabschätzungen sind dadurch um Faktor 4 unterschiedlich begründet; „FoW ≤1 ms" stützt sich implizit auf die kleinere Karte, während das Research die Reserve aus der großen ableitet. Maps.md-Maximum (256 m) ist führend, aber nicht überall referenziert. |
research/FogOfWar.md:121; research/Pathfinding.md:140 („Feld-Fill bei 512×512"); tech/Pathfinding.md:24 |
In beiden Research-Dokumenten klarstellen, dass 512 m ein Worst-Case-Szenario jenseits des GDD-Maximums ist (Reserve-Argument), oder Kostenmodelle einheitlich auf 256 m normieren. |
| F-16 |
NIEDRIG |
Dokumentations-Drift zu Trümmer-Persistenz: D-042.2 hat entschieden (Fade-out 60 s + hartes Cap), AssetBudget.md:151 und Rendering.md:135 führen dasselbe Thema weiter als „offen / nicht entschieden". |
DecisionLog.md:392; AssetBudget.md:151; Rendering.md:135 |
Beide TDDs auf D-042.2 nachziehen (Offene-Punkte-Eintrag schließen, 60-s-Fade + Cap als verbindlich referenzieren). |
| F-17 |
NIEDRIG |
V1-Gate (10.000 Ticks divergenzfrei) deckt nicht das längste Match ab: 10.000 Ticks = 16,7 min bei 10 Hz; GDD-Matchdauer bis 35 min = 21.000 Ticks. Ein Desync ab Tick 15.000 (z. B. durch späte Fixed-Point-Rundungsdrift) entgeht dem Gate. |
PerformanceBudget.md:113; MemoryBudget.md:38 (21.000 Ticks) |
V1 auf 21.000 Ticks (35-min-Match) plus Sicherheitszuschlag erhöhen; Kosten sind CI-Minuten, kein Implementierungsaufwand. |
| F-18 |
NIEDRIG |
0-B/Tick-Enforcement erfasst nur Managed-Allokationen. GC.GetAllocatedBytesForCurrentThread() sieht keine NativeArray-/Allocator.TempJob-Allokationen im Burst-Pfad und keine Native-Leaks durch vergessenes Dispose() – genau die Fehlerklasse, die D-037 einführt. |
MemoryBudget.md:75 (Regel 1); tech/Pathfinding.md:153 (NativeArray-Views) |
Allokationsprobe um Native-Checks ergänzen: Unity.Collections Leak-Detection (NativeLeakDetection-Mode) im Development-Build/CI verpflichtend, Dispose-Analyzer-Regel in CodingGuidelines. |