Child of #390 (graffiti mechanic). See sdlc/#390/plan.md → C1.
Why: SFMapImporterWindow.cs:476–481 gives buildings MeshFilter+MeshRenderer but no collider (BuildingAssembler.cs:726 drops it). On-foot raycasts pass through walls, so facades can't be sprayed. Hard prerequisite for the whole mechanic.
Scope: Add a MeshCollider to streamed building meshes on a hittable layer (Default is fine). Decide bake-time vs runtime-on-load; keep parked-car nesting + streaming unchanged.
Acceptance: on foot, a forward raycast hits a building wall at the expected point/normal; car/traffic/streaming unaffected.
Risk: MeshCollider cook is a tracked import hotspot (_timings.colliderMs) — one cook per combined chunk building mesh; verify no meaningful import regression.
Blockers: none.
Child of #390 (graffiti mechanic). See sdlc/#390/plan.md → C1.
Why:
SFMapImporterWindow.cs:476–481gives buildings MeshFilter+MeshRenderer but no collider (BuildingAssembler.cs:726drops it). On-foot raycasts pass through walls, so facades can't be sprayed. Hard prerequisite for the whole mechanic.Scope: Add a MeshCollider to streamed building meshes on a hittable layer (Default is fine). Decide bake-time vs runtime-on-load; keep parked-car nesting + streaming unchanged.
Acceptance: on foot, a forward raycast hits a building wall at the expected point/normal; car/traffic/streaming unaffected.
Risk: MeshCollider cook is a tracked import hotspot (
_timings.colliderMs) — one cook per combined chunk building mesh; verify no meaningful import regression.Blockers: none.