Second Chance DevlogThe Gazette

Every planned road was refused for a 200% gradient — the probe was measuring a slab of land nobody could delete

roadsterraintoolingproceduralunreal

The game moved onto a new open-world map — an 8.1 km square of landscape, streamed as 256 tiles, with a bare unpainted heightmap on it and nothing built. The estate in the old small level had been made by hand: scaled cubes for the carriageway, flat planes for the pavement, a separate little box for every dashed line. That is fine for one street. It does not survive a town.

So the job was a road painter. Draw a route as a spline; conform it, which drapes and smooths it onto the terrain; carve a formation into the heightmap so the road sits in the ground instead of on it; construct the carriageway from tiled profile meshes along the spline. Four verbs. Junction detection, levelling, junction caps and give-way markings all sit on top of those four.

Two decisions made it more than a convenience. The first is that the road surface is computed, not painted: the profile mesh's texture coordinates are signed metres from the centreline across, and metres travelled along, so the material can generate a dash pattern from the real mark and gap lengths in the British marking schedules rather than from a texture somebody drew at a guess. The second is a single module of statutory constants — desirable and absolute gradients, crossfall, the superelevation cap, the mark/gap pairs for each line type. Six road types fall out of that one table, from a 7.3 m A-road down to a 3 m dirt track, and the gradient gates come from it too: 6% desirable and 8% relaxation on a single carriageway, with side streets allowed 8% desirable and 25% absolute as a project choice.

That gate is the thing this entry is about, because for a week it refused everything.

The symptom

In the words you would type into a search box:

  • Every route the tool surveys is rejected for gradient, on ground that looks like a

gentle field.

  • The reported slopes are absurd and alternating — 131%, then 213%, then back — a

sawtooth that no real hillside makes.

  • There is a flat slab of land floating in the sky that cannot be deleted or sculpted.

Clicking it does nothing; the sculpt tools do nothing; it has no entry you can act on.

  • Where a road did build, it draped to the wrong height, and the carve then **pushed

real terrain upwards into a plinth** around it.

For a day I had the wrong culprit. There was a known invisible surface at height zero blocking visibility traces across the low parts of the map, and the obvious suspect was a water plane left behind when a river was deleted. That guess was wrong, and it cost time, because it is a satisfying story and it explained the plinths.

What it actually was

Sixteen orphaned landscape streaming tiles.

The map's template had left a 504 m starter pad near the origin — a recoloured flat zone at height zero. Its parent landscape actor no longer existed. The tiles did. A streaming tile without a parent is an object the editor will not sculpt and will not let you delete: every route the interface offers to act on a landscape goes through the parent. That is precisely why it could not be removed by hand, and why it read as a mysterious floating slab rather than as a mistake.

The real sculpted terrain sat about 41 m below it.

Now the mechanism. The ground probe took the first thing a downward trace hit. Orphaned collision is unreliable — some traces caught the pad, some passed straight through to the hillside underneath. So consecutive samples along a route alternated between height zero and real ground 41 m down, and a gradient computed between adjacent samples is a division by the sample spacing. Sawtooth in, absurd percentages out. The gate did its job perfectly on data that was nonsense.

And where the probe consistently believed the pad, the failure was worse and quieter: the road conformed to a false ground, and the carve — which writes absolute heights into the heightmap along the spline — then dutifully raised the real terrain to meet it. That is the plinth. Nothing errored. The tool reported success both times.

The fix, and the guard

Two changes, in order.

Delete the orphans. All sixteen, through a scripted scene removal, because the editor UI genuinely has no path to them. A Save All is mandatory afterwards: on this kind of map, actors live in their own external files and an unsaved deletion resurrects on the next load. The developer confirmed visually that the sky slab was gone.

Stop trusting the first hit. The probe now walks the trace: it iterates, steps past every non-landscape blocker it meets, and accepts only a hit whose owner is a landscape. Anything else — a pad, a prop, a road it has already built, a junction cap — is stepped over rather than measured. That last part matters more than it sounds, because as soon as the tool starts building roads, the roads become obstacles to its own surveying.

The result was the point of the whole exercise: the same route that had been reporting 131–213% now read a coherent 40% falling to 28% — a real bowl in the terrain, and a legitimate rejection. The gate had been right all along and had never once been given a true number.

Three smaller things came out of the same session and are worth keeping:

  • Deleted geometry keeps answering editor traces. After removing the tiles, traces in the

editor world still hit a blocker at height zero until garbage collection or a restart. Play mode builds a fresh physics scene, so it is unaffected — but in the editor this produces the single most misleading debugging state there is. Bit-identical readings across a revert and a rebuild are a ghost, not a measurement. If two runs that should differ agree to the centimetre, restart before you theorise.

  • Landscape edits have no undo. Verified the hard way. A bad probe therefore does not

produce a bad preview, it produces permanently wrong terrain. The roads and the roundabout built during the phantom era were corrupted beyond repair; they were reverted and deleted, and even the revert flattened to the phantom heights, which was accepted only because it was a demo area.

  • The obvious guard — refuse to carve when any probe sample hit a non-landscape actor

was agreed as a change, along with a dry-run preview and a confirmation dialog before a destructive carve. Those are agreed, not built. Until they are, one menu click still writes the heightmap with nothing standing between the intention and the ground.

The first junction, end to end

With the probe honest, the pipeline ran on a route the developer drew themselves: a side street tee-ing into another road at their click, landing 16 cm off the centreline.

Detection projects each road's ends onto the other road's polyline and calls it a touch inside the junction platform radius, with end-near-end pairs skipped when the two are nearly colinear — otherwise every ordinary butt join registers as a junction. Levelling pulled both arms to a shared height, producing a flat plateau across a 12% hillside by shifting the major arm 1.56 m. Then carve, then a flat cap plate over the intersection with the carriageway material blanked on the segments underneath it, then give-way markings on the minor arm: six double dashes and one triangle, placed to the driver's left.

Two lessons, both of which will recur on any tool that grades terrain:

Levelling a junction steepens the road running through it. The platform has to blend back into natural ground, and that blend added roughly 8% to the through road — enough that the next carve tripped the 25% absolute gate. The fix was to let the carve take an explicit maximum gradient rather than always applying the road type's absolute, matching the contract the conform step already had. The general shape of it: the fix for one defect trips the gate on the next stage, and a pipeline of gates needs to be able to say "yes, I know, I did that deliberately".

A road exactly coplanar with the ground is buried, not finished. The first planner-built road came out under the grass. Three causes, all real: the carve was cutting only the width of the carriageway, so the kerbs and footways hung out over the blend ramp where natural ground climbs back up through them; the formation was 15 cm deep, which crossfall and heightmap interpolation can eat entirely on a steep grade; and the profile meshes were open shells with no sides, so any sliver of ground above their edge showed through. Widening the carve to the full profile footprint, deepening the formation to 20 cm, and rebuilding all six profiles with 0.6 m vertical skirts fixed it, verified at +20.2 cm clearance at two probe points.

The trap inside that fix is the best thing I learned all day. The carve needs the road lifted by the formation depth while the rasteriser runs, and the first implementation did that by nudging the actor up and back down around the call. Moving the actor triggers a construction-script rerun, which raced the rasteriser — nondeterministically. One build came out coplanar and buried; the next came out floating, with only the restore applied. Same code, different result. The fix was to offset the spline point data instead, in world space, with a single update and an absolute restore in a finally block: nothing moves, so nothing reruns, so there is nothing to race.

What was still wrong at the end of the day

  • Earliest failed builds had left zombie roads — degenerate half-metre actors buried 29 m

and 65 m underground — which poisoned end-snapping, junction detection and the automatic numbering. Deleted, and guarded: a cached road end more than 10 m above or below the aim point is ignored.

  • A plate-built junction box was tried and shelved the same night. At a 78° skew,

axis-aligned rectangles leave notches and seams against the angled road, and it broke pavement continuity — which is a hard requirement here, because pavements must run continuously along all three sides of a T for NPCs to walk them. The plain overlapping cap satisfies that; the box did not. Proper mitred corner geometry is still owed.

  • Camber was capped at 2.5% because the carve banks the terrain but the road segments were

believed not to roll, so a steeper camber drowned the uphill footway in scalloped grass. I should flag that this belief was later shown to be wrong — the spline segments do expose roll, the Blueprint simply never set it — so the cap was resting on a false premise for weeks.

  • Re-conforming a road drapes it onto the ground the previous carve produced, so every rebuild

sinks it one formation depth deeper. A known ratchet, not fixed.

What to take from it

  • A ground probe that takes the first trace hit will believe anything. Filter by what the

hit is, not by what it is nearest. Once a tool starts building, its own output becomes the next thing its probes will happily measure.

  • Absurd, alternating readings are an identity problem, not a precision problem. A number

that flips between two regimes is sampling two surfaces. Do not tune the tolerance.

  • When an editor refuses to let you delete or edit something, ask what owns it. Orphaned

children of a deleted parent are invisible to every interface routed through the parent, and they keep behaving like real geometry.

  • Deleted objects go on answering traces until the world is rebuilt. Two runs agreeing to

the centimetre when they should differ is the tell. Restart before you form a theory.

  • **Where an operation has no undo, a wrong measurement is permanent damage, not a bad

preview.** That is an argument for a dry run and a refusal gate long before it is an argument for better numbers.

  • In a chain of gated stages, each fix moves load onto the next gate. Levelling steepened

the grade; the grade gate then rejected the levelled junction. Give the later stages a way to be told the earlier one meant it.

  • Zero clearance is not a pass. A road sitting exactly on the ground is the burial

signature. Measure the clearance you expect and check the sign of it, not just that the call returned success.

← All devlog entries

Watch it get built. All of this goes up on YouTube as it happens — broken animations, buildings hovering a foot off the ground, the lot.

Subscribe on YouTube