ue-procedural-generation
Use this skill when working with procedural generation in Unreal Engine: PCG framework, ProceduralMesh, instanced mesh, HISM, spline, runtime mesh, noise, terrain generation, or dungeon generation. See references/pcg-node-reference.md for PCG node types and references/procedural-mesh-patterns.md for
By quodsoler · 829 installs
npx skills add quodsoler/unreal-engine-skills --skill ue-procedural-generation
Source repository · Upstream listing
UE Procedural Generation
Target engine: UE 5.8 . APIs below are verified against the 5.8 headers; older forms are listed under "Deprecated — do not use".
Covers the PCG framework (plugin PCG at Engine/Plugins/PCG , enabled by default, Build.cs module PCG ), runtime mesh building with UProceduralMeshComponent (plugin ProceduralMeshComponent , module ProceduralMeshComponent ) and UDynamicMeshComponent + Geometry Script (modules GeometryFramework and GeometryScriptingCore ), instancing with UInstancedStaticMeshComponent / UHierarchicalInstancedStaticMeshComponent , spline driven placement, and deterministic noise/random from Core .
Context
Read .agents/ue project context.md if it exists (module names, conventions, enabled plugins, GAS/networking setup). Do not stop if it is missing.
Identify the area from the request and the codebase. Ask only when two plausible readings would produce different code.
Request is about… Go to
Enabling PCG, module/plugin wiring [PCG setup]( pcg setup)
Driving generation from an actor, runtime generation, partitioning [PCG component and runtime generation]( pcg component and runtime generation)
Reading/writing points inside a graph [Point data]( point data)
Writing a new PCG node in C++ [Custom PCG node in C++]( custom pcg node in c)
Which node does X, pin labels, node settings fields [PCG node reference](references/pcg node reference.md)
Building triangles at runtime [ProceduralMeshComponent]( proceduralmeshcomponent)
Boolean ops, primitives, baking to a static mesh [Dynamic Mesh and Geometry Script]( dynamic mesh and geometry script)
Thousands of repeated meshes [Instanced static meshes]( instanced static meshes)
Roads, rivers, fences, cables [Splines]( splines)
Heightfields, scatter, reproducible results [Noise and deterministic random]( noise and deterministic random)
Marching cubes, BSP dungeons, WFC, Poisson disc [Procedural mesh patterns](references/procedural mesh patterns.md)
PCG setup
Class Header Role
UPCGComponent PCGComponent.h Actor component that owns a graph and drives generation
UPCGGraph PCGGraph.h Graph asset: nodes, edges, UserParameters
UPCGGraphInstance PCGGraph.h Graph instance with per instance parameter overrides
UPCGGraphInterface PCGGraph.h Common base of graph and graph instance
UPCGSettings PCGSettings.h Node settings base class
IPCGElement PCGElement.h The executable half of a node
FPCGContext PCGContext.h Per execution state: InputData , OutputData , Node , ExecutionSource
UPCGBasePointData Data/PCGBasePointData.h Abstract point collection
UPCGPointArrayData Data/PCGPointArrayData.h Structure of arrays point data
UPCGSubsystem Subsystems/PCGSubsystem.h Scheduling, partitioning, runtime generation
APCGVolume PCGVolume.h Volume actor carrying a UPCGComponent
PCG component and runtime generation
Call Replication Use for
Generate(bool bForce) / Cleanup(bool bRemoveComponents) NetMulticast, Reliable Server driven generation that must appear on clients
GenerateLocal(bool bForce) / CleanupLocal(bool bRemoveComponents) none Client side or single player generation
NotifyPropertiesChangedFromBlueprint() none Mark dirty and conditionally regenerate after editing exposed properties
CancelGeneration() none Abort an in flight generation
GetGeneratedGraphOutput() none Read back the FPCGDataCollection the graph produced
EPCGComponentGenerationTrigger ( PCGComponent.h:77 ): GenerateOnLoad , GenerateOnDemand , GenerateAtRuntime .
Partitioning and runtime generation:
SetIsPartitioned(bool) / IsPartitioned() back the bIsComponentPartitioned property; partitioned components dispatch work to local components on a grid.
GenerateAtRuntime hands the component to the runtime gen scheduler. Tune it with SchedulingPolicyClass / SchedulingPolicy ( UPCGSchedulingPolicyBase ) and bOverrideGenerationRadii + GenerationRadii ( FPCGRuntimeGenerationRadii ).
Scheduler CVars: pcg.RuntimeGeneration.Enable , pcg.RuntimeGeneration.NumGeneratingComponents , pcg.RuntimeGeneration.GlobalRadiusMultiplier , pcg.RuntimeGeneration.EnablePooling , pcg.RuntimeGeneration.BasePoolSize , pcg.RuntimeGeneration.FramesBeforeFirstGenerate , pcg.RuntimeGeneration.EnableChangeDetection , pcg.RuntimeGeneration.EnableDebugging .
UPCGSubsystem::GetSubsystemForCurrentWorld() returns the subsystem; RefreshAllComponentsFiltered(Filter, ChangeType) forces a refresh of a subset ( WITH EDITOR only, Subsystems/PCGSubsystem.h:227 230 ).
Hierarchical generation lives on UPCGGraph : bUseHierarchicalGeneration , HiGenGridSize ( EPCGHiGenGrid::Grid4 … Grid2048 , plus Unbounded ), HiGenGridSizeMultiplier , bUse2DGrid .
Graph parameters are an FInstancedPropertyBag UserParameters on UPCGGraph , read and written through UPCGGraphInterface :
Point data
Point collections are UPCGBasePointData . UPCGPointArrayData is the structure of arrays implementation; UPCGPointData is the array of FPCGPoint implementation kept for compatibility. Allocate through the context so the project configured class is used:
Never iterate GetPoints() / GetMutablePoints() in new code — that only exists on UPCGPointData and forces a conversion. Read and write through value ranges instead:
Per point native properties ( EPCGPointNativeProperties in PCGPointPropertiesTraits.h ): Transform , Density , BoundsMin , BoundsMax , Color , Steepness , Seed , MetadataEntry , plus All and AllProperties . Sizing and allocation:
Other data types: UPCGSpatialData (base), UPCGSplineData , UPCGLandscapeData , UPCGVolumeData , UPCGTextureData , UPCGPrimitiveData , UPCGDynamicMeshData , and UPCGParamData for attribute sets. UPCGSpatialData::ToBasePointData(FPCGContext , const FBox&) discretizes any spatial data into points.
Custom PCG node in C++
A node is a UPCGSettings subclass plus an IPCGElement . Settings hold data; the element is const and stateless and reads everything from FPCGContext .
Rules that fall out of the headers:
SupportsBasePointDataInputs returning false (the default) makes PCG convert every input to UPCGPointData before your element runs. Return true and use value ranges.
IsCacheable must return false if the node spawns actors or components, or reads untracked data.
CanExecuteOnlyOnMainThread returning true serializes the node onto the game thread; keep it false unless you touch UWorld or components.
Long loops belong in FPCGAsync::AsyncProcessingRangeEx(&Context AsyncState, NumIterations, Initialize, ProcessRange, MoveDataRange, Finished, bEnableTimeSlicing) ( Helpers/PCGAsync.h ), which time slices and multithreads.
Pin labels come from PCGPinConstants::DefaultInputLabel ( "In" ), DefaultOutputLabel ( "Out" ), DefaultParamsLabel ( "Overrides" ), DefaultExecutionDependencyLabel .
Blueprint nodes derive from UPCGBlueprintBaseElement and override the Execute(const FPCGDataCollection&, FPCGDataCollection&) BlueprintNativeEvent; seed helpers are GetSeedWithContext(GetContextHandle()) and GetRandomStreamWithContext(GetContextHandle()) .
See [PCG node reference](references/pcg node reference.md) for node settings classes, pin behaviour, metadata attributes and GPU nodes.
ProceduralMeshComponent
Triangle level control at runtime. No Nanite support, no automatic LODs.
Materials come from UMeshComponent::SetMaterial(int32 ElementIndex, UMaterialInterface Material) — one material slot per section index.
Collision:
bUseComplexAsSimpleCollision (default true) uses the rendered triangles for collision. Accurate, expensive, and cannot be simulated — set it to false and feed AddCollisionConvexMesh when the mesh must be dynamic.
bUseAsyncCooking moves physics cooking off the game thread. Collision lags a frame or more behind the visual mesh; use it for far away streamed geometry.
UpdateMeshSection LinearColor moves existing vertices and refreshes collision, but cannot change vertex or triangle count — call CreateMeshSection LinearColor when topology changes. Build the arrays on a worker thread, then call the component on the game thread; see [async mesh generation](references/procedural mesh patterns.md async mesh generation pattern).
Dynamic Mesh and Geometry Script
UDynamicMeshComponent ( GeometryFramework , header Components/DynamicMeshComponent.h ) plus the Geometry Script libraries ( GeometryScriptingCore ) are the modern path: boolean operations, remeshing, normals recomputation, and baking to a UStaticMesh asset (editor only — CopyMeshToStaticMesh errors "Not currently supported at Runtime" outside WITH EDITOR , MeshAssetFunctions.cpp:471 ).
Library Representative functions
UGeometryScriptLibrary MeshPrimitiveFunctions AppendBox , AppendSphereLatLong , AppendSphereBox , AppendCapsule , AppendBoxWithCollision
UGeometryScriptLibrary MeshBooleanFunctions ApplyMeshBoolean(TargetMesh, TargetTransform, ToolMesh, ToolTransform, Operation, Options, Debug)
UGeometryScriptLibrary MeshDeformFunctions ApplyPerlinNoiseToMesh2(TargetMesh, Selection, Options, Debug)
UGeometryScriptLibrary MeshNormalsFunctions RecomputeNormals(TargetMesh, CalculateOptions, bDeferChangeNotifications, Debug) , SetPerFaceNormals
UGeometryScriptLibrary StaticMeshFunctions CopyMeshToStaticMesh , CopyMeshFromStaticMeshV2
A worked example is in [dynamic mesh with Geometry Script](references/procedural mesh patterns.md dynamic mesh with geometry script).
Collision on UDynamicMeshComponent : EnableComplexAsSimpleCollision() , SetComplexAsSimpleCollisionEnabled(bool bEnabled, bool bImmediateUpdate) , SetSimpleCollisionShapes(const FKAggregateGeom&, bool bUpdateCollision) , bDeferCollisionUpdates + UpdateCollision(bool bOnlyIfPending) . ADynamicMeshActor ships a component at the root via GetDynamicMeshComponent() .
Instanced static meshes
UInstancedStaticMeshComponent UHierarchicalInstancedStaticMeshComponent
Header Components/InstancedStaticMeshComponent.h Components/HierarchicalInstancedStaticMeshComponent.h
Best for Small, frequently mutated sets Large, mostly static sets
Culling Start/end cull distance Hierarchical tree plus cull distance
Removal Cheap Triggers a tree rebuild ( bAutoRebuildTreeOnInstanceChanges , BuildTreeIfOutdated )
Per instance floats set with SetNumCustomDataFloats / SetCustomDataValue are read in materials through the PerInstanceCustomData node. Cull properties: InstanceStartCullDistance , InstanceEndCullDistance , InstanceLODDistanceScale , bUseGpuLodSelection .
Batch large populations: PreAllocateInstancesMemory first, build the whole TArray<FTransform , then one AddInstances call. A full seeded scatter that traces onto terrain and fills per instance custom data is in [vegetation scatter](references/procedural mesh patterns.md vegetation scatter hism).
Foliage (module Foliage ): painted foliage lives on AInstancedFoliageActor backed by UFoliageInstancedStaticMeshComponent ; simulation driven placement uses UProceduralFoliageComponent with a UProceduralFoliageSpawner . PCG's Static Mesh Spawner node is usually the better fit for graph driven scatter.
Splines
ESplinePointType::Type : Linear , Curve , Constant , CurveClamped , CurveCustomTangent . ESplineCoordinateSpace::Type : Local , World .
Pass bUpdateSpline = false while batching edits and ca