How It's Made · Step 9 of 27
Dress the map once - baked PCG scenery, snow and a honeycomb we did not want
unrealpcgsnowperformance

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
- The mapper's tools write the inputs: which cells are forest, rock, scree, path.
- The game itself dumps its own list of walkable cells, because the scenery must never block a path the simulation walks.
scripts/dress_points.pyplaces 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.- 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.
- 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:
- Exposure. Automatic exposure reacts to a huge white ground and darkens everything standing on it. We hold the day exposure on snow instead.
- Honeycomb. One scale of snow texture tiled in a hexagonal pattern you can see from the sky. A second texture at a different scale broke it up.
- Falling snow. A particle system is easy; a particle system that does not hide a tank is not. First flakes were too big and too many. We lowered the column, shrank and thinned the flakes, dimmed them at night and made them face the lens.
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.

What we would do differently
- Bake everything that does not change during play. Do it from the first map.
- Make the obstacle check part of the bake, not a review step.
- Judge exposure with the interface on and units in frame, because a white ground changes everything around it.
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)
Written afterwards from our project notes and commit history; dated to when the work happened.


