7.6 KiB
NEON-29 Implementation Plan — Expand prototype client district for camera/nav stress QA
Story reference
- Key: NEON-29
- Title: E1.M2: Expand prototype client district for camera/nav stress QA
- Parent epic: NEON-1 — Epic 1 — Core Player Runtime
- Labels: E1, E1.M2, client-qa-district, decomposition
Goal, scope, and out-of-scope
Goal
Provide a ~5× footprint (order-of-magnitude) prototype play space versus the current district, with more obstacles and height-changing regions (steps, terraces, bumps) so day-to-day client work can stress motion, framing, and readability for the camera, navigation, ground pick, and interaction systems.
Scope
client/scenes/main.tscn: expand walkable floor / nav source geometry; add props that participate inNavigationRegion3Dbake andwalkablepicking as today; include elevated terrace/step platforms for vertical variation.client/README.md: short runbook note covering district scale, intent, and any new designer-facing limits.- Optional: pointer in
docs/decomposition/modules/E1_M2_IsometricCameraController.mdthat this geography is the default stress playground for client stories.
Out of scope
- New camera features (zoom bands NEON-26, occlusion NEON-27) — geography may help test them, but this story does not implement them.
- Server schema or MoveCommand contract changes unless existing NEON-7 step/bounds defaults visibly break on the larger map (in that case: document + minimal config tune only).
- Production art pass or zone graph / Epic 4 content.
Acceptance criteria checklist
- Playable area is materially larger (~5× order of magnitude vs pre-change footprint) with additional obstacles and vertical variation usable with click-to-move.
- NavigationRegion3D bakes successfully at startup; long clicks behave per existing NEON-8 tradeoffs (document if new geometry exposes new edge cases).
- Ground pick and
walkablegrouping remain correct on new surfaces. - README updated for anyone running F5 + server.
Technical approach
Current baseline
The current main.tscn district is a single 20 × 20 unit flat floor (BoxMesh_floor, placed at Y = -0.1), giving an approximate playable area of ~400 sq units. Static props:
PrototypeTerminal(0.9 × 1 × 0.4) at originMoveRejectPedestal(1.5 × 2.5 × 1.5) at (7.5, 0, -6.5)MoveRejectFarPad(2.5 × 0.12 × 2.5) at (9, 0.06, 9)Obstacle(2 × 2 × 2,occludergroup) at (6, 0, 5)- Player spawn at (-5, 0.9, -5)
The NavigationMesh stored in the scene file is intentionally stale; main.gd calls bake_navigation_mesh(false) at startup so the live mesh always reflects actual collision geometry.
Expansion plan
Floor size: Replace the 20 × 20 floor with a 45 × 45 unit floor, giving ~2025 sq units (~5× of 400). Keep floor mesh center at origin (X=0, Z=0) so spawn position and existing props stay roughly central.
Additional obstacles (nav stress + camera occlusion): Add 3–4 extra StaticBody3D nodes in the occluder group, distributed across the expanded area — positioned so the follow camera must work around varying angles.
Vertical variation (terraces / steps): Add 2–3 raised terrace platforms as StaticBody3D nodes in the walkable group, elevated ~0.5–2.5 m above the main floor, with ramp/step approach geometry. These are StaticBody3D siblings of Floor under NavigationRegion3D so the runtime bake includes them as nav sources. Each terrace:
- Has its own
CollisionShape3D(BoxShape3D). - Is in the
walkablegroup so ground-pick raycasts hit it correctly. - Has a small
StaticBody3Dramp or step approach (alsowalkable) soNavigationAgent3Dcan route onto it within the NEON-8 step/climb parameters (agent_max_climb = 0.35in existing NavMesh settings — ramp grade must respect this, or use multi-step approach).
MoveReject props: Keep MoveRejectPedestal and MoveRejectFarPad in place — they exercise NEON-7 reject behavior and must remain reachable. Shift MoveRejectFarPad outward if needed to stay within the expanded floor bounds and remain "far."
NavigationMesh settings: No changes to agent parameters (height=1.0, radius=0.4, max_climb=0.35, cell_size=0.15) — they remain aligned with the player capsule per NEON-8. The stale baked mesh in the scene will update at runtime. The geometry_collision_mask = 1 stays, so all collision-layer-1 bodies under the region contribute.
NEON-7 edge case check: With a larger floor the server's step_size / MaxDistance defaults may now allow clicks that would previously have been out-of-range. Document in the README if this changes observed reject behavior; no server code change unless a new reject case is broken (not just shifted in range).
Files to add
None. All geometry lives in the existing scene file; no new GDScript logic is required.
Files to modify
| File | Rationale |
|---|---|
client/scenes/main.tscn |
Replace 20×20 floor with 45×45; add terrace/step platforms and extra obstacle props; update pre-baked NavigationMesh vertices (will be overwritten at runtime, but keeping a reasonable approximation avoids editor warnings). |
client/README.md |
Add district runbook note: new footprint, vertical variation, intent as stress playground, updated manual-check geometry references. |
docs/decomposition/modules/E1_M2_IsometricCameraController.md |
Optional lightweight pointer that this expanded geography is the default QA map for E1.M2 camera stories. |
Tests
No new automated GDScript tests are added for this story — there is no new GDScript logic. This story is pure scene geometry.
Manual verification replaces automated tests:
- F5 with server running: confirm player spawns and nav bake completes without errors in Output.
- Click-to-move across the expanded floor, up/down each terrace, and through obstacles — confirm
NavigationAgent3Droutes andmove_and_slidebehaves per NEON-8 tradeoffs. - Ground-pick regression: click behind each new
occluder-tagged obstacle with player in and out of occlusion fade range (per NEON-30 manual check in README). - Confirm
MoveRejectPedestalandMoveRejectFarPadstill reject correctly. - Follow camera: walk to far corners of the expanded floor — confirm
IsometricFollowCameratracks smoothly without snapping or losing the player (snap_distance not tripped by longer walks). - Interaction radius: walk near
PrototypeTerminalto confirm range indicators still work correctly.
Decisions
- No horizontal step limit (resolved): The server's
MaxHorizontalStep = 18 mwas too restrictive for the expanded 45 × 45 m floor (diagonal ≈ 63 m). AddedHorizontalStepEnabledbool toMovementValidationOptions(defaultsfalse), matching theDistrictBoundsEnabledpattern. The horizontal check is now skipped by default; the property remains available to opt back in via config.MoveRejectFarPadno longer exercises a horizontal range reject; it retains its walkable surface for vertical-step regression only.
Open questions / risks
- NavMesh bake time: A 45×45 floor with several terraces will bake more polygons than the 20×20 baseline. Expected to be negligible for
bake_navigation_mesh(false)on desktop, but monitor Output for a perceptible pause. - Agent climb on terraces:
agent_max_climb = 0.35limits single-step height. Each terrace transition is 0.30 m; verify in Godot editor nav mesh debug overlay before shipping.