Parent: #259 (techdesign) — see sdlc/#259/design.md, lever L3. Gated on #446 (profile first — #260 closed without recording numbers).
Reanalyzed 2026-07-04: gate moved #260→#446; building-collider facts updated; options unchanged.
Why
Each chunk adds a GameObject + MeshFilter + MeshCollider per road, sidewalk, and intersection (see the road/sidewalk/intersection loops in ImportChunk). PhysX cooks each collider inline on AddComponent, no batching — tens of thousands of cooks city-wide. Hypothesised top-tier cold-import cost (confirm via #446).
Update: buildings now also carry one combined MeshCollider per chunk (#415, for graffiti spray raycasts #390) — so the "combine per chunk" pattern already has two precedents (building render mesh + building collider).
Options (pick after #446 numbers, increasing effort)
- Combine colliders per chunk — merge road/sidewalk/intersection collider meshes into one (or one-per-type). Cuts collider and GameObject count (smaller prefabs). Constraints: keep roads/intersections on the Road layer (traffic raycasts) separate from sidewalks (kerbs must not read as drivable) and from the building collider (spray targets);
RoadNetwork builds from _names.json, not colliders, so per-osmId collider identity is not load-bearing — verify nothing else reads collider names.
- Off-thread cook —
Physics.BakeMesh(meshId, convex) in parallel jobs, assign sharedMesh on the main thread.
- Defer colliders to runtime chunk-load in
ChunkStreamer (only resident chunks pay). Highest risk — verify traffic + on-foot + spray tolerate collider-free prefabs at import time.
Done when
Collider-related import cost is materially reduced (per #446 before/after) with traffic raycasts, on-foot physics, and spray-paint hits still correct.
Parent: #259 (techdesign) — see
sdlc/#259/design.md, lever L3. Gated on #446 (profile first — #260 closed without recording numbers).Reanalyzed 2026-07-04: gate moved #260→#446; building-collider facts updated; options unchanged.
Why
Each chunk adds a GameObject +
MeshFilter+MeshColliderper road, sidewalk, and intersection (see the road/sidewalk/intersection loops inImportChunk). PhysX cooks each collider inline onAddComponent, no batching — tens of thousands of cooks city-wide. Hypothesised top-tier cold-import cost (confirm via #446).Update: buildings now also carry one combined MeshCollider per chunk (#415, for graffiti spray raycasts #390) — so the "combine per chunk" pattern already has two precedents (building render mesh + building collider).
Options (pick after #446 numbers, increasing effort)
RoadNetworkbuilds from_names.json, not colliders, so per-osmIdcollider identity is not load-bearing — verify nothing else reads collider names.Physics.BakeMesh(meshId, convex)in parallel jobs, assignsharedMeshon the main thread.ChunkStreamer(only resident chunks pay). Highest risk — verify traffic + on-foot + spray tolerate collider-free prefabs at import time.Done when
Collider-related import cost is materially reduced (per #446 before/after) with traffic raycasts, on-foot physics, and spray-paint hits still correct.