Tiering a living world: simulate what you’re looking at, abstract the rest

← All field notes

A living world has more creatures and plants than modest hardware can fully simulate every frame. The honest version of the problem looked like this: every creature was still running the full per-individual loop, the frame rate had drifted to the edge of its budget, and the cheap “distant” path we’d scaffolded earlier was sitting there as a no-op.

That marginal frame budget was the evidence. The tier we’d always planned for had stopped being a nice-to-have and become load-bearing. This is how we made it real — and how we kept it from quietly breaking the one thing the whole game depends on.

Two tiers, sorted by where you’re looking

The design always called for this. The world is meant to scale far past what a processor can simulate individually, so only the creatures near where you’re looking get the full treatment, and the rest are abstracted. The mechanism is a simple rule run every simulation step: each creature is measured against a focus point that follows the camera, and sorted into one of two buckets.

Creatures inside a camera-relevant range are active. They run the full behaviour loop: they get hungry, choose the nearest grazeable plant, step toward it, arrive, and eat. Creatures beyond that range are distant. They skip all of the expensive work — no target-seeking, no movement, no scanning the world for food, no eating — and instead get a coarse housekeeping pass that runs roughly twenty times less often. The active loop ticks about twenty times a second; the distant update, about once a second.

That coarse pass does exactly one useful thing: it keeps an off-screen creature’s hunger from drifting out of bounds. When a distant creature’s hunger climbs high enough, the world simply assumes it found food off-screen and resets its last-meal marker — it found food eventually without us simulating the search. Crucially, that housekeeping touches only the creature’s own state; it never edits the plants. The performance headroom comes entirely from this: we stopped paying to fully simulate the half of the world you aren’t watching. You can’t simulate every creature fully. You simulate the ones you’re looking at fully, and the rest cheaply but faithfully.

The hard part wasn’t speed — it was reproducibility

The whole world is designed to be perfectly deterministic: the same seed always grows the same world, the same way, for everyone who shares it. But the active set now changes with the camera — which the player controls, and which the world’s seed knows nothing about. Naively, that’s a contradiction. If which creatures are simulated depends on where you happen to be looking, how can two people sharing a seed see the same world unfold?

We resolved it by separating two things that look the same but aren’t. Which creatures are active right now is a performance concern, and it is allowed to depend on the camera. How any individual creature’s life actually unfolds is a simulation-determining concern, and it must not depend on the camera at all.

The active set changes with the camera, but the world’s outcome must not.

Two design choices make the cheap path safe. First, we derive a creature’s hunger forward from the last time it ate, rather than ticking it along second by second. A creature that’s been distant for a while isn’t carrying a running tally that could drift — its hunger is a clean function of how long it’s been since its last meal. Second, we freeze the only piece of state the active loop changes: position. A distant creature doesn’t move, so its stored position is simply correct. A frozen position is its correct value.

Put together, these mean a creature crossing back into the active set is reconstructed correctly — without the cheap path ever having to track it tick by tick. There’s no seam. And the world’s outcome is independent of where you happened to be looking. For our reproducibility tests we pin the focus point to a fixed location, so the tests still exercise the tiering deterministically; the running game feeds it the live camera. Tier membership is purely transient runtime state, so none of it is written into the save file.

Proving it — and a test that almost lied

An optimization you can’t measure is a guess, so we built two things to watch it. The first is a live witness: it confirms that fewer creatures are active than total, reports the active count, the distant count, and the frame rate, and asserts that the frame-rate floor still holds. The second is a dedicated measurement tool that compares the cost of running everything active against the tiered cost, and reports how much work the split recovers.

There was a real trap here, and it’s worth naming. Once tiering was switched on, a naive witness would have kept passing while silently no longer testing anything — the split was now always present, so a test that merely checked “the game runs” would go green forever without ever exercising the tiering. So we deliberately made the witness split-aware: it checks the active count against the total, which means it cannot quietly stop verifying the very thing it exists to verify.

The numbers came out comfortably. Measured against simulating everyone, the tiered split recovers somewhere in the range of roughly 72 to 78 percent of the per-active-tick work — enough that we never had to fall back on detuning anything else. The distant tier earns its keep. The range over which creatures stay fully simulated is a tunable; we landed it so the visible region runs full simulation while the far half tiers cheap, raising it from an initial setting once we’d watched it in motion.

Why “gently bounded” and not “frozen”

The cheapest possible distant tier would freeze off-screen hunger entirely. We chose not to. If hunger simply stops while a creature is off-screen, then a creature you drift away from and come back to reads as exactly as hungry as you left it — but a whole flock that’s been off-screen for a long while snaps back into view all at once, and the systems downstream of hunger get nonsense to work with. Keeping each distant creature’s hunger gently bounded means creatures that come back don’t all read as starving and stampede toward food at once, and the systems that track death and decay get sensible inputs. It costs almost nothing and it keeps the world believable in the corners you aren’t watching.

A scattered herd of pale voxel grazing animals spread calmly across a golden-hour wildflower meadow, each at its own patch of grass, none crowding or rushing, with a river and rolling hills beyond.Concept art · pre‑alpha
A flock that drifts back into view grazing calmly, not stampeding — the corner you weren’t watching kept making sense.

This is the target the tier was tuned against: a few hundred creatures fully simulated at once, on the order of two to five hundred. Our founding population is still smaller than that — under two hundred — so the range stays forward-looking for now, sized for the world it’ll grow into once reproduction takes over. The whole point of the headroom is to let the world keep getting richer without the frame budget biting.


The same discipline, one tier down

An earlier performance pass on the plant world set the discipline we carried into all of this. The world had grown rich enough — once large canopy trees were in the mix — that several scenes were skirting the frame-rate floor. Rather than guess, we profiled first. And the profile contradicted our assumption: the real cost wasn’t redrawing the trees, it was the plant-ecology update.

Two broad-crowned voxel canopy trees rising over a lush flowered meadow at golden hour, with a few grazing animals resting in the dappled shade beneath them.Concept art · pre‑alpha
The scene that first crowded the budget — big canopy trees over a thick meadow, rich enough to push the world to its edge.

Looking closer, the true culprit was a per-slice rebuild of a species count that was being recomputed on the order of hundreds of thousands of times a tick, when it only needed to be computed once at the start of each pass. We cached it. Because that count provably cannot change in the middle of a pass, the optimization was byte-for-byte identical to the old behaviour — same world, same outcome, just faster. The plant-ecology update dropped by about a third, every marginal scene cleared the floor, and a flaky frame-rate dip that had nagged us during testing resolved cleanly.

Profile first. The real hotspot is almost never the one you assumed.

Both chapters close on the same principle, and it’s the one worth carrying away. Optimize only in ways that are safe by construction — so the world provably can’t change underneath you. Prove the world didn’t change by checking it still reproduces identically. And never let a passing test fool you into thinking it’s still doing its job. When the failure mode is “the same seed quietly grows a different world,” an optimization you can’t prove harmless isn’t an optimization. It’s a bet.

Keep reading

Concept art · pre‑alpha