Procedural generation promises infinite content. Unity DOTS and the Burst compiler deliver the throughput to make it real-time. Most tutorials stop at noise functions. This one shows how to architect a generation pipeline that scales across cores without allocating garbage.
Why DOTS Changes the Math
Classic MonoBehaviour approaches choke on per-chunk overhead. Each GameObject carries transform hierarchy, component lookup, and GC pressure. DOTS replaces that with contiguous arrays of plain structs. The Burst compiler then vectorizes the math — SIMD instructions process four, eight, or sixteen voxels per cycle.
Entity Archetypes for Chunk Data
Define one archetype per chunk resolution. A 32³ voxel chunk becomes a single entity with a blob asset reference. The blob stores the density field — no per-voxel entities. This keeps the entity count low and the chunk count high.
Streaming With Job Dependencies
Generation must not stall the main thread. Schedule noise jobs, mesh extraction jobs, and blob baking jobs as a dependency chain. The EntityCommandBufferSystem plays back structural changes at sync points.
Marching Cubes on the GPU Side
Burst handles the density evaluation. For mesh extraction, dispatch a compute shader that reads the blob via a StructuredBuffer. This avoids marshaling vertex data back to CPU. The compute shader writes triangles directly into a GraphicsBuffer for DrawProcedural.
| Stage | Thread | Data Flow |
|---|---|---|
| Noise Eval | Burst (CPU) | NativeArray→Blob |
| Mesh Extract | Compute (GPU) | Blob→GraphicsBuffer |
| Render | GPU | DrawProcedural |
Deterministic Seeds for Multiplayer
Sync the world seed once. Derive per-chunk seeds with a hash: seed = hash(worldSeed, chunkCoord). Every client generates identical terrain without networked voxel data. Only modifications — player-placed blocks — replicate.
"Determinism isn't a feature. It's the absence of hidden state.
— Mike Acton
Memory Budget Guardrails
Allocate a fixed NativeArray pool for active chunks. When the pool fills, evict the furthest chunk using a priority queue keyed by distance. Return its blob to a recycle queue. Zero allocations after warm-up.
Ship It Checklist
- Profile Burst timings with
Unity.Profiling.ProfilerMarkerper job. - Validate determinism: run two clients, compare chunk hashes.
- Stress test: 10k chunks, 60 FPS on mid-tier mobile.
- Add a debug overlay showing job graph latency.
✦
Procedural worlds at scale demand data-oriented design. DOTS and Burst give you the primitives. The architecture — archetypes, blobs, job chains, GPU handoff — is yours to build. Start with a single chunk job. Measure. Extend. The infinite world fits in a finite budget.








