Brick & Mortar

How It's Made · Step 9 of 27

Step9

Dress the map once - baked PCG scenery, snow and a honeycomb we did not want

· 3 min read

unrealpcgsnowperformance

A lone brick tower on fresh snow at golden hour, with lamp posts and bare trees in the distance.

The last step ended with a problem: dressing a map in C++ every time it loads is slow. On 28 September we fixed it on the first campaign map, an arctic island, and we learned a few things about snow while we were at it.

What was wrong

The old way: when a map loaded, our code walked every cell, used a small hash to decide whether a tree, a rock or a tuft belonged there, and spawned it. That is fine for a prototype. On a big city map, 116 seconds of a 132-second load went on that.

The fix was in the engine all along. Unreal 5.8 ships a procedural content generation framework (PCG). You describe the scatter as a graph; the editor runs it; and the result can be baked into a sublevel so that at play time nothing is computed. The map loads a finished scene, not a recipe.

The pipeline

  1. The mapper's tools write the inputs: which cells are forest, rock, scree, path.
  2. The game itself dumps its own list of walkable cells, because the scenery must never block a path the simulation walks.
  3. scripts/dress_points.py places the points (3,778 of them on this island, from a fixed seed) and checks them against the obstacle rules. It refuses to bake if a rule is broken.
  4. A graph made of one point-creation and one mesh-spawner node per mesh builds the dressing. Running it in the editor's command line took 0.3 seconds for all 3,778 instances.
  5. The result is baked into the map's own sublevel, which the game loads as a level instance.

The check in step 3 earned its keep immediately. On the first run it caught 63 violations: 36 of 77 boulder blocks stood on cells the sim lets units walk through, 6 sat in the sea, 20 strands of wire hung off the cliff cells, and a wreck sat on a water cell. They became scree patches, were removed, or were moved a few dozen units onto the rocks.

Two runs from the same inputs produce the same file, checked by a CRC (1886aa9b both times). Scenery is allowed to be random. It is not allowed to be different on every run, because screenshots and trailer takes should repeat.

Snow

The ground, until then, was one landscape material shared by every map. Snow needed its own: the same layers as before, plus twelve variation masks in a fixed blend order, with the colours calibrated to the albedo of real snow, ice and frozen ground. Snow pretty much destroys a camera that has to show units: it is bright, it is flat, and its tiling shows.

The first proofs showed three problems:

A bonus fix that day: packaging failed because the cooker's log could not live in the cache store on an exFAT drive. A flag, -SkipZenStore, goes around it.

A snowy field seen from above with a dark vehicle, a small tower and a yellow lane line, with interface panels at the edges
Snow in a Tower Defense level a few weeks later, with the interface on: bright ground, dark units, readable at a glance.

What we would do differently

Try it yourself

Your engine probably already has a way to bake a scatter. Look for it before you write a loader. And write a rule that refuses a bad bake: it will find things your eyes will not.

Next: The navy arrives - and the explosion that burned the sea bed (10 October 2026)

Start at Step 1All 27 steps

Written afterwards from our project notes and commit history; dated to when the work happened.