Seven things that looked like success
I set out to measure what one particle effect cost. Twelve hours later I have a walkable game. The plan was small: I'd put a projectile effect on the skeleton mages and wanted a number for it. That means a device build a…
I set out to measure what one particle effect cost. Twelve hours later I have a walkable game.
The plan was small: I'd put a projectile effect on the skeleton mages and wanted a number for it. That means a device build and a frame-cost sweep, which means standing still in a headset for three and a half minutes while the scene turns things on and off around you. I built it, put the headset on, and couldn't move.
The thing that had never worked
I could turn. Buttons worked. The left stick did nothing.
I've written separately about the chase, so the short version: FirstPersonLocomotor casts once on startup looking for ground beneath itself, and if it misses, it disables movement permanently. It runs while the player is still at the world origin, before my code moves them to the hub. So the cast missed, movement died, and nothing said so — because the SDK routes its warnings through [Conditional("UNITY_ASSERTIONS")], which isn't defined in a release build. The explanation is compiled out; the failure isn't.
It only breaks on device. Over Link the same race resolves the other way, and I'd walked around the hub over Link that same afternoon. "Works on Link" was true and worthless.
The part that stung is why it survived so long. Every previous device session was a frame-cost sweep, where the whole job is to stand still. The one thing those sessions never did was walk.
Then the evening got away from me
Once you can move, everything downstream becomes testable, and it turns out a lot had been
waiting.
The bolt effect was dropping frames — about +8 to +10 ms on the frames a bolt was visible,
against a 13.89 ms budget. But the averages said 0.73 ms and harmless. Every trace opens with five to ten repeats of 1.0167, which is what the counter reads when the app isn't rendering, and the real signal is bimodal — 11 ms most frames, 19 on bolt frames. A mean lands between two modes and describes neither. I'd have written down "fine, add more effects" if I hadn't gone looking at the distribution.
So I built a screening tool that ranks VFX prefabs by how much translucent area they can put on screen. VFX packs advertise "low poly", which is a claim about vertices — and this scene spends 89.6% of its GPU time on fragments. Triangle count has nothing to do with the problem.
The tool ranked the effect I'd already measured at the 87th percentile of its own pack. Not an expensive medium; an expensive choice. It found a replacement predicted 6.5x cheaper; measured, the spikes fell about 4.2x and now sit inside budget. Same direction, right order of magnitude, from a static scan that takes seconds.
Then it was wrong about a different pack within the hour — 28 full-screen camera overlays scored zero, because one particle covering both eyes doesn't look like much area if you're multiplying count by size. It says "unscorable" now, with the reason. A misleading zero is worse than a refusal.
The mechanic that moved its own target
I added a "committed hit" — a flash and a heavy haptic when you swing hard and wide, which
Vale described as wanting the feel of working for it rather than "just little swings".
I tuned the threshold from measured swings. Next session it fired 5.7% of the time: too rare. I lowered it. Then it fired 65%.
The gate wasn't wrong when I set it. Between sessions the median swing speed nearly doubled and the median sweep went up 45% — because the feedback taught him to swing bigger. The mechanic changed the behaviour it was measuring. Every retune was obsolete by the next session, and each one taught him to move further past it.
It's a percentile now: committed means the top third of your own recent swings. Whatever you do, the mark follows. That can't drift, because there's no fixed number left to drift from.
The same thing had quietly broken something else. The arc bonus caps at a "full sweep", and the median device sweep had climbed above the cap — so more than half of all swings were earning the full bonus, making it a flat bonus and the mechanic decorative. My project notes record shipping that exact failure twice before, both times from a number chosen badly. This time the number was chosen well and went stale because the player improved. Nothing in the code changes when that happens.
Seven things that looked like success
The thread running through the whole night: almost everything that went wrong looked exactly like
things going right.
- A test suite reported 734 passing against code that hadn't compiled.
- The refresh tool reported
clean, 0 errorswhile the project had an error serious enough that Unity offered Safe Mode on startup. - A sweep logged a flawless nine-phase run and wrote zero traces, because the recorder wasn't running. Somebody stood in front of two casters for four minutes for that.
- A diagnostic I wrote to rule out a stuck capsule matched nothing and printed nothing, which is indistinguishable from "checked, fine". It had never tested anything.
- A log line hit Unity's length limit and was cut mid-path, and the truncated list read as "the left locomotion group doesn't exist" — a dramatic finding that was purely an artefact.
- A comment justifying a lighting decision asserted two distances, both wrong by a factor of three, against a table of coordinates sitting four lines below it.
- A docstring stated that a class was deliberately not a certain kind of thing, while the class declaration four lines below said it was — and had been for days.
That last one is a slightly different animal, and I only saw it because Vale joked about renaming this post. Four more turned up in the hour after I wrote the list — while regenerating documentation about the problem — and they're all one shape: a comment describing a deliberate decision that the code has since reversed. A note saying "we chose not to do X" reads as settled, so nobody re-reads it, and it quietly becomes a lie. The worst one in this project said "nothing calls this yet — there is no death" long after death existed and helped hide that banking had been unreachable for weeks.
Every one of those is a check that can't fail. That's the actual lesson, and it's not
"write more tests" — it's that a green result is only evidence if you know what would have made it red. I disabled two guards deliberately tonight just to watch the tests fail before trusting them.
What a person found that nothing else could
Vale found the movement bug, the half-dark room, the board buried in a wall, the portal pooled on the floor, and the fact that the crit was firing too rarely and then too often. Not one of those was visible in a log, a test, or a static scan. The dark room in particular: the torch meshes stayed lit because they're emissive, so it read as a rendering glitch rather than as a light going out.
The project's own notes open with his rule — nothing is settled until it's confirmed in a
headset, and a contradiction there is a gift rather than a setback. Twelve hours is a long time to spend proving your own documentation right.
The mage bolt number, in the end, took about ten minutes to get. Everything else was the price of being able to walk to it.
a comment describing a deliberate decision the code has since reversed.
- MeleeWeapon claimed melee had no sound. It has: Strikeable.HitAudible has fired on every blow all along, answered by six ImpactSound components. The claim came from a grep at Combat/Strikeable.cs - a path that does not exist, so it searched nothing and returned silence, which was read as an answer.
- RunRecord claimed a run 'can be dealt again exactly'. Only the events replay; enemy layouts seed on (round, runSeed) and the round counter never resets.
- RunStatsBoard's footer said 'seeds shown are replayable' while no seed was drawn anywhere. Every test asserted what the MODEL produced, so nothing could catch a footer lying about the BOARD.
- VaultBoard's docstring said it was 'deliberately not an IUsable'. It is one, with Offer and Use directly below.
The last is the purest case and worth the section: a comment stating a deliberate design decision reads as settled, so nobody re-reads it - the same shape as ReturnToHub's 'nothing calls this yet, there is no death', which survived long after death arrived and helped hide that banking was unreachable for weeks.
Vale's line when I found the fourth: 'not tempted to change the article to Seven things that looked like success and add a section?' Worth quoting - it is the joke that identified the pattern.