Populated from the arc42-template (EN/adoc) with project-specific content
across all 12 sections:
1. Introduction and Goals — requirements overview, quality goals, stakeholders
2. Architecture Constraints — technical (engine, collision, coordinates),
organisational (squash-merge, visual review, provenance), conventions
3. Context and Scope — business and technical context tables
4. Solution Strategy — technology decisions, top-level decomposition,
quality achievement approach
5. Building Block View — Gameplay (6 C++ classes), Site (7 meshes + 7
materials), Facades (9 buildings), Art Pipeline, QA & Review; Level 2
white boxes for input flow and collision model
6. Runtime View — walk, screenshot capture, QA self-test, build/import
pipeline scenarios
7. Deployment View — dev workstation and packaged build infrastructure
8. Cross-cutting Concepts — coordinate system, collision model, lighting,
materials, data provenance, QA harness
9. Architecture Decisions — 7 ADRs (dynamic lighting, UE materials,
C++ collision helper, grounded reset, core ticker, Y convention,
headless Blender)
10. Quality Requirements — overview table + 7 measurable scenarios
11. Risks and Technical Debts — 5 risks, 2 debts with mitigations
12. Glossary — 16 domain-specific terms
Master document: Docs/Architecture/architecture.adoc
Config: Docs/Architecture/config.adoc
48 lines
3.2 KiB
Plaintext
48 lines
3.2 KiB
Plaintext
ifndef::imagesdir[:imagesdir: ./images]
|
||
|
||
[[section-design-decisions]]
|
||
== Architecture Decisions
|
||
|
||
=== ADR-1: Dynamic-only lighting for the demo
|
||
|
||
* **Context**: The demo is a fixed daytime scene. Stationary lights demand a lighting build and produce "LIGHTING NEEDS TO BE REBUILT" warnings.
|
||
* **Decision**: `r.AllowStaticLighting=False`, all lights `MOVABLE`.
|
||
* **Consequences**: No bake step, no warning, simpler iteration. Slightly higher GPU cost per frame (no baked shadows) — acceptable for the demo scope.
|
||
|
||
=== ADR-2: Materials authored in Unreal, not imported from Blender
|
||
|
||
* **Context**: FBX→Unreal import maps all Blender diffuse colours to white. Flat colour materials do not survive the pipeline.
|
||
* **Decision**: Build all materials (asphalt, concrete, stucco, façade stone, road paint) directly in Unreal with procedural nodes.
|
||
* **Consequences**: Materials cannot be previewed in Blender look-dev. Must round-trip to Unreal for visual check. But: full PBR control, world-space noise, no import surprise.
|
||
|
||
=== ADR-3: Complex-as-simple collision on terrain via C++ helper
|
||
|
||
* **Context**: UE 5.8 removed `bUseComplexAsSimpleCollision`. Python cannot set `CollisionTraceFlag` on `StaticMesh`/`BodySetup` at all. The Interchange default is bbox-only simple collision, which placed an invisible lid 8 m above the street.
|
||
* **Decision**: `UGigLineAssetTools::SetComplexCollisionAsSimple` (C++) forces `CTF_UseComplexAsSimple` and saves the asset.
|
||
* **Consequences**: One C++ helper class. The flag must be saved on the asset (not just the map). No Python workaround exists.
|
||
|
||
=== ADR-4: Reset captures StartLocation on first grounded frame
|
||
|
||
* **Context**: `BeginPlay` captures `StartLocation` at the PlayerStart, which is above grade (Z 600) so the capsule does not spawn embedded. Every reset dropped the player 1.4 m back into the air.
|
||
* **Decision**: Repeating 0.25 s timer captures `StartLocation` once the character reports `IsMovingOnGround()`, then clears itself.
|
||
* **Consequences**: Reset is correct. A one-shot timer at 2 s is wrong (fires after walking begins, records mid-stride position).
|
||
|
||
=== ADR-5: Core ticker for QA self-test, not world timer
|
||
|
||
* **Context**: Pausing the game stops world timers. A timer-driven test freezes exactly when it proves pause works.
|
||
* **Decision**: `FTSTicker::GetCoreTicker()` drives the `-qaselftest` harness.
|
||
* **Consequences**: Test runs even while paused. Must be enabled explicitly (`-qaselftest`), never in normal play.
|
||
|
||
=== ADR-6: South = +Y, north = −Y in Unreal
|
||
|
||
* **Context**: The street mesh established this convention: `Sidewalk_North` has Y range −1912..−1053, `Sidewalk_South` has +718..+1447.
|
||
* **Decision**: Adopt it project-wide. Never place a building by assumption; always verify against a street mesh or neighbour.
|
||
* **Consequences**: Matches Blender's north→+Y after the Y-flip in the `ue_metric_v1` export preset.
|
||
|
||
=== ADR-7: Headless Blender via bpy scripts, not MCP
|
||
|
||
* **Context**: Blender skill packs assume an MCP server; the project does not run one.
|
||
* **Decision**: All Blender work driven by Python scripts in `Tools/`. Skill packs used as method guides (checklists, naming, proportions) only.
|
||
* **Consequences**: Scripts are version-controlled and repeatable. No live Blender session needed for CI.
|
||
|