Most procedural generation tutorials start with noise functions and stop there. Wave Function Collapse (WFC) is a different way in: instead of sampling randomness directly, you describe local adjacency rules — which tile can sit next to which — and let the algorithm propagate constraints until every cell in the grid is resolved.
The core loop
WFC treats each cell in your output grid as a superposition of every tile that hasn't been ruled out yet. The loop is simple:
- Pick the cell with the lowest entropy — the fewest remaining possibilities.
- Collapse it to a single tile, weighted by your input frequencies.
- Propagate that choice outward, removing now-invalid options from neighboring cells.
- Repeat until every cell has collapsed, or you hit a contradiction and backtrack.
That's the whole algorithm. The interesting engineering work is in step two and three: how you represent adjacency rules, and how efficiently you propagate.
A minimal entropy picker
The engine-agnostic core is plain data manipulation — no MonoBehaviours, nothing Unity-specific. That makes it unit-testable outside the editor:
function lowestEntropyCell(grid) { return grid.cells .filter((c) => !c.collapsed) .reduce((min, c) => c.options.length < min.options.length ? c : min );}
function collapse(cell, weights) { cell.value = weightedPick(cell.options, weights); cell.collapsed = true; return cell;}Where it earns its keep
WFC shines when your content has implicit grammar — dungeon layouts, circuit-like level geometry, tile-based terrain — anything where "this piece touches that piece" is a real constraint, not just texture. It's a poor fit for content that's genuinely continuous, like terrain heightmaps, where noise-based approaches are simpler and cheaper.
Treat the solver as a pure function of constraints in, grid out — the moment it knows about Unity, you've lost the ability to test it in isolation.
The full toolkit, including the in-editor authoring workflow, is linked in the portfolio section above.