"Runtime world-building helpers"
▸ SYMPTOM
- Hand-placing every prop in the scene editor doesn't scale; you want C# to build the world at boot.
- Build-validity checks via physics traces are flaky (water, felled trees, overlapping footprints).
- Decals sink into the ground; wires don't stretch between points.
▸ CAUSE
A small set of spawn helpers + a data obstacle list is enough for most stylized games. Physics queries are the wrong tool for "can I place here?" when you already know every footprint you spawned.
▸ FIX
Helpers worth having
FlatBox: models/dev/box.vmdl is a 50u cube. Scale with:
go.WorldScale = size / 50f;
renderer.MaterialOverride = terrainOrWaterMat;Remember: flat ground decals (water/roads). Top surface must sit above the ground plane top. This is only half the rule, though: lifting an overlay clears it of the ground, but says nothing about overlays clearing each other, or about a single closed overlay (a loop/ring path) crossing its own footprint. Stacked or self-crossing overlays still z-fight unless you give each layer its own distinct lift and break self-crossing loops into non-overlapping segments.
Prop: catalog model + bounds-sized static BoxCollider + register a placement obstacle.
Deco: renderer only (flowers, clutter), no collider, no footprint.
Wire, thin box stretched between two points:
var delta = b - a;
go.WorldPosition = (a + b) * 0.5f;
go.WorldRotation = Rotation.LookAt(delta.Normal);
// scale the 50u dev box: length/50 along the axis pointing at the target, thickness on the other twoWhich scale component maps to which world axis depends on your box's orientation under LookAt: measure one wire visually, then hard-code the mapping.
Placement as plain data
record struct Obstacle(GameObject Go, Vector3 Pos, float Radius, bool IsWater);
// removable by GameObject when a tree is felled
// water flag lets creek-only buildables opt out of "blocked by water"Prefer this over scene traces for build-validity. Forbid placement inside the player's footprint too (see kinematic-movement-startedsolid).
Boot order
Managers → world builder → state. Mark runtime-placed structures for save/load with a small component (BuildId) and respawn through the same factory (saveload-without-drift).
Author builder math in meters; convert once with * 39.37f (sbox-units-are-inches).
▸ WHY IT WORKS
Helpers encode the engine quirks (dev box size, collider policy, facing) in one place. Obstacle records are authoritative for footprints you created (no trace miss, no trigger asymmetry) and can carry semantic flags physics shapes don't have.
- Noted the z-lift rule only clears an overlay of the ground, not overlays of each other or a closed overlay crossing its own footprint.
- Removed unverified exact wire scale-axis mapping; kept verified LookAt + 50u-box scaling.