Designing for Constraint: A Practical Intro to Wave Function Collapse
How constraint-based procedural generation actually works, and a minimal implementation you can drop into a Unity project this weekend.
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.
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.
A minimal Unity setup
In practice, I keep the constraint solver engine-agnostic — plain C#, no MonoBehaviours — and treat Unity's job purely as visualization: read the resolved grid, instantiate prefabs. That separation makes the solver testable outside the editor and reusable if you ever port the game.
The full toolkit, including the in-editor authoring workflow, is linked in the portfolio section above.