This blog post will break down the Unreal PCG section of the Procedural Monadnock project. You will be able to see the construction of the PCG system used to populate the landscape. I’ll also talk about the process and some problems I encountered throughout this section of the project. Link to Portfolio Post here:
Data Asset Framework
Utilizing Data Assets, I can easily create, edit, and control what data the PCG system is processing.
A Layer Properties Data Asset stores the controls for each layer. Including Layer Density, Masking, Custom Colors, and another Data Asset containing the mesh contents
The Properties Data Asset contains the contents of each layer and the controls that guide their placement. This data includes their spawn Weight, Meshes (Detailed and Imposter), Cull Distances, Orientation, Self Pruning Bias, Transforms, WPO Disable Distance. This structure also supports spawning Level Instances rather than meshes, as well as a debug toggle.
Main vs Sub-Gen
This framework supports three levels of generation: a Main graph for the overall large-scale forest and two Sub-Gen graphs for smaller, high-detail areas influenced by the Main graph’s data.
Red arrows denote areas of Sub-Gen
The separation into these two systems is driven by performance and cook time. The Main graph covers the entire landscape with a lower point density, while the Sub-Gen graphs handle high-detail areas with significantly higher point density. This division allows for detailed generation in focused areas without exceeding PCG or hardware limitations, maintaining both scale and performance without overwhelming the system.
Creating Level Instances
Physics Based Scattering
This PCG system enables the spawning of physics-simulated meshes, which fall to the ground during level simulation. After saving their positions and returning to the editor, I can generate a pile of physically placed objects, which can then be instanced through a PCG graph. This approach significantly streamlined the process of creating and iterating Level Instances for the scene.
Mesh Sampling
By utilizing a Mesh Sampler node in the PCG system, I scattered points across a mesh surface and filtered them by their normals, retaining only the upward-facing ones. These points were then used to spawn actors. Additionally, with the use of tags, I filtered the points during Level Instance processing, enabling per-instance variation for each Level Instance. This approach was inspired by a talk from Chris Murphy at Unreal Fest
Problems Encountered
Handling Various Layer Count
The original system was limited to a hard-coded count of eight layers. By converting the Landscape Layers Subgraph into a loop capable of handling any number of layers, I eliminated the hard cap, though this required reworking the layer partitioning process.
Runtime Hi-Gen
I experimented with combining the Main Graph with a Hi-Gen Runtime Graph to manage foliage. However, due to the large amount of point data being passed from the Main Graph to the Runtime Graph for point masking, performance issues arose. The need for smaller partitions in the Runtime Graph made the culling and spawning of meshes visually noticeable and distracting. Additionally, the partitioning caused some meshes to be cut off. These challenges led to the development of the Sub-Gen framework.
Partitioning
The large volume of point data being sent from the Main Graph to the Sub-Gen Graph for point masking caused extremely slow cook times. By partitioning the Main Graph, I was able to reduce the cook time by limiting the data sent to the Sub-Gen Graph to only the point data within each specific partition.
PCG Bugs & Learning Pains
The PCG system, while impressive, is still in its early stages and has presented some challenges during my work. One notable issue was the Mesh Spawning node’s inability to process Dynamically Created Attributes, which I managed to address with assistance from PGC developer Adrien Logut.
Additionally, learning resources for PCG are limited, making troubleshooting more challenging. However, the PCG chat on the Unreal Source Discord has been an invaluable resource for resolving many of these issues.