Back to Journal

Procedural Generation: Building Worlds Out of Rules

A procedural world is not stored but described: a seed, a handful of deterministic rules and a careful order of operations can rebuild the same forest, river and ruin every time, and that discipline is the whole craft.

A developer feels something close to vertigo on first understanding that a world need not be built at all, only described. A mountain range, a coastline, a cellar full of rats and old barrels: none of it has to be modelled by hand and saved to disk if one can write down, precisely enough, the rules by which such things come to be. The game then becomes a kind of interpreter, reading those rules each time it starts and raising the same hills from the same nothing, faithfully, like a liturgy recited from memory.

Procedural generation is the name for this practice, and it is older and humbler than its reputation. It was born less from ambition than from scarcity: early machines had too little memory to store large maps, so designers stored the recipe instead of the meal. The habit survived long after memory became cheap, because it offers something storage never could, which is variety without authorship of every detail, and a world that can surprise even the person who wrote it.

What follows is an account of the machinery underneath: how a single number can stand in for an entire continent, which families of techniques produce which kinds of shape, why large worlds are generated in pieces, and where the generated must yield to the handmade. None of it is magic, though some of it feels uncomfortably close. All of it rests on one stubborn requirement, that the same question asked twice must receive the same answer.

The seed and the promise of determinism

Computers do not produce randomness so much as convincing imitations of it. A pseudorandom number generator is a small deterministic machine: give it a starting value, the seed, and it will emit a long sequence of numbers that look patternless but are entirely fixed by that starting value. In C# one writes new System.Random(12345) and receives the same stream on every run; in Unity, Random.InitState(12345) does the same for the global UnityEngine.Random. Everything procedural begins here, with the deliberate abandonment of true chance.

This determinism, far from being a limitation to tolerate, is the property that makes generated worlds useful. Because a seed fully determines its output, a world of many square kilometres can be shared as a single integer, reproduced on another player's machine, rebuilt after a crash, or regenerated by a tester who wants to see precisely the bug someone else reported. The world is never saved in the ordinary sense but recomputed, and the recomputation is trustworthy only if nothing in the process depends on anything but the seed.

That last condition is where most procedural bugs live, quietly, like damp behind plaster. A generator that iterates over a Dictionary whose ordering is unspecified, that reads the frame time, that shares one global random stream between terrain and enemy spawning, or that depends on the order in which coroutines happen to finish, will produce worlds that drift apart without warning. The discipline is to give each subsystem its own generator, derived from the master seed, and to treat every hidden source of variation as a defect.

A common refinement is to stop thinking of the random stream as a sequence at all and to think of it as a function. Instead of drawing the next number, the generator hashes its inputs: the world seed, a coordinate, perhaps a salt naming the purpose, such as trees or ore. The result is the same value for the same tile no matter when or in what order it is asked for. This shift, from stream to hash, is what later allows a world to be generated piecemeal without the pieces disagreeing at their borders.

Noise, rules and the vocabulary of shape

Raw random numbers are almost useless for terrain of any believable kind, because nature is correlated: a hilltop is surrounded by slightly lower ground, not by a pit and a spire. Coherent noise functions, of which Perlin noise is the most famous, solve this by producing values that vary smoothly across space. Sampled across a grid and read as height, a noise field gives rolling terrain; layered at several scales, it gives ridges upon hills upon continents. Most terrain generators are, at heart, careful arrangements of noise.

Noise describes texture well but structure poorly, and for structure developers turn to explicit rules. Cellular automata are the classic example: fill a grid with random walls, then repeatedly apply a rule such as a cell becomes wall if five or more of its eight neighbours are walls. After four or five passes the static resolves into organic caverns with smooth, cave-like edges. The rule is tiny and local, yet the shape it produces has a global character that no one drew.

Agents are another family, simpler to picture than to tune. A drunkard's walk carves corridors by moving a digger randomly through solid rock; a river agent follows the steepest descent across a heightmap until it reaches the sea or a basin; a road builder runs a pathfinding search between settlements with costs that penalise steep slopes and water. Each produces features with history in them, a sense that something travelled from here to there, which is precisely what noise alone cannot give.

Grammars and constraint solvers

When the thing being generated has internal logic, a building with rooms or a quest with steps, grammars are often the right tool. An l-system, introduced by the biologist Aristid Lindenmayer in 1968 to model plant growth, begins with an axiom and repeatedly rewrites each symbol according to production rules. A rule as plain as replacing a branch with a branch that forks into two smaller branches, applied a few times and drawn with a turtle, yields startlingly convincing ferns and trees. Shape grammars extend the same idea to facades and floor plans.

Grammars excel because they encode hierarchy. A castle expands into a keep, walls and a gate; the keep expands into floors; each floor into rooms; each room into furniture appropriate to its purpose. Constraints can ride along at every level, so that a kitchen never appears on the top floor beside the bedchambers, and a dungeon grammar can guarantee that a locked door is always preceded somewhere by its key. The generated result is varied in detail but never incoherent in plan.

Wave function collapse approaches structure from the opposite direction. Rather than growing a design outward, it begins with every cell of a grid able to hold any tile, then repeatedly picks the cell with the fewest remaining possibilities, commits it to one, and propagates the consequences to its neighbours through adjacency rules learned from an example image or written by hand. The grid settles, cell by cell, into a pattern that respects every local rule. When propagation leaves some cell with no options at all, the solver must backtrack or restart.

Its appeal is that the designer specifies only what may touch what, and the algorithm discovers arrangements nobody enumerated. Its weakness is the mirror image: local rules say nothing about global intent, so a town made this way may have perfectly joined streets that never lead anywhere. Practical systems therefore combine methods, using noise or a grammar to lay down the large decisions and letting a constraint solver fill the fine grain, the way a mason lays out the walls before any single stone is chosen.

Worlds generated in pieces

A world larger than memory cannot be generated all at once, so it is divided into chunks, fixed regions that exist only while the player is near them. Minecraft is the familiar reference: its terrain appears column by column as the player walks, and disappears behind them. In Unity the pattern usually involves a manager that tracks the player's position, computes which chunk coordinates should be loaded within some radius, instantiates or reuses meshes for new ones, and releases those that have fallen out of range.

The hard part is the borders, far more than the bookkeeping. A chunk generated in isolation must agree exactly with neighbours that may not exist yet and may be generated later, in a different order, on a different day. This is where the hash-based approach earns its keep: if the height at a point depends only on the seed and the world coordinate of that point, never on chunk-local state, then two adjacent chunks will compute identical values along their shared edge, and the seam vanishes.

Features larger than a chunk require more care. A tree whose canopy overhangs a boundary, a river that crosses several regions, a village sprawling over four: these are typically handled in passes. A first pass decides, for a coarse grid of cells, where large features begin; later passes, run per chunk, ask the coarse grid what overlaps them and draw their share. Generation becomes a staged pipeline in which each stage may read only from stages that are already complete for the surrounding area.

Performance shapes all of this. Generating meshes on the main thread will stall a frame, so production code moves noise evaluation and mesh building into the C# Job System or background threads, often with Burst compilation, and only hands finished vertex arrays to the main thread for the final Mesh.SetVertices call. The world is assembled just ahead of the player's gaze, like a stage crew moving scenery in the dark while the audience looks elsewhere.

Handcrafted against generated

Every generated world eventually confronts the problem of sameness. A thousand procedurally distinct valleys can feel like one valley seen a thousand times, because the human eye is excellent at recognising the rules behind the variation. Players describe this as content that is wide but shallow. The remedy is rarely more randomness; it is more meaning, landmarks and situations that carry intent, and intent is the one thing a rule cannot easily supply on its own.

Rogue, released in 1980, is instructive here. Its dungeons were generated anew on each descent, yet the rooms and corridors served a design that was entirely deliberate: monsters, items and the permanence of death were authored systems, and the generator merely shuffled the stage on which they played. The lineage it began, the roguelike, still works this way. Generation supplies freshness; authored systems supply the reasons a player cares about what was generated.

Most successful projects settle into a hybrid. Designers build vignettes by hand, a ruined chapel, a bandit camp, a shrine at a crossroads, and the generator places them according to rules about terrain, distance and rarity. Others reverse the relationship and handcraft the macro structure while generating the detail: the coastline is drawn, the rocks and grass are scattered. In either case the question is not which approach wins, but which decisions are worth a designer's attention and which can safely be left to arithmetic.

Testing a world nobody has seen

A generated world poses a strange problem for quality assurance, since the developer cannot inspect every version of it. The answer is to test the generator rather than its output. Automated checks can generate thousands of seeds overnight and verify invariants: that every region is reachable from the spawn point, that no settlement is placed in water, that resources fall within intended ranges. A failing seed is then a gift, a perfectly reproducible counterexample that can be loaded and studied at leisure.

Visualisation helps more than almost anything else. Rendering a generator's intermediate stages as flat images, the raw noise, the biome map, the river network, the placed structures, lets a developer see at a glance what would take hours to discover by walking. Many teams build small editor windows for this, with a seed field and a regenerate button, so that tuning a parameter and seeing its consequence takes a second rather than a play session.

There is something faintly unnerving about this kind of work, in the end. One writes a few hundred lines of rules, presses a key, and a place appears that no one has ever visited, with its own quiet hollows and unlucky ridges. A settlement on the edge of a fallen kingdom, such as the one in Crown & Ashes, can sit on ground that was never drawn by anyone. The craft lies in making sure that such ground, however strange, is still a place worth standing on.