UCAbstractWorldmaker is the abstract base class for terrain generation. It manages the tile grid, LOD computation, async build pipeline, noise blending and mesh lifecycle. Concrete implementations (UCWorldmaker_ProceduralMesh, UCWorldmaker_DynamicMesh) provide the actual mesh creation.
Pure Virtual Functions
Name
Description
isFirstStart
Returns true if no mesh has been created yet
cleanPmc
Destroys the mesh component at a given UV index
calculatePoint
Computes tile mesh data (LOD, vertex count, transform) for a world/relative UV pair
createPMC_sync
Creates mesh components on the game thread from pre-calculated data
debug
Toggles debug material on/off for all mesh components
// These must be implemented by subclasses:
virtualboolisFirstStart() =0;
virtualvoidcleanPmc(FCUVIndex index, bool clearContent, bool remove = true) =0;
virtualvoidcalculatePoint(const FCUVIndex& world, const FCUVIndex& rel) =0;
virtualvoidcreatePMC_sync(const TArray<TPair<FCUVIndex, FCUVIndex>>& pairUVArray, bool poolStart, int poolSize) =0;
virtualvoiddebug(bool onOff, UMaterialInterface* debugMaterial) =0;
Build Pipeline
Name
Description
buildASync
Entry point called by the spawner. Runs drawFloor async then updatePMC_sync on game thread
wantDraw
Guards against redundant draws: checks room state, pawn movement and queue status
drawFloor
Computes the tile grid around the pawn, runs calculatePoint in parallel, enqueues pooled batches
updatePMC_sync
Dequeues one batch, removes old tiles, calls createPMC_sync, broadcasts delegates
adaptPoolSize
Dynamically adjusts pool batch size based on frame time
// buildASync is the main entry point, called each tick by ACWorldSpawner:
worldmaker->buildASync(singleDoRun, pawnX, pawnY);
// Internally:
// 1. wantDraw() checks if a new draw pass is needed
// 2. drawFloor() computes UV grid, runs calculatePoint() in ParallelFor
// 3. Results are enqueued as FCWorldDataQueue batches
// 4. updatePMC_sync() dequeues and creates meshes on game thread
Z Calculation & Noise Blending
Name
Description
innerZCalculate
Computes the Z height at (x,y) by blending world, cluster, room and edge noises
calcMax4PointSlope
Samples 4 surrounding points to estimate terrain slope
calcNormal
Computes a surface normal from 3 sample points
bendRotatorOnSlope
Adapts a rotator to align with the computed slope
// innerZCalculate blends multiple noise layers:
// - worldNoise: base terrain noise
// - clusterNoise: per-cluster noise variation (with optional specific noise per cluster)
// - clusterShiftNoise: shift noise for cluster boundaries
// - roomNoise: noise variation inside rooms
// Blending uses easeIt() with the configured easeMethod (default QuinticInOut).
FLinearColor vertexColor;
float z = worldmaker->innerZCalculate(x, y, vertexColor);
// Vertex color encodes spatial context for material use:
// R = cluster proximity (0 = outside, 1 = center)
// G = room proximity (0 = outside, 1 = center)
// B = corridor/edge proximity (0 = outside, 1 = center)
// A = biome noise value (normalized)
Noise Sources
Name
Description
worldNoise
Base terrain noise, singleton CNAME_Singleton_WorldNoise
biomeNoise
Biome boundary noise, singleton CNAME_Singleton_BiomeNoise. Stored in vertex color alpha
clusterNoise
Cluster-level noise, singleton CNAME_Singleton_ClusterNoise. Can be overridden per cluster
clusterShiftNoise
Cluster boundary shift noise, singleton CNAME_Singleton_ClusterShiftNoise. Can be overridden per cluster
Returns true once noise initialization is complete
isBuilt
Returns true once all tile batches have been processed
isRendered
Checks if a tile at (x,y) is rendered, outputs UV index and full LOD status
onTileReady
Delegate broadcast when a tile mesh is created (with UV index and fullLOD flag)
onTileRemoved
Delegate broadcast when a tile mesh is removed (with UV index and area rectangle)
// Bind to tile lifecycle events:
worldmaker->onTileReady.AddDynamic(myObject, &ICWorldBoundable::onTileReady);
worldmaker->onTileRemoved.AddDynamic(myObject, &ICWorldBoundable::onTileRemoved);
// Check world state:
if (worldmaker->isReady()) { /* Z queries are safe */ }
if (worldmaker->isBuilt()) { /* all tiles generated */ }
FCUVIndex uvIndex;
bool fullLOD;
if (worldmaker->isRendered(x, y, uvIndex, fullLOD)) {
// tile exists and is rendered
}