A measurement gate, five lots at once, and a street editor inside Unity
Day 2 left two questions open: whether the draw-call budget could be read at all, and whether the build-and-review loop could run several lots in parallel. The night answered both, then spent the morning on three look decisions with mock-ups. The afternoon changed direction: instead of writing every future street in Blender, the next streets get drawn inside Unity with a build-mode editor, and the first one was laid out, baked and walked by evening.

- Commits
- 46
- Tests passing
- 238
- Lots in parallel
- 5
- Editor code
- 6.2k
4:59 AMFive lots at once
One builder per lot, one orchestrator on Unity, four passes: 3.08 to 3.37.
5:30 AMThree look decisions
A cooler golden hour, cream lanterns, a willow of painted cards, each from a mock-up sheet.
6:34 PMA street editor
Rooms, walls, doors, roofs, lots, roads and exits drawn in the Scene view, baked to a scene the game loads.
1:34 AM to 2:25 AM
The measurement gate
The night run was not allowed to build anything until the draw-call question from Day 2 had an answer. It took an hour.
- The budget is the frame debugger's batch count from a fixed camera, without the shadow-map passes and the UI. The editor's raw counter had been counting every renderer inside a batch: Day 2's 489 was never the number.
- Every built location reads 59 to 144 batches of 300. The frame debugger only captures while the editor is the active application, so the reading script brings it to the front first; the frame's SetPass count stands in when no capture is possible, and matches within two.
- Static batching is off on macOS: it changed the batch count by under four and cut raw draws by 10 to 25 percent.
- The first development-build smoke test: no player errors, 18 to 24 ms a frame on the arcade against 11 to 18 on the station street, 288 to 310 MB of textures with half of it render targets and 77 MB of uncompressed avatar textures.
- A status board for the run: every builder posts its phase, pass and scores to two files under a lock; a local page polls them and flags a run that has gone quiet.
- Rules for parallel builders: one builder per lot, only the orchestrator touches Unity, Blender jobs share a two-job lock across sessions and wait while Unity is busy.
2:46 AM to 4:10 AM
Kit round: masks, wind, guardrails
Before the batch, the shared kit got the changes every later lot would inherit: data in the vertex colors, a wind shader, more tests that fail on real defects, and a sky.
- The exporter writes two masks into the vertex colors: how much a vertex sways in the wind and how much sky it sees. Kit helpers tag what they build (cloth, foliage, a rail, a pole), and an audit reports floating, detached, interpenetrating and mis-scaled pieces per file.
- A URP Lit shader with the sway added: up to 3 cm with gusts, a mesh with no mask never moves. A wind director in the game scene drives it, April petals fall, steam and smoke rise from vent markers. All 36 kit materials moved to it; whole-frame shots differed by under 0.1 percent of pixels.
- Glass became dark and thin (7 percent tint, smoothness 0.9); lit sign variants and a fluorescent strip got their own materials; garments are alpha-cut cards. One box-projected reflection probe per street, re-rendered as the hour moves, so shop glass mirrors the shops opposite.
- Four new guardrail tests: a door's approach must be clear, props may not overlap, no two meshes may share a coplanar face (54 z-fighting pairs found, 29 cleared by deleting the party walls between neighboring modules), and every scene needs a current draw-call reading, keyed to its file hash.
- Scripted walks through a dev override of the move input, since simulated keys never reached it on Day 2: the arcade reaches 12 of 14 waypoints and the walk found a blocked pavement by the north gate.
- LOD1 for the 21 street props that had none: a planar dissolve, then collapse to about 45 percent with weighted normals kept. The home's window view fell from 132,987 to 117,624 triangles.
- Window light shafts now end at the first wall or floor along the sun, and a watertight test casts rays from every room: 96 findings in the hand-built home went on a known-open list for a room-by-room pass.
- A skyline ring: kit masses rendered at their bearings onto a 4096 by 1024 texture on a 300 m ring that follows the camera, a scrolling high-cloud dome, ten cumulus that drift with the wind, tints that follow the hour. 4,208 triangles under a view root.

4:59 AM to 5:05 AM
Batch B1: five lots at once
Day 2's loop built one lot at a time. Batch B1 ran the arcade's five west lots through four passes in parallel, each with its own builder and critic pair, while a single orchestrator owned Unity.
- One Unity step per batch pass: import, re-dress, budgets, guardrails, lot shots, draw calls. Builders paint their sign cells into a shared atlas through a merge script that lets a lot redraw its own cells, and a pruning script drops stale entries from the known-open lists.
- The critics now read the exporter's audit alongside the screenshots, so an audited overlap fails the checklist even when no camera shows it.
- The batch mean went from 3.08 at pass one to 3.37 at pass four. The best lot reached 3.58; the worst, a bookshop, lost ground on a technical finding it could not clear.
- The street itself got its pass in the same window: the arcade roof is spans and posts on a bay grid with column colliders, lantern strings hang in 4 m and 6 m lengths, props moved off posts and doors, the street floor shows wear, and two willows stand at the river end.
- Wall calendars show day marks instead of numbers. A month grid whose first weekday is drawn pins the year, and two calendars had disagreed.
- The run stopped at 5:05 AM on its own rule, by 0.01 (see Challenges), after three and a half hours unattended.


5:30 AM to 7:04 AM
Three look decisions, with mock-ups
The night's Needs-Elle list had three look questions. Each got a sheet of rendered options, a choice, and a commit before breakfast.
Before
After- Lanterns: a row of red paper read as a bar street to the local reader. A recolor script edits the two lantern cells of the first sign atlas in place, red paper to cream, blue band to red, so every lantern string and both gates change at once.
- The willow: solid green strips had read as ribbons. Version 8 is a CC0 trunk with a crown of painted cards on a foliage atlas drawn by script, normals copied from a sphere so it shades as one soft volume, and authored LODs of 1,588, 128 and 30 triangles. The importer now sets per-model LOD switch heights; the willow keeps its full crown to about 70 m.
- Mock-ups beat descriptions: every option was rendered at the same three camera positions and the sheets decided in minutes.



11:51 AM to 12:00 PM
Characters: a Sims rig in Unity, a look pass, wind that parts
The characters so far were VRoid avatars, and they never matched the reference designs. The reference designs exist as characters in The Sims 4, so the question was whether one could stand on the street in Unity with the shared locomotion, a face and a voice. It can, as a prototype.
Getting a Sim into Unity
- The only exporter for that game's characters is a Windows Forms application (TS4SimRipper, GPL-3.0). It was ported to a headless .NET 8 command line on macOS: the forms and controls replaced by a thin shim layer, the DXT texture decoder rebuilt as a native library, System.Drawing on Unix for the compositing. The save file, the character and the mods folder are arguments; it writes Collada plus the composited diffuse and normal maps. Loading the game's packages takes about two and a half minutes.
- The mods folder is a filtered copy: adult packs add bones to the rig, so the clean folder is symlinks minus those.
- In Unity an asset postprocessor maps the exporter's bone names onto the humanoid avatar, 24 body bones and 30 finger joints. Humanoid retargeting expects a T-pose and the export's arms hang at an angle, so the skeleton is built from the model's own bind pose on a scratch copy with each arm chain rotated out sideways. The jaw stays unmapped: the shared clips would hold the mouth open. The result runs on the same locomotion controller as every other character.
- One atlas carries skin, clothes and the hair cards, so the material is alpha-clipped and double-sided.
- There are no blend shapes. The face is driven by small bones, so each expression is a set of bone offsets from the rest pose in millimeters, authored for one side and mirrored; blinking is a lid rotation (inverted on that rig), and while a voice clip plays the jaw follows its loudness.
- A voice bank from recorded lines: an index file per character maps audio files to line keys and barks, a tag on a dialogue line plays its clip, and characters with barks greet the player with a cooldown.
- Prototype only. The base meshes and skeleton belong to the game's publisher and the custom content to its creators, so every part is replaced or licensed before anything ships, and that is why there is no picture of it here.
A look pass on characters only
- A render feature ports two community ReShade presets to URP and applies them to characters alone. Characters carry a rendering-layer bit; a mask pass records their pixels and unlit color, and a pass after post-processing applies the look inside the mask: ink outlines for one, sharpening, clarity and a glow fed by character pixels for the other, and for both a relight that keeps the character's own colors but evens out the light so faces read at night.
- The presets' color grades are baked into strip LUTs by a script and off by default. Each character picks a look; a pause-menu setting overrides it for everyone.
Wind that parts
- The player and every NPC carry a pusher. The wind director sends the four bodies nearest the camera to the wind shader as capsules, and swaying vertices are pushed out to the capsule surface with a little drag and lift, so foliage and hanging cloth part as someone walks through.
12:30 PM to 6:34 PM
A street editor inside Unity
Two streets exist as Blender layouts and hand-written dressers. The town has thirty more. The afternoon built the tool that draws the rest: a build-mode editor in the Scene view, modeled on how life-sim games do it, that bakes to the same scene layout, markers and registries the hand-built streets use, so every existing test applies unchanged.


What it feels like
- It is a Scene-view tool, not a window: a grid on the level you are building, the thing under the cursor highlighted, a green or red ghost with the reason next to it, a legend of keys along the bottom, and one undo entry per gesture.
- Two scales. Street: the camera pitched 55 degrees over the whole street, lots sliding along their road, roads clicked out as corners, exits dragged across a road mouth, camera zones as boxes. Lot: pitched 45 over one lot, rooms, walls, floors, doors and windows, a roof, with levels stacked and the floors above hidden. Enter drills into a lot, Esc backs out, T flips to a flat plan.
- Letter keys while the tool is active (W wall, R room, F floor, D door, N road, L lot, X exit, M place, K hammer) through a shortcut context, with the number row as a fallback.
- Walls chain: release, and the next press within half a cell continues from the end corner; the chain collapses into one undo entry. Closing a loop flashes the new room and its area.
- A catalog overlay for placing: the kit's facades, backdrops and props by tab with thumbnails and search, plus NPC spots, activity spots and lights. A facade in hand snaps to the hovered lot's front centre facing its road and warns in orange when it is wider than the lot.
How it is built
- The logic is plain C# with no Unity types: a 0.5 m grid in 8 by 8 chunks, walls as half-meter pieces on a lattice, rooms found by flood fill and updated incrementally, every action an operation with prepare, apply and revert. 62 tests run on it outside Unity in under a tenth of a second.
- One component on an editor-only object holds the whole street (grid, walls, openings, roofs, roads, lots, exits, zones), so a single undo record covers any gesture, and a version number tells the cached world when to rebuild.
- Placed kit pieces are prefab instances under that object, not records: Unity's own Move tool and undo handle them, and the bake copies them out.
- The street comes from the city plan: lot ids, widths, types and exits are read, never typed. Creating a street seeds a road from edge to edge, every lot flush in plan order, and each exit at the end its name points to; a readiness list says what is left before a bake.
- A plan rowThe street's entry in the city plan: its lots with their widths and types, its exits and what they link to. The editor reads it and never invents a lot.Input
- A seeded streetOne click makes the scene: a road from edge to edge, every lot laid flush in plan order at a default depth, each exit waiting at the end its name points to.Create
- Street toolsLots slide along their road and resize from the back edge; roads are clicked out as corners with a width per type; exits are lines across a road mouth; camera zones are boxes.Street scale
- Lot toolsRooms as rectangles, walls as chains, floors by drag or room fill, doors and windows that slide along a wall, a roof per lot, a hammer. Levels stack with the floor above hidden.Lot scale
- PlaceA catalog of the kit's facades, backdrops and props with thumbnails and search. A facade snaps to a lot's front edge facing its road; a marker becomes a spot or a lamp at bake.Catalog
- BakeMesh assets per lot and road, lot markers, exits with arrival spawns, entrances, one interior scene per front door, kit copies with their markers turned into gameplay, the neighbor's scenery past each exit, the registries.Output
- TestsThe same guardrails as the hand-built streets: lot markers on their buildings, every link walkable both ways, watertight rooms, no z-fighting, budgets. Then Play from here.Gate


The bake
- Each lot becomes one mesh asset at its front-centre pivot, with walls as merged runs, openings cut with sills and lintels, slabs on each level and the roof; door panels and window glass are a second mesh with colliders, so rooms close for the watertight test.
- Exits become walk-through triggers across the road mouth with an arrival spawn facing in, named the way the hand-built streets name them, so the connection test pairs them with the neighbor's.
- A door marked as an entrance writes the street's door and spawn outside, and bakes an interior scene: the same mesh at the same pivot, a door back out, the arrival spawn just inside, one camera zone per closed room. A kit facade's own door marker wins over a drawn one.
- Past each exit, the neighbor's scenery is copied from its scene: everything within 30 m of its matching exit on its own side, moved so its exit line lands on ours facing the other way, colliders stripped, drawn at the lowest detail level.
- The registries update themselves: the world map, the lot registry the marker test reads, the build settings by folder scan, and the plan's Unbuilt flag. The bake never runs the tests; it ends by telling you to.
- Play from here: the Town window sets a key, opens the game scene and enters play mode; the game reads the key once and starts a new game on that street, skipping the title.
- Fourteen design decisions came up and were taken without a meeting, each recorded with its reason in the design document: interiors as separate scenes, straight roads first, the plan file never written automatically, stand-in boxes for lots without a facade, and so on.


Riverside at the end of the day: eight lots, two with kit facades, one drawn house with an interior scene, a bench, a lamp, an NPC spot, two exits and the arcade past the north one. 237 of 238 tests pass; the last is the draw-call reading, which needs play mode.
Challenges
What went wrong, how it was found, and what changed so it stays fixed.
Rooms that leaked light through solid walls
The watertight test casts rays from every room toward the sun and wants a back face behind the first wall it hits. The generated walls were 0.5 m boxes, so a ray entering one found the next box's end cap first and called the wall a single surface. Merging boxes into runs helped, then every other hidden face turned up in turn: slab edges inside walls, jambs inside door panels, a wall's inner face crossing its neighbor's thickness at a corner.
Fix: The mesh builder now produces no face inside another solid: walls are straight runs, a wall that butts into another stops at that wall's face with no cap and the receiving face is cut around it, slabs merge into walls, panels run into the jambs with no end faces.
Lesson: A test that reads geometry the way light does is worth more than a visual check. Every hidden face it found was real.
The test's 30 cm rule was wrong, not the walls
After the rebuild, hundreds of hits remained. A sun ray grazing a 15 cm wall at a shallow angle travels a meter inside it; the rule gave up after 30 cm and called that thin.
Fix: The rule looks two meters for the back face. Five grazing hits on the hand-built home that had been listed as known open stopped reproducing and left the list.
Lesson: When a proxy rule fails on correct input, fix the rule and check what else it had been excusing.
A cache that outlived the mesh
Re-baking a street changes its mesh assets in place. The test helper caches mesh data by object, and the object survives a reimport, so the test kept judging last bake's geometry until something reloaded the domain.
Fix: The cache is cleared per scene. A diagnostic that cast the test's own rays against the asset on disk is what showed the two results disagreeing.
A bridge that stops waiting after five seconds
The editor bridge used to drive Unity from scripts returns after five seconds on the main thread. A bake takes longer, and a delayed call never fired while the editor was in the background.
Fix: Long jobs run synchronously and write their report to a file the script polls. The job keeps running after the bridge gives up.
The stop rule tripped by 0.01
Batch B1's mean came in at 3.37 against the previous batch's 3.38, and the run stopped as its rule says. But the critics had changed in between: they now read the exporter's audit, and any audited overlap fails the checklist, so the two batches were not comparable.
Fix: A batch is compared only with batches scored by the same critic setup; B1 is the new baseline.
Lesson: A rule that compares scores has to pin the scorer too.
Two facades wider than their lots
The teahouse module is 9.4 m on an 8 m lot and the shrine 8.1 m on its 8 m lot, so placed flush they shared a wall and the z-fighting test caught it. The lot behind them could not move: an alley to the next street sits where it would go.
Fix: The first lot moved a meter west instead. The Place tool shows “Module is 9.4 m, lot is 8 m” in orange while a facade is in hand, and allows it.
Budgets
Measured in the Unity editor at the end of the day. The arcade grew with its bays, lanterns and willows and still sits under its budget; the riverside is small because most of its lots are stand-ins; the home is still over, and its window views are still the next performance job.
Draw calls, read for the first time: 59 to 144 batches of 300 on every built location, static batching off. Frame time in a development build: 16 to 23 ms on the arcade, 11 to 18 on the station street; the lights left on by day cost about 2 ms.
What’s next
- The riverside's draw-call reading, then wall and floor paint, an upper-floor support rule and push-pull handles on room walls in the editor.
- Importing the two Blender-laid streets into the editor's records, with a bake that reproduces today's markers within a centimeter before the hand-written dressers retire.
- Batch B2 of the arcade with the shared fixes B1's critics raised: night pools lighting the awnings from below, gray plates at the post feet, helper overlaps at the piers.
End of Day 3.