Procedural Content Generation (PCG) in a Nutshell
A Reference Guide for PCG in Unreal Engine (5.3)
What is Procedural Content Generation?
Procedural Content Generation (PCG), is the placement of 3D content (objects, trees, grass, buildings, etc.) without being hand-placed by an artist.
The below cityscape was built entirely in a single PCG graph.
I’ll explain how.
What is the Purpose of this Guide?
This little reference guide should help clarify some of the core concepts so you can keep moving ahead quickly and easily.
What are the Prerequisites?
To get started, enable the plugin (only on UE 5.2 & 5.3 as of 8/3/2024)…
Right click…
What are the Basics?
This is the heart of Procedural Content Generation in Unreal Engine;
The PCG Graph
Note the most vital nodes:
- Input — How will we place the content?
In this example, we’ll render the content onto a landscape. - Surface Sampler —On which surface will we place the content?
The sampler picks spots on the surface where we will render objects. - Transform Points — What orientation and size should the objects be?
This node lets us specify or randomize the orientation of content - Spawners — What will be placed?
This node simply defines which meshes or actors will be placed.
Easy.
:)
Meshes vs. Actors?
Most tutorials on PCG that I’ve seen, emphasize the spawning of static meshes, and a simple plus button (+) allows us to add many different meshes to a single node. Like so.
And that creates something like this.
But sometimes you’ll want to spawn something a little more complex than that. That’s where spawning actors come in.
Actors refers to just abut any blueprint. We’ll discuss one of the big differences between them further down this guide.
Density
Surface Sampler
So how do we modify how densely populated our PCG volume gets?
With Point Extents, we define the size of our object. The default value of 100x100x100 is good for large objects like trees. For my grass below, 30x30x30 is much better.
With Points Per Squared Meter, we define how closely packed they can get. Again, the default of 0,1 looks good for trees, but for my grass, I’ve ramped it up to 1000.
Filtering by Height
Point Filter
What if I want to stop my PCG from spawning grass below my waterline, for example?
Add a point filter. This tells PCG to filter points out for whatever reason.
The reason, here, is in the Settings tab.
By using the top output pin, we tell the graph to only render points inside this filter. Then we tell it to target the $Position.Z attribute (height), change the type to float, and specify the height of our shoreline in Float Value.
Et voila. Magic.
Filtering by Landscape Flatness
Projection + Normal To Density + Density Filter
Get deacōnline’s stories in your inbox
Join Medium for free to get updates from this writer.
There’s a quick and easy way to ensure objects like buildings get rendered on relatively flat surfaces.
- The Projection node projects a ray down on our PCG points
- The Normal To Density node changes our Density value into the Normal (an angular measurement) value that’s detected by the Projection node.
- A new Density Filter will omit all Normal values that are not between 0.99% and 100%, a measure of flatness.
- To get our regular Density figures back, there is no such thing as a Density To Normal node, so we simply use a Difference Node.
Very satisfying.
Avoid Overlapping
To space our objects apart, we can turn to the Density Filter node. This node simply tells the PCG graph to ignore a certain number of sample points. If we want a densely populated area, however, we might need to add a few more nodes.
Bounds Modifier & Self Pruning
To keep my large, densely-packed meshes from intersecting one another, we can simply add the Bounds Modifier and a Self Pruning nodes. The Bounds Modifier creates a boundary around each mesh. The Self Pruner prevents any new meshes from being rendered inside another sample points’ boundary. Simple.
Difference
In my example, I wanted to render a lot of buildings with trees scattered between them. The way to do this is with a Difference node.
The trees and buildings have different samplers, so there’s a chance that they’ll overlap (especially since my buildings are pretty large). To prevent trees from spawning inside buildings, my graph renders trees only where there aren’t any buildings. In the space between. In the “difference”.
You can see all of these nodes at work here. I also like to rigorously comment my code. No, no, not for your benefit. I do it to remind myself how my own code works. ;)
Actor Variation
Density Filter
If we link up a Spawn Actor node to our Sampled Points (those black and white boxes), the PCG renders that actor on each point. If we link up many different actors to the graph, we get one instance of each mesh at every point on the map.
That’ll look like this; They’ll all render on top of each other and look like some homogenous mess.
So we need a filter to tell the PCG which asset goes where. Each Spawn Actor node needs its own Density Filter.
(Note: Density is a term used by the PCG system to denote a reference value between 0 and 1–0. 0 = black, 0.5 = grey, and white = 1)
Below, I’ve told the PCG to render Building A if the Lower Bound of a points Density is higher than 0.0, and the Upper Bound is lower than 0.25. So we have a 25% chance to render Building A. My quick demo is set up like this:
Building A = 0.0-0.25
Building B = 0.26-0.5
Building C = 0.51-0.75
Building D = 0.76-1.0
This gives each building a 25% chance of being rendered in any given point.
The result will now look like this; One of four building types on each point.
City Scale
I suspect this’ll get ironed out in an upcoming Unreal Engine update, but for now, actors are set in their own node (unlike meshes). So to render a city’s worth of actors (in this case, a collection of meshes for each building) I had to duplicate my building rendering.
Note that they all spawn from a single Surface Sampler and Transform node. That’s because we want buildings to either be of type A-R in any given location. The trees however, live outside this framework, between buildings. It sounds simple enough, but it took me a while to figure this out for myself.
Splines
Okay, so we’ve looked into how to spawn our PCG goodies within a big cube (volume), but in real life, things aren’t always so neat and tidy. What if we want to spawn a cluster of assets inside a blob?
That’s where splines come in.
A spline is a very simple little Blueprint.
First, we create a blueprint and then we add a spline component. If we save and drop that blueprint into our level, we can set our spline path as illustrated above.
Seeds
Finally, I’d like to discuss one of the most rewarding and enjoyable aspects of PCG.
In the context of procedural generation, a “seed” is a number or text string used to initialize the algorithm that generates the game world or “map”. This seed serves as the basis for the creation process.
The seed is often referred to as the “DNA” for a specific copy of whatever you’re trying to procedurally produce. When we use a specific seed in a procedural generation algorithm, it will always produce the same output. This means that if we generate a world with a certain seed, we can regenerate the exact same world later by using the same seed. Although different seeds will generate very different combinations of results.









