What is WorldScape

WorldScape brings Clipmap-based terrain technology to Unreal Engine. With its 64-bit precision geometry, you can craft infinite flat and spherical worlds for single-player or multiplayer games. Instanced, multithreaded procedural foliage, RGBA-layered noise biomes, custom planetary gravity, heightmap import (8/16-bit), procedural materials and many editor tools come in the box. All sources in C++.

Who this is for: game developers using UE5 who need procedural surfaces that scale beyond UE's stock Landscape system, planet-scale exploration, multiplayer survival sandboxes, RTS battlefields, infinite arcade worlds, cinematic real-world recreations.

Feature list

  • Create an infinite world playable in single-player and multiplayer, flat or spherical.
  • 64-bit geometry precision for surface mesh construction.
  • Create infinitely large or tiny flat worlds.
  • Create infinitely large or tiny planets.
  • Instanced & multithreaded procedural foliage (spawn driven by terrain temperature & humidity).
  • Import HeightMaps in 8-bit or 16-bit and apply them to surfaces as decals (additive or merged).
  • Editable terrain collision.
  • Noise biomes customizable in C++.
  • Realistic lighting for planets.
  • WorldShifting ("fake 64-bit squared") for stable kilometer-scale gameplay.
  • Procedural materials for surfaces.
  • Custom MovementComponent BP for planetary gameplay.
  • Custom gravity behavior for planets.

Architecture

WorldScape ships as 10 native modules. Each one does one thing:

ModuleTypeRole
WorldScapeCoreRuntimeThe Root actor, mesh component, LOD pipeline, FCP collision pool, grid & snap spawners
WorldScapeNoiseRuntimeNoise classes. Earth, Moon, Rocky, Ice, Selenae, Cube, Warped, Tiny, HeightMap-based
WorldScapeFoliagesRuntimeFoliage Asset / Collection / Cluster / Blueprint with biome constraints
WorldScapeVolumeRuntimeHeightMap, Noise, Hole and Foliage Mask volumes
WorldScapeCommonRuntimeDouble-precision math, FDVector, shared structs
WorldScapeComputeRuntimeGPU compute shaders for noise generation
WorldScapeGPUTerrainRuntimeQuadtree manager, heightfield manager, custom vertex factory
WorldScapeEditorEditorToolbar, custom details panels, content browser categories
WorldScapeFactoryEditorAsset factories for noise classes, foliage assets, heightmap data
WorldScapePCGEditorProcedural Content Generation nodes & Blueprint library
Diagram, module dependencies assets/new/diagrams/architecture.svg

Requirements

  • Unreal Engine versions supported: 4.26, 4.27, and 5.0 through 5.7
  • Build platforms: Win64 or Linux (the plugin's .uplugin blacklists Mac, iOS and Android)
  • Plugins activated automatically: Niagara, ProceduralMeshComponent, ModelingToolsEditorMode, Landmass, GeometryScripting, PCG, QLevel
  • For packaging: the Water plugin must be enabled (see Troubleshooting)
  • Networking: replication is supported on Dedicated Server and Listen Server
Fab Marketplace: WorldScape ships as a single Fab listing covering UE 4.26-5.7. First published August 2021, actively maintained.

Installation

From a fresh project to a procedural planet in under 10 minutes.

1

Get the plugin

Buy WorldScape on Fab Marketplace. Install via the Epic Games Launcher into your engine, or copy the WorldScape folder into YourProject/Plugins/.

2

Enable in your project

Open your UE5 project, go to Edit → Plugins, search for WorldScape, enable it, and restart the editor when prompted.

3

Apply the required UE5 settings

WorldScape needs two engine settings adjusted for terrain artifacts to disappear. See the next section.

4

Open the demo map

Inside the plugin's Content/Maps folder, open L_PlanetCore. Hit Play. Walk around. You're on a 6,360 km procedural planet.

Recommended UE5 settings

One render setting fixes a known visual artifact on UE 5.x:

Velocity Pass: Write After Base Pass

Open Project Settings → Rendering → Velocity Pass and set it to Write After Base Pass. This prevents terrain visual artifacts on UE 5.x.

Project Settings. Velocity Pass capture to refresh in UE 5.x
Floating point fix (legacy materials): if you see floating-point artifacts on the surface, open the material function MF_SLM_Layer_Planet in the WorldScape material functions folder, find planet location, right-click → Promote to Double, and set Rotate with Planet to false. (Thanks to zyzy2922 for spotting this.)
About r.UseVisibilityOctree 0: earlier docs recommended this engine cvar. It is not registered by the WorldScape plugin and is deprecated in modern UE5 builds, so it has been removed from the setup. The plugin's own runtime cvars are listed in the Console reference.

Your first flat world

1

Drag a Root

In the Place Actors panel, type "WorldScape" and drag WorldScapeRoot into your level. Add a directional light if your scene doesn't have one.

2

Set the world type

In the Root's details panel, set Generation Type (the GenerationType property, of type EWorldScapeType) to Flat World.

3

Position at origin

Make sure the actor's transform location is (0, 0, 0).

4

Pick a noise & generate

Assign a noise asset to the Root's WorldScapeNoise property (right-click in the content browser → WorldScape tab to create one). See Noise system for the list of built-in noise classes. Generation runs automatically; force a regen with WS_ForceRegenerate() from Blueprint.

Place Actors. WorldScapeRoot in UE 5.x capture to refresh

Your first planet

1

Drag a Root

Same as flat world, drag WorldScapeRoot into the level.

2

Set Generation Type to Planet, enable Generate

In the details panel under the Default category, set GenerationType to Planet. Enable bGenerateWorldScape (DisplayName "Generate") and bOcean (DisplayName "Generate Ocean"). The companion flag bFreezeGeneration (DisplayName "Freeze Generation") pauses regeneration if you ever need to lock the world while editing.

3

Set the planet scale

The Root's PlanetScale property holds the planet's radius in centimeters. Default value is 637817792 (a classic Earth-radius approximation in cm). Lower it for moons, raise it for gas giants.

PlanetScale = 637817792.0 // default — Earth-like

If your camera starts inside the planet, lift it up by roughly PlanetScale on Z (legacy maps used a transform offset of Z = -PlanetScale to put the actor's pivot at the planet's center). The plugin no longer requires this convention, placing the Root at (0,0,0) is fine and the demo map does just that.

4

Pick a planet-class noise

Use one of the built-in noise generators: UTerraNoiseExample, URockyWorldsNoise, USelenaeNoise, UIceWorldNoise, UCubeNoise, UTinyPlanetExample, UTheMoonNoise, or your own subclass. See Built-in noises.

5

Materials, foliage, atmosphere

Copy materials from the demo map, add foliage collections to the Foliage tab, drop in a Sky Atmosphere and Skylight. Hit play.

Recommended starting values: TriangleSize500-5000 (vertex spacing in cm near the ground), LodResolution32-64 (vertices per axis per LOD), MaxLod10-12 (lower values cause mountain pop-in), PlanetScale = target radius in cm (Earth-like = 637,817,792).

Demo map tour

The plugin ships a single sample map: WorldScape/Content/Maps/L_PlanetCore.umap. Use it to validate your install and as a reference scene for your own setup. (Older docs and tutorials may reference a "Demonstration_EarthLikePlanet" map, that name is legacy; the current map is L_PlanetCore.)

Demo disclaimer: the sample map was put together quickly with placeholder objects and textures. Use it to verify the plugin works on your machine, not as a benchmark of visual quality.
L_PlanetCore, outliner + viewport overview capture to add

Core Concepts

Understand these five concepts and the rest of the docs slot in cleanly.

Flat vs Planet

EWorldScapeType picks one of two surface topologies:

ModeMathUse case
Flatinfinite tiled XY planeRTS, survival, top-down, square open worlds
Planetcube-mapped sphere with FDVector ECEF coordsspace sims, full-planet exploration, real-world heightmaps

Both share the same Root actor, same noise system, same foliage stack. You can swap between them by changing one enum and the transform.

Root properties, quick reference

Verified directly against WorldScapeRoot.h. Categories below match the names you see in the editor's details panel.

Default

PropertyTypeDefault
GenerationTypeEWorldScapeType(none)
bGenerateWorldScapebool(none). DisplayName "Generate"
bFreezeGenerationbool(none). DisplayName "Freeze Generation"
bOceanbool(none). DisplayName "Generate Ocean"
bProjectPositionbool(none). DisplayName "Projected Position (Experimental)"
IsAllowAutoGetNearestbooltrue, lets the subsystem track this Root
UsePostSlateTickbooltrue
OverrideMainTickbooltrue
StartTickGroup, EndTickGroupETickingGroupTG_PrePhysics
PlanetScalefloat637817792, only shown when GenerationType == Planet

Lod Parameters

"Collisions are generated around the player, 1 at the player position, and 8 around. Collision size is Collision Resolution × Collision Triangle Size. LOD Resolution is the number of vertices generated on each axis. TriangleSize is the distance between each vertex of the terrain when near the ground."
PropertyTypePurpose
MaxLodint32How many LODs of doubling-size sectors are generated.
LodResolutionint32Number of vertices per axis per sector. Higher = more detail, more cost.
TriangleSizefloatDistance between each vertex of the terrain when near the ground (cm).
HeightAnchorfloatDoubles triangle size above this altitude so distant/high terrain is cheaper.
OceanMaxLod, OceanLodResolution, OceanTriangleSizeint32 / floatSame triplet for the ocean clipmap. Hidden when bOcean = false.

Collision

CollisionTriangleSize (float) is in the Collision category, not Lod Parameters, gated by bGenerateCollision / bGenerateCollisionInEditor.

Noise

PropertyTypeDefault
WorldScapeNoiseUWorldScapeNoiseClass*nullptr, assign your noise asset here
NoiseScalefloat800
NoiseIntensityfloat1200000
NoiseOffsetFVector(0,0,0)
Seedint3210
OceanHeightfloat0, hidden when bOcean = false
MaxLod recommendation: minimum 8 for low-variation worlds, 10-12 for altitude-heavy terrain to prevent mountain pop-in.
Diagram, sectors & LOD pyramidassets/new/diagrams/lod-system.svg

64-bit precision (FDVector)

UE5's stock FVector is float-precision. At kilometer scale that's not enough, you get jitter, terrain seams, snapping artifacts. WorldScape uses FDVector (double-precision) internally for all surface positions, then converts to float at the rendering boundary. That's how you get a 100,000 km planet without losing centimeter-level placement at the player's feet.

The Root actor lifecycle

AWorldScapeRoot exposes a small set of Blueprint-assignable delegates, verified directly in WorldScapeRoot.h:

DelegateSignatureFires when
InitializedEndFInitializedEnd()The Root has finished its first initialization pass.
OnCollisionLodsUpdateFOnCollisionLodsUpdate(UWorldScapeLod*)A per-section collision LOD update; provides the affected UWorldScapeLod*.
WS_Pooling_OnInitializedFWS_Pooling_OnInitialized()Volume pooling is fully initialized and ready for Pooling_Take_* calls.
WS_Grid_LoadCell_DelegateFWS_Grid_LoadCell_Delegate(const FWS_Grid& Cell)A grid cell finished loading.
WS_Grid_UnLoadCell_DelegateFWS_Grid_UnLoadCell_Delegate(const FWS_Grid& Cell)A grid cell unloaded.
WS_Grid_StartPendingLoadFWS_Grid_StartPendingLoad()A batch grid-load window opened.
WS_Grid_EndPendingLoadFWS_Grid_EndPendingLoad()A batch grid-load window closed.
Note: the source contains a commented-out block declaring WS_OnStartFoliage, WS_OnEndFoliage, WS_OnStartGrid, WS_OnEndGrid, WS_OnStartTerrain, WS_OnEndTerrain, WS_OnStartCollision, WS_OnEndCollision (between /* and */ in WorldScapeRoot.h around lines 357-386). These delegates are not currently exposed in the build, an earlier audit incorrectly listed them as available.

The Subsystem adds 4 more cross-Root delegates: WS_OnNearestChanged, WS_OnNearestNULL, WS_OnWorldScapeRegistry, FWS_OnWorldScapeUnRegistry.

The Subsystem Beta

"The subsystem updates the terrain closest to the player, transfers parameters from one terrain to another, knows the orientation from the center of the planets in real time, automatically updates a Material Parameter Collection with planet and flat-world parameters, and notifies you when a planet is registered or destroyed. All systems have delegates that you can connect to your own system."

Class name: UWorldscapeSubsystem. Auto-created per UWorld.

Cross-Root delegates

  • FWS_OnWorldScapeRegistry(AWorldScapeRoot*), a Root just registered
  • FWS_OnWorldScapeUnRegistry(AWorldScapeRoot*), a Root unregistered
  • FWS_OnNearestChanged(AWorldScapeRoot*), the player got within range of a different Root
  • FWS_OnNearestNULL(), no Root is nearby anymore

Key functions (BlueprintCallable)

FunctionReturnsPurpose
Get_NearWorldScapeFromLocationAWorldScapeRoot*Find the active Root nearest to a location, with optional valid/exclude tags.
WS_Start_AutoGetNearestvoidStart auto-tracking the nearest world for the player.
WS_Stop_AutoGetNearestvoidStop the auto-tracking loop.
WS_GetValidNearestboolTrue if a tracked Root is currently valid.
WS_GetCurrentNearestRootAWorldScapeRoot*Currently tracked Root (null if none).
WS_GetCurrentSurfaceUpVectorFVectorUp-vector at the player's current surface point.
WS_GetActualGravityFromLocationFVectorGravity vector + direction + magnitude at any location.

Auto-Get-Nearest tuning (subsystem settings)

PropertyDefaultPurpose
AutoGetNearest_AutoEnabledtrueMaster switch for auto-tracking.
AutoGetNearest_Update_Interval1.0 sHow often to re-pick the nearest Root.
AutoGetNearest_PlanetaryRadiusScaleLimit1.5Multiplier on PlanetScale beyond which the Root is considered out of range.
AutoGetNearest_FlatDistanceToGroundLimit20,000,000 cmMax distance for flat worlds.
AutoGetNearest_Use_ValidTagfalseRequire the valid tag for tracking. Defaults OFF, flip on if you want tag-filtered tracking.
AutoGetNearest_ValidTagWS_ValidTag a Root must carry to be tracked (when Use_ValidTag is on).
AutoGetNearest_Use_InvalidTagfalseApply the exclude tag. Defaults OFF.
AutoGetNearest_invalidTagWS_InvalidTag that excludes a Root from tracking.

Material Parameter Collection auto-sync

The subsystem owns a UMaterialParameterCollection* reference and updates it every frame with the current surface up-vector (Update_SurfaceVector()) and other planet/flat-world parameters (Update_MPC_Value()). Reference that MPC in any material or shader to get gravity-aware effects without calling functions from Blueprint.

Noise system

Every WorldScape vertex is the output of a noise function. The noise drives both shape (height) and biome (temperature, humidity, water mask). Customize it and you customize everything downstream.

FNoiseData, the contract

Every noise function returns an FNoiseData struct. Seven fields, registered in vertex color and used everywhere:

FieldTypeDescription
HeightNormalizedoubleHeight normalized 0-1, also stored in vertex color Red.
HeightdoubleHeight in Unreal units, displaces terrain from planet center (or up for flat).
TemperaturefloatStored in vertex color Green. Drives material biomes & foliage masking.
HumidityfloatStored in vertex color Blue. Drives material biomes & foliage masking.
WaterMaskfloatFoliage masking + flag for HeightMap Influencer when ocean is higher than terrain.
FoliageMaskfloatDirect foliage masking channel.
HoleboolPer-vertex flag that punches a hole in the terrain (used by the Hole Volume).

Two functions must exist on every noise class:

  • FNoiseData GetHeight(..), terrain noise.
  • FNoiseData GetOceanHeight(..), ocean / river / lake noise.

Built-in noise classes

Two-tier system. Generators (subclasses of UWorldScapeNoiseClass) produce FNoiseData per vertex. Most generators consume a parameter object (subclass of UNoiseParameter) holding the tunable values. Right-click in the content browser → WorldScape tab → create either.

Generators (assign to the Root's WorldScapeNoise property)

Generator classPairs with parameterBest for
UWorldScapeCustomNoiseUCustomNoiseParameterEarth or Moon (with crater mode). The most general-purpose generator.
UTerraNoiseExampleUPlanetTerraNoiseGeneric planetary terrain preset.
URockyWorldsNoiseURockyWorldsRocky, low-vegetation planets.
USelenaeNoiseUSelenaeLuna-like moons.
UIceWorldNoiseUIceWorldIce-covered worlds.
UCubeNoiseUCubeNoiseParameterCube-mapped noise for cubic / weird planets.
UwarpedNoiseeExampleUWarpedNoiseDomain-warped noise for alien terrain.
UTinyPlanetExampleUTinyPlanetSmall procedural worlds (asteroids, marble planets).
UHeightMapBasedV2UHeightMapV2Heightmap-driven instead of pure procedural.
UYourOwnNoiseExampleUYourNoiseParameterTemplate / starting point for custom subclasses.

Additional QANGA / Earth noise generators (under CustomWorldScapeNoise/)

  • UEarthNoiseFuntion, UEarthNoise2Example, alternate Earth-style presets
  • UearthTerra, legacy Earth-Terra blend
  • UTheMoonNoise. Luna preset with craters
  • UBarenWorldsNoise, barren / desert planets
  • UQangaV2Noise, UQangaNoise. QANGA-game-tuned presets
  • UHeightMapBased, legacy heightmap-driven generator (use V2 for new projects)
Note on naming: a few classes carry typos in their C++ symbol (UwarpedNoiseeExample, UEarthNoiseFuntion, UearthTerra). The plugin still ships them as-is; use them with their literal name.
Gallery, one preview per generator (~16 thumbnails)assets/new/captures/noise-gallery.png

Custom noise (C++)

WorldScape was designed for noise editing in C++. Subclass UWorldScapeNoiseClass, implement GetHeight() and GetOceanHeight(), expose your own UPROPERTY parameters. The plugin includes UYourOwnNoiseExample as a barebones starting point.

Video tutorial: a step-by-step custom noise walkthrough is on YouTube, see youtu.be/HpMExX-JcTY.

Key parameters available on UCustomNoiseParameter:

Ocean

OceanFloorHeight (0.015), OceanFloorBaseHeight (-0.1), OceanFloorScale (1.0), OceanFloorOctave (5), OceanFloorLacunarity (2.5), OceanFloorPersistence (0.4), OceanFloorWeight (2.0), OceanFloorWeightOctave (10), OceanFloorWeightScale (0.5), OceanFloorWeightPower (256.0).

Mountains

MountainHeight (0.5), MountainHeightPower (1.2), MountainScale (0.15), MountainOctave (8), MountainLacunarity (1.5), MountainPersistence (0.7), MountainWeight (1.5), MountainWeightScale (0.0025), MountainWeightPower (10), MountainTemperatureReduction (0.35).

Hills

HillHeight (0.1), HillScale (0.5), HillOctave (8), HillLacunarity (2.3), HillPersistence (0.4).

Beaches

BeachMask (8), BeachMaskOffset (3.75), BeachMaskWeight (1), BeachHeight (0.001), BeachScale (1).

Climate

TemperatureOffset, TemperatureHeightReduction (2), TemperatureHeightReductionPower (1.2), HumidityOffset, HumidityScale (1).

Warp

WarpIntensity (0.01), WarpScale (10), Warp2Scale (100), bIgnorePlanetaryHeightmap.

Moon-specific (when EWorldGenerationType::Moon)

CraterFrequency (1), CraterOctave (8), CraterLacunarity (1.25), CraterPersistence (0.75), CraterHeightMultiplier (1), CraterSize (8), CraterRimHeight (15), CraterRimOctaveLimit (3), CraterRimPower (4), CraterWarp (1), CraterWarpFrequency (1), CraterWarpOctave (4).

Noise Volume

To add procedural noise overrides in a specific region:

  1. Right-click in content browser → Blueprint Class → search "Noise Volume".
  2. Drag the volume into your level. Its details panel mirrors the Root's noise tab.
  3. Open the Root, go to Volumes Tab, click + next to the Noise Volume list and assign your volume.
Scale recommendation: "You're going to have to scale the NoiseVolumeBp up by a lot, recommend at least 28000 or 5000000 on all axes for it to affect a large area."

GPU compute noise New

The WorldScapeCompute module ships GPU compute shaders that generate noise on the graphics card. Use this when CPU noise generation becomes a bottleneck (very high-detail planets, real-time terrain deformation, kilometer-radius streaming).

Capture. GPU vs CPU noise comparisoncapture to add

Heightmap system

Heightmap volumes apply external textures to your terrain as decals, localized via AHeightMapVolume, or wrapping the entire planet via the Root's planetary heightmap. The textures live in UHeightMapVolumeData data assets that can be reused by multiple volumes.

Channel layout

A UHeightMapVolumeData asset holds two texture references and exposes six addressable mask channels:

Texture slotRGBA
HeightMapHeightTemperatureHumidityAlpha (mask for R/G/B)
HeightMapOceanOcean Height,,Ocean Alpha

EWSHeightMask (six values) addresses each channel: Height, Temperature, Humidity, Alpha, OceanHeight, OceanAlpha.

Sampling & tiling

EHMSamplingMethod (set per-volume in SamplingMethod):

  • Nearest, pixel-perfect, fast
  • Bilinear, smooth interpolation (default)
  • Bicubic, smoothest, costs more samples

EHMTilingMethod is configured on the data asset, separately for X and Y, separately for the main and ocean textures (HeightXTiling, HeightYTiling, OceanXTiling, OceanYTiling, default Wrap):

  • Wrap, tile beyond UV 0-1 (good for repeating patterns / planetary wrap)
  • Clamp, clamp to edge pixel beyond UV 0-1 (good for one-shot decals)
  • Mirror, mirrored repetition

The UHeightMapVolumeData data asset

Right-click in content browser → WorldScape tab → HeightMap Volume Data. The asset is split into three property categories:

Category Texture

PropertyTypePurpose
HeightMapTSoftObjectPtr<UTexture2D>Main texture (R/G/B = height/temp/humidity, A = mask).
HeightMapOceanTSoftObjectPtr<UTexture2D>Optional second texture (R = ocean height, A = ocean mask).

Category TextureInfo

PropertyDefaultPurpose
HeightXTiling, HeightYTilingWrapTiling mode for the main texture, X and Y axis independently.
OceanXTiling, OceanYTilingWrapTiling mode for the ocean texture.
bIgnoreHeightMapfalseSkip the height channel even if the texture is present.
bIgnoreTemperaturefalseSkip the temperature channel.
bIgnoreHumidityfalseSkip the humidity channel.
bIgnoreAlphafalseSkip the main alpha mask.
bIgnoreOceanHeightMapfalseSkip the ocean-height channel.
bIgnoreOceanAlphafalseSkip the ocean alpha mask.

Category TextureInfo · CustomResolution

Per-channel maximum sample resolution caps (in pixels). 0 = no limit (use the full texture resolution).

PropertyDefaultPurpose
MaxHeightResolution0Cap the height-channel sampling resolution.
MaxTemperatureResolution0Cap temperature.
MaxHumidityResolution0Cap humidity.
MaxAlphaResolution0Cap the main alpha.
MaxOceanHeightResolution0Cap ocean height.
MaxOceanAlphaResolution0Cap ocean alpha.

Functions on the asset

FunctionEditor onlyPurpose
Generate()yesThe main button. Auto-configures the source textures and rebuilds all internal sample arrays, see workflow below.
CleanData()yesEmpty all StoredHeightMapData / StoredTemperatureData / etc. Use before re-Generate to force a clean rebuild.
BuildTexture(UTexture2D*)noSample a specific texture into the main channel arrays.
BuildOceanTexture(UTexture2D*)noSample into ocean channel arrays.
GetStoredValue(int Index, EWSHeightMask)noDirect read of the sampled uint16 array.
IsValidIndex(int, EWSHeightMask)noBounds check.
MaskSize(EWSHeightMask)noResolution of the sampled array for that channel.
Width(EWSHeightMask) / Height(EWSHeightMask)noPer-channel sampled width/height.

Texture import workflow

The Generate() function does the heavy lifting automatically. You don't need to manually adjust the texture's compression / mip / sRGB settings, Generate() sets them for you, samples the pixels into typed arrays, then restores the original texture configuration.

What Generate() changes on the source texture (briefly, then restores):
  • PowerOfTwoMode = PadToPowerOfTwo, non-power-of-two textures are padded automatically.
  • CompressionSettings = TC_HDR, raw 16-bit-float pixel access.
  • MipGenSettings = NoMipmaps, sample from the full-res mip.
  • SRGB = false, linear data.

Step-by-step

  1. Import your texture (PNG 16-bit recommended for height; 8-bit acceptable for masks).
  2. Right-click content browser → WorldScape tab → HeightMap Volume Data → name it (e.g. HMD_Crater).
  3. Open the data asset. Drop your main texture into HeightMap; optionally a second texture into HeightMapOcean.
  4. Set tiling per axis if you don't want defaults (Wrap for planetary wraps, Clamp for one-shot decals).
  5. Toggle bIgnore* flags to skip channels you don't need (saves memory).
  6. Click Generate. The asset's internal uint16 arrays fill with sampled values.
  7. Save the asset.

Source-specific tips

  • WorldMachine: export PNG 16-bit. Never use the (+1) offset option, it shifts the value range and breaks height interpretation.
  • NASA elevation tiles: usable directly as planetary heightmaps. Map the elevation range with PlanetaryMapHeight + PlanetaryAltitude on the Root.
  • Existing UE landscapes: use the WS Tools Landscape Export feature to convert.
  • Power of 2 isn't required any more, Generate() auto-pads via PadToPowerOfTwo. (However, power-of-2 sources still produce slightly cleaner sampling.)

Apply via a HeightMap Volume (localized)

  1. Create the data asset (previous section).
  2. Drag a HeightMapVolume blueprint into your level (right-click content browser → Blueprint Class → type "HeightMap"). Position and scale it where you want the decal.
  3. On the volume, set HeightMapData to your data asset.
  4. Toggle the channels you want active: Height, Temperature, Humidity, OceanHeight, plus optional HeightAlpha / OceanHeightAlpha masks.
  5. Configure per-channel ranges:
    • Height: MapHeight (texture value => cm), Altitude (base offset).
    • Temperature / Humidity: Min* & Max* (0-1).
    • Ocean: MaxOceanHeight & MinOceanHeight.
  6. Set OverrideHeight, true (default) replaces the underlying terrain height; false adds/subtracts on top of the existing noise.
  7. Optionally enable UseBlending + EdgeFalloff to soft-fade the volume's edges into the surrounding terrain.
  8. Open your WorldScapeRoot. In Category VolumesHeightMapVolumeList, click + and assign your volume.
  9. Make sure bEnableVolumes = true on the Root (master toggle for ALL volume types).
If the volume seems unresponsive after re-importing the texture, open its data asset and click Generate again, then restart the level (the Root caches volume data on init).

Planetary heightmap (the entire planet)

Distinct from local volumes: the Root has a built-in planetary heightmap that wraps the entire planet. All properties live in Category Noise · PlanetaryHeightmap and only show when GenerationType = Planet.

Master toggles

PropertyDefaultPurpose
bUsePlanetaryHeightMapfalseMaster toggle. Without this, all the rest is ignored.
PlanetaryHeightMapnullptrThe UHeightMapVolumeData data asset wrapping the planet (typically a single equirectangular texture).
SamplingMethodBilinearSampler used for planet-wide reads.
PlanetaryHeightMapBlendAdditionEPlanetaryHeightMapBlendType: Replace (DisplayName "Normal", replace procedural noise), Addition (DisplayName "Additional", add on top), Subtract.
PlanetaryBlendAlpha1Master blend amount (0-1) between procedural noise and the heightmap result.
bPlanetaryInvertMapBlendfalseInvert the blend direction.

Height channel

PropertyDefaultPurpose
bPlanetaryHeightfalseToggle the height channel from the planetary texture.
PlanetaryMapHeight800,000 (8 km)Texture value => world-space height. Default range is 8 km of vertical relief.
PlanetaryAltitude-1,000,000 (-10 km)Base altitude offset added on top of the sampled height. Default places the "zero" of the texture 10 km below sea level.
HeightBlendAlpha1Per-channel blend weight (0-1) for the height contribution.

Temperature channel

PropertyDefaultPurpose
bPlanetaryTemperaturefalseToggle.
PlanetaryMaxTemperature1Upper bound (0-1).
PlanetaryMinTemperature0Lower bound (0-1).
TemperatureBlendAlpha1Per-channel blend (0-1).

Humidity channel

PropertyDefaultPurpose
bPlanetaryHumidityfalseToggle.
PlanetaryMaxHumidity1Upper bound (0-1).
PlanetaryMinHumidity0Lower bound (0-1).
HumidityBlendAlpha1Per-channel blend.

Alpha & ocean

PropertyDefaultPurpose
bPlanetaryHeightAlphafalseUse the main texture's alpha as a mask (only shown when at least one of bPlanetaryHeight/Temperature/Humidity is on).
bPlanetaryOceanHeightfalseUse the second texture's R channel for ocean height.
PlanetaryMaxOceanHeight0Upper bound for ocean height remap.
PlanetaryMinOceanHeight0Lower bound.
bPlanetaryOceanHeightAlphafalseUse the second texture's alpha as ocean mask.

Step-by-step setup

  1. Build a UHeightMapVolumeData asset (see Texture import workflow) using an equirectangular projection of your planet.
  2. On the Root, set GenerationType = Planet and confirm the planetary section appears.
  3. Enable bUsePlanetaryHeightMap.
  4. Assign the data asset to PlanetaryHeightMap.
  5. Choose the blend mode: Replace for pure heightmap (no procedural noise), Addition to add to procedural, Subtract for inverted.
  6. Toggle the channels you need (bPlanetaryHeight, bPlanetaryTemperature, etc.).
  7. Tune PlanetaryMapHeight (texture range in cm) and PlanetaryAltitude (base offset). Defaults are 8 km of relief, anchored 10 km below sea level, adjust for your planet's geology.
  8. Use PlanetaryBlendAlpha for global heightmap-vs-noise mixing, and per-channel *BlendAlpha for fine control.

Blueprint API

  • GetPlanetaryDataFromPosition(FVector Position) → float, sample the planetary height at a 3D location (BlueprintCallable, Category "Info").
  • GetPlanetaryCoordinate(DVector Position) → FDVector2D. ECEF → UV (for custom sampling code).
Mixing planetary heightmap + procedural noise: set PlanetaryHeightMapBlend = Addition, lower PlanetaryBlendAlpha to 0.5-0.7 to let the noise show through. Or use per-channel: keep HeightBlendAlpha = 0 to disable the heightmap's contribution to height while still using its temperature/humidity/ocean channels for biome control.
Hybrid worlds: recent versions also let local HeightMapVolume actors layer on top of the planetary heightmap (e.g. a global Earth texture + a hand-painted Mt. Everest volume).

Heightmap Editor Beta

The WS Tools toolbar exposes an in-engine heightmap editor, sculpt textures with a brush, apply filters (blur, noise, erosion), resize, save, view in 3D. See WS Toolbar for the full feature list.

Volumes

Volumes are localized modifiers that override the Root's terrain in their bounding region. All inherit from AVolumeInterface and are managed via the Root's Volumes tab.

Shared base, AVolumeInterface

Every volume listed below inherits these properties (Category Defaults):

PropertyTypeDefaultPurpose
IsEnabledbooltrueToggle the volume on/off without deleting it.
Priorityint320Sorting priority when multiple volumes overlap.
AlignToPlanetSurfaceboolfalseFor planets, align the volume's transform to the surface tangent at its location.
SurfaceAlignmentRotationOffsetFRotator(0,0,0)Extra rotation applied after surface alignment (gated by the flag above).

Plus the WS_ForceRefresh() BlueprintCallable function that flags the volume as dirty for re-application.

HeightMap Volume (AHeightMapVolume)

Apply an external heightmap as a localized decal on the terrain. Workflow covered in Heightmap · Apply via volume; full property list:

PropertyTypeDefaultPurpose
HeightMapDataUHeightMapVolumeData*nullptrThe data asset holding the textures + channel config.
SamplingMethodEHMSamplingMethodBilinearPer-volume sampler (Nearest / Bilinear / Bicubic).
OverrideHeightbooltrueReplace the underlying height (default), instead of adding/subtracting.
EdgeFallofffloat (0-0.5)0Soft edge falloff, how much of the volume's edge fades into the surrounding terrain.
UseBlendingboolfalseEnable curve-based blending.
BlendingFWSHeight_Blend(default)Blend curve config when UseBlending is on.
HeightboolfalseToggle the height channel (Red).
TemperatureboolfalseToggle the temperature channel (Green).
HumidityboolfalseToggle the humidity channel (Blue).
HeightAlphaboolfalseUse the texture's alpha as a mask for the three above. Hidden until at least one channel is on.
OceanHeightboolfalseToggle the ocean-height channel (second texture, Red).
OceanHeightAlphaboolfalseUse second texture's alpha as ocean mask.
MapHeightfloat10000Texture value => world-space height in cm. Hidden when Height is off.
Altitudefloat0Base altitude offset added on top of the sampled height.
MaxTemperature, MinTemperaturefloat (0-1)0Range remap for the temperature channel.
MaxHumidity, MinHumidityfloat (0-1)0Range remap for the humidity channel.
MaxOceanHeight, MinOceanHeightfloat0Range remap for the ocean-height channel.

BlueprintCallable methods on the volume: CanSample(), CanSampleMask(EWSHeightMask), IsHeightDataValid(), GetData(FVector2D UV, EWSHeightMask)float.

Noise Volume (ANoiseVolume)

Adds procedural noise generation in a region, blended with the global noise. Properties (Category Noise):

PropertyTypePurpose
WorldScapeNoiseUWorldScapeNoiseClass*The noise generator to apply locally (subclass of UWorldScapeNoiseClass).
NoiseScalefloatWider value = wider details (same semantics as the Root's NoiseScale).
NoiseIntensityfloatIntensity in cm, higher value = higher mountains.
NoiseHeightOffsetfloatHeight offset added on top of the noise output.
NoiseOffsetFVector3D offset applied to the noise sampling space.
Seedint32Random seed for this volume's noise (independent of the Root's Seed).
EdgeFallofffloatSoft falloff at the volume's edge.
Scale recommendation: "You're going to have to scale the NoiseVolumeBp up by a lot, recommend at least 28000 or 5000000 on all axes for it to affect a large area."

Hole Volume (ATerrainHoleVolume)

Cuts holes in the terrain, for caves, cliffs, hand-built openings. Inherits the base AVolumeInterface properties only; data lives in its UTerrainHoleVolumeData data asset.

  1. Right-click content browser → Blueprint Class → type "hole".
  2. Apply under the Root's Volumes tab.
  3. A Foliage Mask Volume can overlap to remove foliage from inside the hole.
If the hole has no visual effect: "you may have to edit the master material for the WorldScape manager and multiply the alpha vertex color at the end of the opacity mask lerp."

Foliage Mask Volume (AFoliageMaskVolume)

Mask specific areas to clear or allow foliage. Properties (Category Defaults):

PropertyTypeDefaultPurpose
UseBlendingbooltrueSoft-blend the mask edge instead of a hard cut.
BlendFallofffloat (0-1)0.33How wide the soft-blend region is.
MaskAllboolfalseApply to every foliage entry (ignore FoliageLayerMask).
FoliageLayerMaskTArray<int>[]Layer integers this volume affects. Must match foliage's FoliageLayer.
SpawnVolumeboolfalseInverted mode: when true, foliage with the right layer + SpawnOnlyInVolume set is allowed to spawn here (instead of being masked out).

See also Foliage layer masking for the integer-matching rules.

Collision Invoker Volume Beta

Generates isolated collision for WorldScape terrain in a region, via a collision actor that auto-attaches to the Root.

ParameterTypePurpose
Max ResolutionintLimits triangle count to avoid editor performance hits.
Quad Size TargetfloatControls collision mesh resolution based on volume size.
Quad Size Auto CorrectionboolAdjusts target resolution if the volume is too large to maintain reasonable performance.
Triangle SizefloatTriangle size in WorldScape mesh generation.

Place the volume, click Make Collision, ensure assignment to the Root.

Volume Pooling Beta

"Volume pooling is a method that allows you to keep the number of active volumes low in the field. You can at any time in C++ or Blueprint request a volume from the worldscape root, which will be a volume that is part of the pooling list, then configure it and place it where you want."

Foliage

WorldScape foliage is multithreaded, instanced, biome-aware. You don't paint anything, you describe what should grow where, and the plugin places it during terrain generation.

Foliage Asset

UWorldScapeFoliagesAsset is the basic unit. Right-click → WorldScape tab → Foliage Asset.

Visuals

  • StaticMesh, the mesh to instance.
  • OverrideMaterial array, replace the mesh's materials.
  • Is_NaniteMesh, toggle Nanite for high-poly foliage.
  • bCastShadows, bReceiveDecal, bCastFarShadow, bAffectDynamicIndirectLighting, bAffectDistanceFieldLighting, bNeverDistanceCull, bCastDistanceFieldIndirectShadow, bSelfShadowOnly.

Placement

  • Offset (FVector), position offset.
  • MinScale, MaxScale, size variation (defaults 0.8-1.2).
  • bAlignedToGround, snap to terrain.
  • bRandomRotation, rotation variation.
  • GroundRotationInfluenceMin/Max, slope alignment (defaults 0.35-0.6).

Spacing & density

  • FoliageSectorSize (default 2000), generation sector size.
  • bUsePoissonDisc, use Poisson distribution.
  • PoissonDiscDensity (1-200). Poisson density.
  • FoliagesCount (1-30000), spawn count per sector.
  • FoliageCullDistanceMultiplier (default 0.5x), cull distance.

Behavior

  • bSpawnActorInstead + ObjectToSpawn, spawn full actors. Marked obsolete in source (DisplayName ends with "(Obselete)" sic), prefer Foliage Blueprint for scripted behavior.
  • bRequiresDeterminism, consistent placement (use for trees that gameplay refers to). Disable for grass/rubble to enable parallelization.
  • SpawnInWater, the EFoliageWaterSpawn enum: Ignore, OutsideWater, InWater.
  • FoliageLayer (-1 = use collection default; ≥ 0 = override).
  • SpawnOnlyInVolume, bGenerateOnServer (defaults to true), bUseFoliageNoiseMask.
About Poisson Disc: the bUsePoissonDisc property exists but is hidden from the editor in the current build (EditCondition = "false"). The default placement uses sector-based randomization with the FoliagesCount count.

Foliage Collection

Right-click → WorldScape tab → WorldScapeFoliageCollection. A collection groups multiple foliage assets that share constraints.

  1. Open the collection. Add foliage assets to the foliage list.
  2. Set shared constraints (elevation, temperature, humidity).
  3. In the Root's Foliage tab, click + to add the collection to the spawn list.
Above-water foliage: "the elevation should be set by whatever value your ocean level is set at, if using above-water type foliage."

Foliage Cluster

Spawn dense clumped objects (grass, rocks) with minimal perf impact, resembles UE's Hierarchical Instanced Static Mesh.

  1. Right-click → WorldScape tab → Foliage Cluster.
  2. Open the cluster, click + on Foliage Cluster Unit List.
  3. Sector size + count dictate spawn area + density. With dense meshes, start with smaller foliage counts.

Biome constraints

"Slope is based on the dot product between the normal of the ground and the up vector, capped between 0 and 1. This allows constraining generation to only planar surfaces or only cliff sides.

Temperature & Humidity influence generation through noise-derived climate data.

Spawn in Water: if true, force foliage to spawn inside water bodies (when ocean height > land height); if false, force outside.

Align to Surface + Ground Influence: aligns foliage to ground normal. Ground Influence customizes how much, the value is randomized between min and max.

Note: random rotation is not compatible with align to surface."

Per-foliage constraints (when bOverrideCollectionConstraint is true):

ConstraintTypeRange
ElevationFWorldScapeFoliagesContraintheight min/max in cm
TemperatureFWorldScapeFoliagesContraintNormalized0-1
HumidityFWorldScapeFoliagesContraintNormalized0-1
SlopeFWorldScapeFoliagesContraintNormalized0-1

Layer masking

Three mechanisms to control where foliage appears:

  1. Define Layers Foliage: set a FoliageLayer integer on a collection or foliage.
  2. Exclude Layers Foliage: place an influencer in your level, specify the layer numbers to exclude in the influencer menu in the Root.
  3. Noise Mask: the Use Noise Mask parameter spawns foliage inside a procedurally generated mask.
Foliage Volume: the integer in your foliage volume mask must match the integer of your foliage instance in the collections. "Make sure each foliage has a different number to isolate certain kinds."

Foliage Baker Beta

Converts procedurally-generated WorldScape foliage into standard Unreal Foliage actors or HISM components, useful for shipping or for handing terrain over to artists.

ParameterTypePurpose
WorldScape Root ActordropdownSource of procedural foliage
WS Foliage Baker Bound VolumevolumeDefines the bake region
Tile CapturesliderHorizontal/vertical tile divisions, more = more localized sections
Process Tile DelayfloatDelay between tile bakes

Workflow: launch from the WS Tools toolbar → position over procedural foliage → Launch Foliage Baker Tools → adjust tile capture → Start Capture → don't move the camera → pick HISM or Foliage output.

Foliage Collision Pooling (FCP) Beta

"Foliage Collision Pooling is a new method for foliage collisions to address micro-freezing issues when spawning large amounts of foliage. This allows all foliage to spawn without collision, then automatically moves the collision around the player, resulting in a significant performance gain when spawning foliage, especially at great distances. This system only works on the client side."

Configure on each foliage asset:

PropertyTypePurpose
CollisionPooling_ComputeTypeEWS_FCP_TypeComputeAuto / Near / Far, controls when collision is computed for a foliage cell relative to the player.
CollisionPooling_DataFWS_FCP_PoolingDataContains BasePoolSize (pool capacity, default 100), MinimalScale (skip collision for foliage scaled below this), and a full BodyInstance for collision channels & responses.

Materials (5.0+)

Most material controls live on the Root. Five color layers + surface noise drive the entire planet appearance, blended by the Layer tab.

The shipped materials are placeholders, encouraged for prototyping, not for shipping. Replace with your own when polishing.

Color layers

LayerRole
BottomCoastline aspects of the landscape.
Mid Color Layer 1 (humid)Colors 1-3: temperate grass. Color 4: cold tundra near snow edge. Color 5: savanna + desert transition.
Mid Color Layer 2 (dry)Colors 1-2: sand. Color 3: rock on mountains/dry. Color 4: sand tint. Color 5: no effect.
TopSnow caps / overall snow color.
Surface noiseDetail textures visible from space.

Layer tab controls the height and sharpness transition for bottom/mid/top primary layers.

Foliage doesn't react to material changes, modify foliage materials separately.

Legacy 5-layer materials

For UE 4.26-4.27 builds and older WorldScape versions:

  • Sand, deserts & when height < 0.
  • Grass, default layer.
  • Stone, high height (mountains).
  • Cliff, high slopes; tunable via Automask parameters.
  • Snow, low temperature + low slope, or very low temperature.

Each layer needs three textures: Color (RGB albedo), Normal, and OMRH. Red=Occlusion, Green=Metal, Blue=Roughness, Alpha=Height.

Set RatioScale to your PlanetSize.

Material fix, floating point errors

If you see floating-point artifacts on the surface:

  1. Open the WorldScape material functions folder.
  2. Find MF_SLM_Layer_Planet.
  3. Locate the planet location parameter and the Rotate with Planet parameter.
  4. Right-click planet location → Promote to Double.
  5. Set Rotate with Planet to false.

Grid & Snap spawning Experimental

Two systems for placing pre-built content (POIs, buildings, roads, props) on procedural surfaces.

Grid Spawning

The grid system has its own dedicated chapter with full workflows, the 6 spawn-type modes, placement parameters, constraints, LOD proxies, exclusion zones and 5 worked recipes:

Grid spawning & streaming, complete guide

That chapter covers both entry points (Root's global Grid_BaseSpawnData and the localized AWorldScape_GridSpawnerVolume), the UWorldScape_GridDataAsset structure, the FWS_Grid_SpawnParams constraints, and dedicated-server tuning.

Snap Spawner

"A derivative of the Grid Spawner, this one places an actor directly on the surface of the planet. It spawns elements (StaticMesh and actors with-or-without serializer) maintaining structure, snaps elements to terrain surface, and manages spawn quantity directly with a manager."

Key parameters

PropertyTypePurpose
DataTypeEWSSnapDataTypeManualData, SnapData, or GridData (3 values, not 2, ManualData uses the inline arrays in the actor).
SnapDataAssetUWorldScape_SnapDataAssetBuilding / road collection data
ExtentFVectorSpawn volume (default 1000,1000,1000)
ComputeCullingboolLOD culling
WS_ValidTagFNameTag the Snap Spawner looks for on Roots (default WS_Planetary)
AutoGet_NearWSboolAuto-find the nearest Root
Use_PendingSpawnboolAsync/streamed spawning
PendingSpawnActor_PerTickintThrottle (default 10)
PendingSpawnStaticMesh_PerTickintThrottle (default 2)

Editor functions (when WITH_EDITOR): ViewFlat() for debug visualization, Simulate() to preview, Clear() to reset.

Physics & Movement

Standard UE characters can't walk on a sphere. WorldScape ships a custom MovementComponent and a gravity API to fix that.

Gravity Value Beta

"Gravity Value is a simple system that allows you to calculate the gravity at a given point on planets and flat worlds. This allows you to directly obtain a usable value to determine the gravity at a given location. Currently, no force is applied to objects, you must obtain this value yourself from the planet or from the subsystem."

Use the subsystem call:

FVector GravityDir; double Force; FVector G = Subsystem->WS_GetActualGravityFromLocation( Location, GravityDir, Force);

WorldScapePlayer

The plugin provides a ready-to-test player Blueprint at WorldScape/Content/Ressources/Mesh/Player/WorldScapePlayer.uasset (note: "Ressources" with two s's, literal folder spelling in the plugin). Use it as-is to walk on a planet, or as a reference for your own custom character.

Custom character & MovementComponent

"A custom MovementComponentCharacter is required for planetary gameplay, it enables proper gravity/rotation when a character moves on a planet surface. The native UnrealEngine MovementComponentCharacter doesn't allow you to do this."

Recipe:

  1. Subclass UCharacterMovementComponent.
  2. Override PhysicsRotation to align the character's up-vector to WS_GetCurrentSurfaceUpVector().
  3. Override gravity application: each tick, query WS_GetActualGravityFromLocation and apply the resulting force as your acceleration.
  4. In your Character class, set the new MovementComponent class via the CharacterMovementComponentClass override in the constructor.
  5. For multiplayer, ensure replication of the up-vector or recompute it server-side via the same subsystem call.
Capture, custom MovementComponent BP graphcapture to add

Multiplayer

WorldScape is officially marketed as "Network Replicated: Yes (DedicatedServer & ListenServer)". Read the next paragraph carefully, that statement is true but means something different from what most UE developers expect.

The fundamental contract: WorldScape ships with zero UPROPERTY(Replicated), zero UFUNCTION(Server|Client|NetMulticast) RPCs, and zero bReplicates = true actors. The plugin's "multiplayer" is deterministic local generation from a shared Seed. Each peer (server and clients) regenerates the same terrain, foliage and grid spawns independently, in lock-step, by reading the identical Seed + identical noise asset + identical world parameters. No vertex data, no foliage instance, no spawned mesh ever crosses the wire.

This is by design and matches a comment found in the source: // Pourquoi répliquer l'actor ? ("Why replicate the actor?") in WorldScapeRoot_Main.cpp. The plugin is netmode-aware everywhere, exposes per-side knobs, and knows the difference between dedicated server, listen server, client and standalone, but it does not push state across the wire.

What you must replicate yourself

Anything that varies at runtime must be replicated by your own code, then applied to AWorldScapeRoot on each peer. Typical replicated state in a WorldScape MP game:

  • Seed, the single most important value. If your design has a "world seed" that changes between matches, replicate it via your AGameState and apply it to each Root in OnRep_Seed.
  • Player-built / persistent terrain modifications (custom volumes, dynamically spawned holes, height edits).
  • Any custom GameMode flags that drive WorldScape regeneration (season, time of day affecting biomes, etc.).

Determinism

WorldScape's "multiplayer" works because every peer runs the same procedural code path on the same inputs. There is no syncing of vertex positions or foliage instances over the wire. Understanding which inputs matter is the key to a stable MP build.

The chain of derivations

Determinism flows in one direction:

Input

Root.Seed + noise asset + per-Root noise parameters

Drives

Terrain noise (height + temperature + humidity + watermask + foliagemask)

Defines

The LOD sector pyramid & sector positions in world space

Drives

Foliage seed = FMath::Fmod(DotProduct(Sector.Position, FVector(Sector.Size + 100×CollectionID, 2000×FoliageID, 50000×FLID)), 2×109)

Drives

Per-instance position, scale, rotation

Grid streaming uses an analogous chain, cell coords + per-asset SeedOffset drive the spawn seed (Root.Seed doesn't directly appear in the grid seed math either).

Note: Root.Seed doesn't appear in the foliage or grid seed formulas at all. Both depend on position, which transitively depends on the terrain noise. Because the terrain noise depends on Root.Seed, the chain is preserved, but if you ever change foliage or grid in code expecting Root.Seed to feed in directly, it doesn't.

What MUST match across peers

InputWhy
Root.Seed (int32, default 10)Drives noise → terrain shape → transitively, sector positions → foliage / grid placement.
Noise asset reference + parameters on the RootDifferent noise = different terrain shape, even with same seed.
Foliage Collections array (order matters)The foliage seed includes FoliageCollectionID and FoliageID, reordering collections shifts every foliage placement.
Grid DataAssets + per-asset SeedOffsetSame reasoning, the grid seed includes the asset's SeedOffset.
Volumes placed in the level (HeightMap, Hole, etc.)Level-loaded volumes are identical on every peer "for free" because every peer loads the level. Dynamic volumes you spawn at runtime must be spawned on every peer.
PlanetScale, NoiseScale, NoiseIntensity, NoiseOffset, LodResolution, MaxLod, TriangleSize, HeightAnchorAll Root parameters that affect terrain or LOD geometry. If your design flips them at runtime, replicate them.

Replicating Root.Seed in your own code

The Root's Seed is a plain non-replicated UPROPERTY. If your design requires changing it at runtime (per-match seeds, server-controlled regen), replicate it via your AGameState or your own actor:

// In your GameState header UPROPERTY(ReplicatedUsing = OnRep_WorldSeed) int32 WorldSeed = 10; UFUNCTION() void OnRep_WorldSeed() { if (AWorldScapeRoot* Root = ..) { Root->Seed = WorldSeed; Root->WS_ForceRegenerate(); } }

About the bRequiresDeterminism foliage flag

The flag (WorldScapeFoliagesInterface.h:69, default false) selects which generation pipeline runs for that foliage:

  • TrueGenerateVegetationForSector_Batched. Sequential. Source comment: "Batched Noise Version. Only batch MAIN point noise, keep everything else IDENTICAL to original".
  • FalseGenerateVegetationForSector_FullParallel. Uses ParallelFor across points. Random values are pre-drawn sequentially before parallelization (RandomValues[p] = Stream.FRand(); in a single-threaded loop, indexed read inside the lambda).

The author's verbatim comment, directly above the property declaration:

"If true, foliage placement will be deterministic (same seed = same placement). Set to false for grass/small rocks where position doesn't matter, enables heavy parallelization. Set to true for trees/large rocks where consistent placement is important."

Take that at face value: follow the author's recommendation and set bRequiresDeterminism = true for any foliage where position must match across regenerations or peers (trees, large rocks, anything gameplay-significant). For purely cosmetic grass and small rubble where exact position is invisible, leave it false for the parallel speed-up.

What CAN go wrong (sources of cross-peer divergence)

When two peers desync visually or physically, the cause is almost always one of:

  • Different Root.Seed on each side. The single most common cause. Verify in PIE with Play As Listen Server + Play As Client by logging the seed on both.
  • Different noise asset reference, e.g. one side has a redirector, the other has the renamed asset.
  • Foliage collection order differs, e.g. you added an entry to Foliages[] at index 0 on the server but appended on the client. Every FoliageCollectionID downstream shifts.
  • One side missing a placed volume, usually because of streaming-level differences. Volumes are seen "for free" only if both peers loaded the same sub-level.
  • Dynamically spawned volumes / actors that aren't replicated. If you spawn a HeightMapVolume at runtime on the server but not on the client, the client doesn't see the terrain modification.
  • Different PlanetScale or noise parameters after a runtime tweak that wasn't replicated.

Grid-specific dedup: Grid_CheckSpawnBySeed

Default true. Maintains a per-side TSet<int64> of already-spawned instance seeds to deduplicate items at cell boundaries (where two adjacent cells could try to spawn the same instance). Leave on for MP, turning it off can cause ghost / double spawns at cell seams that may differ between peers.

Dedicated server behavior

Auto-disabled paths (always off on DS, no flag to flip)

  • GPU noise, the server has no RHI. Even if bUseGPUNoise = true, the server falls back to the CPU path silently.
  • Indirect instanced terrain renderer, never used on DS.
  • Foliage Collision Pooling (FCP), the dynamic per-pawn collision swap-in. Use bCollision = true + bGenerateOnServer = true on foliage instead.
  • Grid SMProxy visualization, the LOD swap-mesh layer is no-op on DS.
  • Subsystem auto-tracking, WS_Start_AutoGetNearest()'s timer never starts on DS (or listen).
  • Material Parameter Collection sync, the auto-update of WS_Surface_UpVector, WS_Planet_Origin, WS_Planet_Size, WS_Planetary, WS_Valid, WS_Flat_Origin is never run on DS.

Auto-enabled paths on DS

  • All-player collision generation, collision is built around every connected player's pawn (not just the local one).
  • All-player grid streaming, grid loads cells around every connected player's pawn.
  • Multiplied volume pools, pre-allocated pool sizes are larger on DS to service many players' regions concurrently.

Per-side performance knobs (on AWorldScapeRoot)

PropertyDefaultPurpose
DisableFoliageDedicatedServerfalseMaster kill switch for ALL foliage on DS. Skip every foliage entirely on dedicated.
Grid_MaxSpawnPerSecond512Spawn throttle for client / listen / standalone.
Grid_MaxSpawnPerSecond_OnDedicated1024Spawn throttle for dedicated server (higher because no rendering competition).
Grid_MaxDestroyPerSecond1024Despawn throttle, non-DS.
Grid_MaxDestroyPerSecond_OnDedicated2048Despawn throttle, DS.
Grid_SkipStaticMeshOnDedicatedfalseSkip ALL StaticMesh/CollectionStaticMesh/Foliage grid types on DS (keeps actor types).
Grid_SkipAdjacentCellOnDedicatedfalseShrink loaded grid neighborhood from 9 cells to 1 on DS.
Grid_SimulateDedicatedfalsePretend you're DS even on a client (debugging).
VolumePooling_EnabledfalseMaster switch for client/listen/standalone pooling.
VolumePooling_Enabled_OnDedicatedtrueIndependent switch for DS pooling.
Heightmap_Pooling_Dedicated_Multiplier3.0DS pool size multiplier (heightmap volumes).
HFoliage_Pooling_Dedicated_Multiplier3.0DS pool size multiplier (foliage mask volumes).
Hole_Pooling_Dedicated_Multiplier3.0DS pool size multiplier (hole volumes).
bGenerateCollisionForAllPlayerfalseForce the all-player collision branch even on a pure client (useful for split-screen-like setups).

Per-asset DS opt-in / opt-out

  • UWorldScape_GridDataAsset.SpawnableOnDedicated (default true), per grid data asset. Set to false for purely-cosmetic items.
  • AWorldScape_SnapSpawnerActor.SpawnOnDedicated (default false!), you must opt in for snap spawns to exist server-side.
  • UWorldScapeFoliagesInterface.bGenerateOnServer (default true, per foliage), turn off for visual-only grass.

Cooking implications

The plugin uses IsRunningDedicatedServer() guards around several SoftClass.LoadSynchronous() calls, meaning soft-class assets that aren't already loaded won't be force-loaded on DS. If your gameplay depends on certain actor classes existing on the server, ensure they are cooked into the server build via Project Settings → Asset Manager or +ServerAdditionalAssetDirectoriesToCook. ProxyMesh and AdditionalComponentClass paths are skipped on DS entirely, their assets can be omitted from the server cook.

Listen server quirks

Listen server is the most asymmetric netmode. Document this carefully if you ship a listen-server-based MP mode.
  • Collision: all-player branch, ✅ same as DS
  • Foliage Collision Pooling: ✅ runs on listen (unlike DS)
  • Subsystem auto-tracking: ❌ does NOT run on listen (gated to NM_Client || NM_Standalone)
  • Material Parameter Collection sync: ❌ does NOT run on listen
  • Grid streaming tick: ⚠ neither the DS branch nor the client branch matches NM_ListenServer, grid streaming may not fire on the listen-server host. Workaround: call Subsystem->WS_Start_AutoGetNearest() manually after BeginPlay, and audit the result. If grid items are missing for the host, this is the cause.

Per-side feature matrix

SystemDedicatedListenClientStandalone
Terrain mesh (CPU noise)
Terrain mesh (GPU noise)
Indirect instanced terrain
Foliage (default)✅ if bGenerateOnServer
Foliage Collision Pooling (FCP)
Grid items✅ per-asset SpawnableOnDedicated⚠ may not stream
Grid SMProxy visualization
Volume pooling✅ (3× pool)
Snap spawneronly if SpawnOnDedicated=true
Subsystem auto-tracking
MPC parameter sync

Foliage in MP

  • bGenerateOnServer (per foliage, default true), keep ON for trees with collision, turn OFF for purely-visual grass to save DS CPU.
  • DisableFoliageDedicatedServer (Root), nuclear option, kills all foliage on DS.
  • bRequiresDeterminism (per foliage, default false), per the author's source comment, set to true for trees/large rocks where consistent placement matters across regenerations / peers. See Determinism.
  • bCollision (per foliage) + bGenerateOnServer = true, required combination for server-authoritative shooting / movement against foliage trunks.
  • FCP is client-only, do not rely on it for server-authoritative gameplay against foliage.
For cross-peer foliage matching: the four cross-peer inputs are Root.Seed, the noise asset, the noise parameters, and the foliage collection ordering. The bRequiresDeterminism flag is an additional safety net the author recommends for gameplay-significant foliage, per the source comment, set it to true for trees and large rocks.

Grid spawning in MP

The grid system is the most server-aware of all systems. Both the server and clients independently compute the same grid items at the same locations from the shared seed, then each side decides whether to spawn them based on SpawnableOnDedicated + Grid_Skip* flags.

Watch out: if you make your spawned grid actor bReplicates = true in your own code, you'll end up with two copies on each client, one from the local grid spawn, one replicated by the server. The standard fix:

  • For cosmetic grid actors (rocks, grass clumps, billboards): leave bReplicates = false and let each peer spawn locally. Default behavior.
  • For interactable / persistent grid actors (lootable chests, NPCs): set SpawnableOnDedicated = true, mark the actor bReplicates = true, AND set bNetLoadOnClient = false on the actor so the client doesn't double-spawn. Server spawns + replicates as canon; clients receive the replicated copy and skip the grid path.

Collision invokers in MP

The UWorldscapeCollisionInvoker component is local-only (not replicated). It registers itself with the per-world UWorldscapeSubsystem in BeginPlay. In MP:

  • Each replicated pawn carries a component instance on each side where the pawn exists.
  • Server: every player's pawn drives collision generation around it (because all replicated pawns exist on the server).
  • Client: by default, only the local pawn exists in full (other players' pawns may be culled by relevancy). Use bGenerateCollisionForAllPlayer = true if you need clients to generate terrain collision around other players too.

Subsystem in MP

UWorldscapeSubsystem per-side caveats:

  • WS_Start_AutoGetNearest() only schedules its 1Hz tick on NM_Client or NM_Standalone. It is silently a no-op on dedicated and listen servers.
  • Delegates (FWS_OnNearestChanged, FWS_OnNearestNULL, FWS_OnWorldScapeRegistry, FWS_OnWorldScapeUnRegistry) are local Blueprint events, not RPCs.
  • Get_NearWorldScapeFromLocation() is netmode-agnostic, you can call it on the server.
  • For server-authoritative gameplay that needs gravity / surface up vector, do NOT rely on the MPC. Call WorldScapeRoot->WS_GetGravityFromLocation(..) or the subsystem's WS_GetActualGravityFromLocation(..) directly.

Sample multiplayer setup (recipe)

The plugin ships zero MP sample content. No multiplayer level, no replicated character template, no example GameMode. You'll build your own from scratch, here's the minimum recipe.
  1. Create a UE Third-Person template project, enable WorldScape.
  2. Drop an AWorldScapeRoot in your level. Set GenerationType = Planet, pick a noise asset, set Seed to your design's value.
  3. Open BP_ThirdPersonCharacter, add a UWorldscapeCollisionInvoker component on the root.
  4. In your AGameState (or AGameMode if you don't have a custom GameState), add a UPROPERTY(ReplicatedUsing=OnRep_WorldSeed) int32 WorldSeed; and propagate it to the Root in OnRep_WorldSeed().
  5. For every replicated foliage you can interact with: open the foliage asset, set bRequiresDeterminism = true, bCollision = true, bGenerateOnServer = true.
  6. For purely-cosmetic foliage: bGenerateOnServer = false to save DS CPU.
  7. Test in PIE with Number of Players = 2 and switch between Play As Listen Server and Play As Client.
  8. For a real dedicated-server build, package your project with the Server target and verify foliage / grid items appear correctly on both sides.

Common MP bugs & fixes

SymptomFix
Grass visible on client but not on serverbGenerateOnServer = true on the foliage interface (default), and DisableFoliageDedicatedServer = false on the Root.
Tree appears in different positions on each peerAudit the four cross-peer inputs: same Root.Seed? Same noise asset reference (no redirectors)? Same foliage collection order in Foliages[]? Same noise parameters (NoiseScale, NoiseIntensity, NoiseOffset, PlanetScale)? Identical on both sides → identical placement.
Server-side projectile passes through treesFoliage needs bCollision = true AND bGenerateOnServer = true. FCP doesn't help because it's client-only.
Grid items missing for listen-server hostListen-server gap (M13). Call Subsystem->WS_Start_AutoGetNearest() manually post-BeginPlay; check that grid update tick is being reached.
Material parameter X reads 0 on serverMPC sync doesn't run on DS / listen. Query the Root directly for any gameplay-relevant data; reserve MPC for client-side rendering.
Two copies of the same actor on a client (one from grid, one from server)On the actor, set bNetLoadOnClient = false so only the server-replicated copy exists.
Terrain visible but no collision around remote players (on a client)Either accept the design (clients only collide around local pawn), or set bGenerateCollisionForAllPlayer = true on the Root.
Soft-referenced asset missing on dedicated serverAdd it to Project Settings → Asset Manager directories or +ServerAdditionalAssetDirectoriesToCook.
Server and client see different terrain after seed changeReplicate Seed via your GameState and call WS_ForceRegenerate() on each peer in OnRep_Seed.

When NOT to use the local-determinism model

WorldScape's seed-driven local generation is great for same-on-every-peer procedural worlds. It is a poor fit for:

  • Persistent player-modified terrain across sessions (e.g. trenches the players dug stay dug after a server restart).
  • Server-authoritative procedural decorations placed by a separate system (raid spawns, GM-placed items).
  • Cross-session deterministic events ("the chest spawned on Tuesday is still there").

For those cases, layer your own replicated state on top: a USaveGame or database that persists the deltas, replicated via your GameState, applied to WorldScape's runtime API (volumes, custom FNoiseData overrides, dynamic spawners).

Net driver compatibility

WorldScape works with any UE net driver, default, Steam Sockets, EOS, Iris, because it never touches the network stack. The plugin compiles identically regardless of which OnlineSubsystem is active.

PCG integration New

The WorldScapePCG module exposes WorldScape data to Unreal's Procedural Content Generation graph, query terrain heights, sample biomes, drive your PCG outputs from the active Root.

Blueprint library

FunctionReturnsPurpose
IsWorldScapePCGAvailableboolCheck before any PCG-side WorldScape call
GetAllWorldScapeRootsTArray<AWorldScapeRoot*>Every active Root in the world
CreateWorldScapeTestPCGNodeUWorldScapeTestPCGNodeSettings*Programmatically create a node settings object
GetWorldScapePCGVersionFStringReturns the PCG module version string

Recipe: PCG-driven foliage placement

  1. Create a PCG Graph asset.
  2. Add a WorldScape PCG node and connect it to your sample / spawn nodes.
  3. Use the Root's height / temperature / humidity samples to filter PCG points before spawning.
Capture. PCG graph using a WorldScape nodecapture to add

GPU Terrain New

When CPU clipmap LOD isn't enough, massive view distances, real-time deformation, ultra-high resolution, switch to the GPU terrain pipeline.

Components

  • WSGPUTerrainRenderer, main scene proxy.
  • WSGPUTerrainVertexFactory, custom vertex layout.
  • WSHeightfieldManager. GPU heightfield textures.
  • WSQuadtreeManager + WSQuadtreeNode, quadtree LOD on the GPU.

When to use GPU vs CPU

ScenarioRecommended
Standard kilometer-scale worldCPU clipmap
Real-time terrain deformationGPU
Ultra-far view distancesGPU
Servers (no GPU)CPU only
Mobile platformsnot supported (Win64/Linux only)
Capture. GPU quadtree debug visualizationcapture to add

WS Toolbar

A user-friendly toolbar for planetary and terrain work. Some features are still beta, flagged below.

How to launch

  1. Open the WorldScape plugin folder in the content browser.
  2. Navigate to Content/Tools/WS_ToolsBar/ and run the WS_ToolsBar Editor Utility Widget.
  3. Position the WS Tools window where you like.
  4. Explore the available options.

The 23 toolbar features

  1. WS selector, select the WS actor in the current scene.
  2. Select from Outliner, focus on the currently selected WS actor in the outliner.
  3. Pick Actor from Scene, eyedropper tool to select a WS actor in the scene.
  4. Reset to Default, resets the selected Root.
  5. Freeze and Unfreeze Landscape, pauses landscape generation for the selected actor.
  6. View Collision, shows the collision; you may need editor collision view enabled.
  7. Custom Details Panel, opens a curated details panel for the current WS actor.
  8. View POI Editor, shows available points of interest in the scene.
  9. Go to Camera POI, focus travel to a POI on the selected actor.
  10. Add POI at Camera Position, adds a new POI at the camera's location.
  11. Add Volume Specified to Worldscape, adds a Foliage / Foliage Baker / Collision Invoker / Hole / Noise / Heightmap Volume at the camera.
  12. Attach Actor to Root, attaches an actor to the selected Root.
  13. Rotate Selected Actor, rotates the selected actor to the tangent of the WS actor.
  14. Snap Actor to Worldscape, snaps the selected actor to the surface.
  15. Move Camera Actor, moves the camera to the selected actor.
  16. Auto Attach Actor to Root, auto-attaches on drop.
  17. Auto Rotate Selected Actor, auto-rotates on drop.
  18. Auto Snap Actor to Worldscape, auto-snaps on drop.
  19. Auto Move Camera Actor, auto-moves the camera on drop.
  20. Open Heightmap Editor, opens the heightmap editor menu.
  21. Reset Camera Roll, resets camera rotation for worldspace.
  22. Camera Selector Mode, pick from 6 modes (see below).
  23. Online Documentation, opens the docs at the current location you're referring to.

Camera Selector Modes

ModeBehavior
NormalStandard editor camera.
AutomatiqueAuto-switches between flat and planetary modes.
UnlockFree-form camera, no constraints.
Unlock with Planetary CorrectionFree movement but corrects orientation to planet up-vector.
TangentCamera locked to surface tangent, ideal for surface-walking previews.
Planetary ExploreHigh-altitude planetary navigation.

Heightmap Editor (in toolbar)

  • Edit with Brush, paint directly on the heightmap.
  • Brush Parametric Controls, use materials/textures as brushes.
  • Channel Selection. Heightmap, Temperature, Humidity, additional channels.
  • 3D View, 3D displacement display of the current texture.
  • Filter, apply blur, noise, or erosion simulation.
  • Resize, resize the heightmap texture.
  • Save / Save As + Key (control reference).

Heightmap Tools Volume Beta

Advanced terrain modification toolkit for planet creators. Generates heightmap volumes scaled to planets, creates landscapes for in-engine editing, bakes landscapes to Nanite meshes. Overlays additional heightmap info on placed volumes (does not replace existing data).

Landscape Export Beta

Convert UE terrain into standardized heightmap files, either a Heightmap Volume Data asset or a heightmap texture file.

Textures created without power-of-two dimensions may cause data shifts in volume data, manual edits required.

Blueprint API

All public Blueprint nodes split across the function library (UWS_FunctionLibrary) and methods on AWorldScapeRoot itself. Right-click in any Blueprint graph and search "WorldScape" to find them.

Pawn-relative queries (on the Root)

For per-frame character/vehicle logic on planets:

FunctionReturnsDescription
GetPawnNormal(Location)FVectorSurface up-vector at the given location.
GetPawnSnappedNormal(Location)FVectorUp-vector snapped to the nearest configured angle.
GetPawnTangent(Location)FVectorSurface tangent.
GetPawnBiTangent(Location)FVectorSurface bi-tangent.
GetPawnAltitude(Location, bWaterNoiseHeight)floatAltitude above sea level.
GetPawnDistanceFromGround(Location, ECEFCoordinate)floatVertical distance to the ground; pass ECEFCoordinate=true if Location is already in planet-centered coordinates.
GetHeight(Location, Water)floatRaw noise height at a 3D position.
GetGroundHeight(Location, Water)floatNoise height projected onto the ground.
GetGroundHeight_HOnly(Location)doubleGround height as a single double (cheaper).
GetGroundHeight_HOnly_Multi(Locations[])TArray<double>Batch version, ~10× faster than looping single calls.
GetPlanetaryDataFromPosition(Position)floatSingle-float "planet height" for material / AI use.

Force-regenerate & cleanup

  • WS_ForceRegenerate(), full terrain regen.
  • WS_ForceRegenerate_WS(bool), partial WS regen.
  • WS_ForceRegenerate_Foliage(), foliage-only regen.
  • WS_ForceResetCollision(), reset collision sectors.
  • WS_ForceUpdatePotion(), force update of internal positioning.
  • WS_CleanFoliage(), clean & tag the regen reason for debug logs.

Volume queries

  • GetVolumeAtPosition(Location, out NoiseVolume[], out HeightMapVolume[], out TerrainHole[]), fills three output arrays with the overlapping volumes at Location.
  • GetLocationInSelectedVolume(Location, HeightMapVolume)bool.
  • GetVolumeCanSample(HeightMapVolume)bool.
  • GetLocationIsInWSVolume(Location, FTransform VolumeTransform, FVector VolumeBoxExtend)bool (generic AABB).
  • GetGroundNoiseWithVolume(Location, NoiseVolumes[], HeightMapVolumes[], TerrainHoles[])double (height value, not the full FNoiseData).

Material runtime swap

  • UpdateTerrainMaterial(FWSMaterialLodArray), swap terrain materials at runtime (no regen).
  • UpdateOceanMaterial(FWSMaterialLodArray), swap ocean materials.

Function library, surface sampling

  • WS_SampleSurface(Root, Location, Size, StepSize, HeightThreshold) → bool
  • WS_SampleSlopeSurface(Root, Location, Size, Step, SlopeMin, SlopeMax) → bool, RelativeNormal
  • WS_SampleSurfaceH(Root, Center, Forward, Right, Up, Size, StepSize) → HDifference, Median, Average
  • WS_SampleSlope(Root, Center, Forward, Right, Up, Size) → Normal1, Normal2

Function library, grid sampling

  • WS_Sample_2DGrid(Root, Center, Rotation, Extend, Step) → TArray<FVector>
  • WS_Sample_2DGrid_Async(Index, Delegate, Root, Center, Rotation, Extend, Step), non-blocking version with FWS_SampleReturn callback.
  • WS_GetGridCoord(Location, BaseLocation, Depth, Radius) → FWS_Grid
  • WS_GetAdjacentGridCoord(Coord, BaseLocation, Radius) → TArray<FWS_Grid>

Function library, projection & alignment

  • WS_ProjectGroundLocation_Multi(Root, Locations[]) → TArray<FTransform>
  • WS_ProjectGroundLocationWithNormal_Multi(Root, Locations, Offset), also returns ground normals.
  • WS_ProjectActorToGround(Root, Actor, Offset)
  • WS_ProjectTransformToGround(Root, Transform, Offset) → FTransform, snaps + rotates.
  • WS_SingleProject(Root, Location) → FVector
  • WS_SingleProject_Transform(Root, Location, Size, YawBase, Z_Offset) → FTransform
  • WS_GetTerrainNormalTriTest(Root, Location, Offset) → FVector

Function library, data queries

  • WS_GetHeightValueAtLocation(Root, Location) → double
  • WS_GetTemperatureValueAtLocation(Root, Location) → double
  • WS_GetHumidityValueAtLocation(Root, Location) → double
  • WS_GetGroundInWater(Root, Location) → bool
  • WS_FindMinimalGroundH(Root, Points[]) → double
  • WS_OverrideLocationH(Root, Location, NewH) → FVector
  • WS_GetAltitudeInLocation(Root, Location, Offset) → double
  • WS_GetAllFoliageIndexMask(Root) → TArray<int>

Function library, math utilities

  • WS_CubicBezierY(A, B, C, D, T) → FVector
  • WS_GetSplineOffset(A, B, C, D, T) → FVector
  • WS_SphereToCube(Location, CenterLocation, MinRadius) → FVector
  • WS_RelativeToWorld(WorldTransform, RelativeLocation, RelativeRotation) → FTransform
  • Grid_SerializeActor_Direct(Actor) → TArray<uint8>

Editor function library

From WorldScapeEditor_FunctionLib:

  • WS_CreateLandscape(Transform, SectionSize, SectionsPerComponent, ComponentCountX, ComponentCountY), spawn a UE Landscape actor procedurally.
  • WS_GetLandscapeInfo(), WS_GetSectionSize(), query landscape properties.

Legacy "Picture-style" nodes

NodeDescription
Get HeightGet the noise height at the set position.
Get Height NormalizeGet the normalized height at the set position.
Get NoiseGet the full FNoiseData at a position.
Get Ground HeightSame as Get Height but projected to the ground.
Get Ground Height NormalizeSame as Get Height Normalize but projected to ground.
Get Ground NoiseSame as Get Noise but projected to ground.

Rebase events (world origin shifting)

When the engine rebases the world origin (large-world streaming), the Root forwards two events:

  • OnBeginRebase(), world rebase started.
  • OnFinishedRebase(), world rebase finished.

Bind to these to freeze gameplay/physics during the shift.

Console reference

Console variables and commands registered by the WorldScape plugin. Type into the editor's ~ console at runtime, or set under [ConsoleVariables] in DefaultEngine.ini.

NameTypeDefaultPurpose
WorldScape.Foliage.Debugcommand,Toggle the WorldScape foliage debug overlay and verbose logging. Equivalent to WSFoliageDebugToggle in older builds.
r.RayTracing.Geometry.WorldScapeMeshint321Include WorldScape meshes in ray-tracing effects (Lumen, RT shadows). 0 disables.
ws.GPUTerrain.Indirect.HeightfieldTickBudgetMsfloat2.0Render-thread budget (ms) for indirect GPU terrain heightfield generation. 0 = unlimited.
ws.GPUTerrain.Indirect.MeshTickBudgetMsfloat2.0Render-thread budget (ms) for indirect GPU terrain mesh generation. 0 = unlimited.
ws.GPUTerrain.Indirect.ForceVertexColorViewint320Debug overlay on indirect GPU terrain. 0=off, 1=color, 2=red, 3=green, 4=blue, 5=alpha.
ws.GPUTerrain.Indirect.LogBoundMaterialsint320Logs bound materials on indirect GPU terrain (throttled to 1/sec per proxy).
ws.GPUNoiseint32-1Override bUseGPUNoise at runtime. -1=use actor setting, 0=force off, 1=force on.
ws.IndirectInstancingint32-1Override bUseIndirectInstancedNoise at runtime. -1/0/1.
Tags used by the runtime: WS_Valid (auto-tracking accept), WS_Invalid (auto-tracking exclude), WS_Planetary (Snap Spawner default valid tag), WS_Exclude (Snap Spawner default exclude tag). Add these as actor tags to filter which Roots the subsystem considers.

Volume pooling Beta

Take and release volumes from a pre-allocated pool instead of spawning/destroying them at runtime. Avoids garbage-collection hitches during procedural editing or runtime worldgen.

API on AWorldScapeRoot

FunctionPurpose
Pooling_Init()Initialize the pool (auto-called on BeginPlay, but can be re-run).
Pooling_Clear()Empty the pool and destroy all pooled volumes.
WS_Pooling_IsInitialized()Returns true once WS_Pooling_OnInitialized has fired.
Pooling_Take_HeightmapVolume(out Volume)Get a HeightMap Volume from the pool. Returns false if none available.
Pooling_Release_HeightmapVolume(Volume)Return a HeightMap Volume to the pool.
Pooling_Release_HeightmapVolume_Multi(Volumes[])Batch release.
Pooling_Take_FoliageMaskVolume(out Volume)Same for FoliageMask Volumes.
Pooling_Release_FoliageMaskVolume(Volume)Return to pool.
Pooling_Release_FoliageMaskVolume_Multi(Volumes[])Batch.
Pooling_Take_HoleVolume(out Volume)Same for Hole Volumes.
Pooling_Release_HoleVolume(Volume)Return to pool.
Pooling_Release_HoleVolume_Multi(Volumes[])Batch.
"Volume pooling is a method that allows you to keep the number of active volumes low in the field. You can at any time in C++ or Blueprint request a volume from the worldscape root, which will be a volume that is part of the pooling list, then configure it and place it where you want."

Bind to the WS_Pooling_OnInitialized delegate (on the Root) to know when the pool is ready, before issuing any Take.

Grid spawning & streaming Experimental

A cell-based streaming system that spawns and despawns content (rocks, props, buildings, foliage, anything) around the player based on a deterministic seed. Loads as the player approaches, unloads when they leave. Replicates "for free" across server & clients via shared-seed determinism.

The two grid layers

WorldScape exposes two entry points into the same grid system. Pick whichever fits your design:

Entry pointScopeWhen to use
Root's Grid_BaseSpawnDataGlobal, applies everywhere the streaming radius reachesScattered props or biome content covering the entire world (rocks all over the desert, debris everywhere on a moon).
AWorldScape_GridSpawnerVolumeLocalized, only within the volume's sphereRegion-specific content (a forest only in this zone, buildings only in this hand-placed area).

Both feed the same execution engine: a UWorldScape_GridDataAsset describes what to spawn and how, and the Root's runtime takes care of streaming, throttling, snapping, and per-side replication.

Quick start (5 steps)

  1. Enable the grid: select your WorldScapeRoot, set EnabledGrid = true.
  2. Create a Grid Data Asset: right-click in content browser → WorldScape tab → Grid Data Asset. Name it (e.g. GDA_Rocks_Mountain).
  3. Open the asset, set SpawnType = StaticMesh, add at least one entry to StaticMeshDatas (set its StaticMesh field to a rock mesh).
  4. Configure constraints in SpawnParams (e.g. MaxSlope = 0.3, SpawnableInWater = false).
  5. Add the asset to the Root's Grid_BaseSpawnData array. Hit Play. Walk around. Rocks appear within Grid_DistanceToLoad (default 50 km).
For a localized version: skip step 5 and instead drag a WorldScape_GridSpawnerVolume into the level, scale its sphere, link your Grid Data Asset in SpawnDataAsset, link the Root in Linked_WS_Root.

The 6 spawn types

The SpawnType enum on a Grid Data Asset selects which list is used and what gets spawned.

SpawnTypeLists usedResult per cell
ActorActorsDatas (TArray<FWS_Grid_Spawner_Actor>)One actor instance, picked by weighted SpawnableChance.
StaticMeshStaticMeshDatasOne ISM-instanced static mesh, picked by weighted chance.
CollectionCollection_ActorsDatas + Collection_StaticMeshDatas + Collection_ProxyDataA pre-arranged group of actors and meshes spawned together (e.g. a "small camp" = tent + crates + barrels). Each entry has its own placement.
CollectionStaticMeshCollection_StaticMeshDatasSame as Collection but static-mesh-only (no actor classes, cheaper).
FoliageStaticMeshDatasFoliage-style high-density spawn using FoliageSectorSize (default 32 km) instead of the per-cell loop.
DataAssetSpawners (TArray<FWS_Grid_Spawner_DataAsset>)Cascade, spawns from nested Grid Data Assets, each with its own scale multiplier. Use to compose modular sets.

The SamplingType enum is exposed in the editor with only one usable value, CircleRND. (The PoissonDisk and Grid values are present in source but flagged UMETA(Hidden).)

Grid Data Asset properties

Full breakdown of UWorldScape_GridDataAsset:

PropertyTypeDefaultPurpose
EnabledbooltrueMaster toggle.
SpawnableOnDedicatedbooltrueSpawn on dedicated server (set false for cosmetic-only items to save DS CPU).
SpawnTypeEWS_Grid_SpawnTypeActorWhich list / mode to use (see above).
SamplingTypeEWS_Grid_SamplingTypeCircleRNDHow candidate positions are sampled in the cell.
Max_TestToSpawnint32200How many candidate positions to sample per cell before giving up.
Max_Spawnint3220Max actual instances spawned per cell (after constraints filter candidates).
Z_Offsetdouble0.0Global Z offset added to every spawn from this asset.
SeedOffsetint320Per-asset seed offset, tweak to shift placements without changing the global Seed.
SpawnParamsFWS_Grid_SpawnParams(see below)Constraints (elevation, slope, climate, water, flatness).
SpawnersTArray<FWS_Grid_Spawner_DataAsset>[]For DataAsset mode, cascading list of nested data assets.
ActorsDatasTArray<FWS_Grid_Spawner_Actor>[]For Actor mode, weighted actor classes.
StaticMeshDatasTArray<FWS_Grid_StaticMesh_Data>[]For StaticMesh / Foliage modes.
Collection_ProxyDataFWS_Grid_Proxy(default)For Collection modes. LOD proxy mesh + switch distance.
Collection_ActorsDatasTArray<FWS_Grid_Actor_Data>[]Collection mode, the actors that compose the group.
Collection_StaticMeshDatasTArray<FWS_Grid_StaticMesh_Data>[]Collection mode, the static meshes that compose the group.
ExtentFVector(1000,1000,1000)Bounding extent for collection items.
FoliageSectorSizedouble3,200,000For Foliage mode, sector size in cm (~32 km).

Spawn constraints (FWS_Grid_SpawnParams)

Every Grid Data Asset has a SpawnParams struct that filters candidate positions before spawning:

FieldDefaultPurpose
MinElevation-200000Skip the spawn if terrain height is below this (cm).
MaxElevation200000Upper height bound.
MinTemperature-100Lower temperature bound (raw noise output range, not 0-1).
MaxTemperature100Upper temperature bound.
MinHumidity0.5Lower humidity bound (0-1).
MaxHumidity1Upper humidity bound.
MaxSlope0.1Reject if slope exceeds this (0 = flat, 1 = vertical). Lower → flatter required.
CheckDifferencetrueVerify local terrain flatness, sample neighbors and reject if elevation varies too much.
Max_ElevationDifference650Max allowed elevation variance under the spawn (cm). Tightens to "must be flat".
SpawnableInWaterfalseIf false, reject candidates where ocean height is above terrain height.
RotateToGroundtrueAuto-orient the spawn to surface normal.
InvalidSize85000Exclusion radius around each successful spawn (cm), prevents two items from this asset from spawning closer than this.
SpawnSize450Effective area around the spawn point.
Tuning the flatness check: for buildings or static structures that demand level ground, lower Max_ElevationDifference to 100-200. For props that can sit on slopes (rocks, bushes), raise it to 2000+ or set CheckDifference = false.

Placement (FWS_Grid_Placement_Data)

Inside FWS_Grid_Actor_Data and FWS_Grid_StaticMesh_Data, every entry carries a Placement struct that fine-tunes how that specific item is positioned:

FieldDefaultPurpose
TransformidentityBase transform applied before the snap-to-ground step.
SnapGroundtrueProject the spawn down to the terrain surface.
RotateToGroundtrueAlign the spawn's up-vector to surface normal.
RND_YawfalseApply random yaw rotation.
Yaw_Rotate(1°, 360°)Yaw range used by RND_Yaw.
Z_Offset0Per-item Z offset on top of the asset's global Z_Offset.
Use_DiskRNDtrueApply a random offset within a disk (for collection items, scatter them around the base point).
DiskRND_Size400Disk radius for the random offset (cm).
RND_LinearScalefalseRandom uniform scale.
LinearScale(0.5, 1.5)Scale range used when RND_LinearScale = true.

LOD proxies (FWS_Grid_Proxy)

Each Spawner_Actor, Spawner_StaticMesh, and the collection's Collection_ProxyData can carry an optional LOD proxy mesh that's swapped in at distance to save draw calls:

FieldDefaultPurpose
UseProxyfalseMaster toggle for the proxy.
ProxyMeshnullSoft reference to the simplified mesh (loaded async on client).
ProxySwitchDistance100,000Distance at which the real spawn is replaced by the proxy (default 1 km).
Use_AdditionalComponentfalseSpawn an additional component class on the proxy (e.g. for VFX, light marker).
AdditionalComponentClassnullSoft reference to the additional component.
Proxies are skipped on dedicated server (the SMProxy actor is no-op on DS), they're a pure render optimization.

Root-level streaming knobs

All under Category Grid on AWorldScapeRoot:

Master switches

PropertyDefaultPurpose
EnabledGridfalseMaster toggle.
Grid_BaseSpawnData[]Global Grid Data Assets active everywhere.
Grid_InvalidVolume[]Array of AWS_Grid_InvalidSphere exclusion zones.
Grid_DebugfalseDraw debug visualization of the loaded grid.
Grid_CheckSpawnBySeedtruePer-side dedup by instance seed (leave on for MP, prevents ghost spawns at cell seams).
Grid_DestroyAllOnOutDistancefalseForce despawn all out-of-range items immediately (default keeps them for the unload window).

Streaming distance & cell size

PropertyDefaultPurpose
Grid_DistanceToLoad5,000,000Streaming radius (cm). Default = 50 km. Cells inside this radius load, others unload.
Grid_Size64Internal grid index resolution. Combined with Grid_Data_Size determines the per-cell spatial extent.
Grid_Data_Size8Per-cell data resolution.
Grid_Size_Scale1.1Multiplier on the cell area (slight overlap to avoid seams).
Grid_BaseSpawnScale1.0Base scale on the per-cell Max_Spawn count.
Grid_GlobalSpawnScale1.0Global multiplier across all data assets.
Grid_RNDCircle_TestLimite600Hard cap on candidate-position tests per cell (safety).

Throttling (per-side)

PropertyDefaultPurpose
Grid_UsePendingSpawntrueQueue spawns instead of doing them all in one frame.
Grid_MaxSpawnPerSecond512Spawn throttle for client / listen / standalone.
Grid_MaxSpawnPerSecond_OnDedicated1024Spawn throttle for dedicated server.
Grid_UsePendingDestroytrueQueue destroys.
Grid_MaxDestroyPerSecond1024Despawn throttle, non-DS.
Grid_MaxDestroyPerSecond_OnDedicated2048Despawn throttle, DS.
Grid_FoliageBlockSend16Foliage-batch granularity.

Dedicated-server tweaks

PropertyDefaultPurpose
Grid_SimulateDedicatedfalsePretend you're DS even on a client (debug DS behavior in PIE).
Grid_SkipStaticMeshOnDedicatedfalseSkip ALL StaticMesh/CollectionStaticMesh/Foliage grid types on DS.
Grid_SkipAdjacentCellOnDedicatedfalseShrink loaded neighborhood from 9 cells to 1 on DS.

Live info (read-only, exposed for debug)

PropertyPurpose
NumberOfCellLoadedCurrent count of loaded cells around all known players.
NumberOfThreadActive grid worker threads.
OnPendingAsyncComputePending async compute jobs.
TempQueueLengthLength of the spawn queue.

Exclusion zones (AWS_Grid_InvalidSphere)

Drop one or more AWS_Grid_InvalidSphere actors in your level, register them in the Root's Grid_InvalidVolume array, and the grid will refuse to load any cell whose center falls inside the sphere. Useful for:

  • Clearing space around hand-placed structures (no rocks inside your village).
  • "No buildings in the river valley" type designer overrides.
  • Hand-tuning regions around POIs.

The actor exposes a single function WS_ZoneGetSize() that returns the scaled sphere radius.

Localized: AWorldScape_GridSpawnerVolume

Place a Grid Spawner Volume in your level for region-specific spawn rules. Properties (Category Spawner):

PropertyTypePurpose
SpawnDataAssetTArray<TSoftObjectPtr<UWorldScape_GridDataAsset>>One or more Grid Data Assets active inside this sphere.
SpawnScalefloatMultiplier on each asset's Max_Spawn within this zone.
Linked_WS_RootAWorldScapeRoot*Which Root to spawn against. Auto-set if the volume is a child of a Root.
SphereComponentUSphereComponentDefines the zone radius. Scale the actor in-editor to resize.

The volume's items still pass through the same streaming pipeline, they'll only spawn inside cells overlapping the sphere AND within Grid_DistanceToLoad of the player.

Per-cell & phase delegates

Bind to these BlueprintAssignable delegates on the Root:

  • WS_Grid_LoadCell_Delegate(FWS_Grid), fires for every cell that finishes loading. Useful for spawning custom per-cell content (NPCs, AI zones).
  • WS_Grid_UnLoadCell_Delegate(FWS_Grid), cell unloaded.
  • WS_Grid_StartPendingLoad / WS_Grid_EndPendingLoad, batch-load window opened / closed (good for hiding HUD during heavy streaming).
  • OnStartGrid / OnEndGrid, the entire grid pass starts / ends.

Common recipes

Recipe 1. Scattered rocks all over the planet

  1. Create GDA_Rocks_Global: SpawnType = StaticMesh.
  2. Add 5-10 rock meshes to StaticMeshDatas, vary SpawnableChance (e.g. small rocks weight 5, big rocks weight 1).
  3. Set each entry's Placement.RND_Yaw = true, Placement.RND_LinearScale = true, Placement.LinearScale = (0.6, 1.4).
  4. SpawnParams: MaxSlope = 0.6, SpawnableInWater = false, CheckDifference = false, Max_Spawn = 30.
  5. Add the asset to Root's Grid_BaseSpawnData.

Recipe 2. Buildings in a single zone with flat terrain check

  1. Create GDA_Village_Buildings: SpawnType = Actor, fill ActorsDatas with house/tower/well actor classes.
  2. SpawnParams: MaxSlope = 0.05, CheckDifference = true, Max_ElevationDifference = 100, InvalidSize = 200000 (200 m between buildings).
  3. Max_Spawn = 5 (per cell).
  4. Drop a WorldScape_GridSpawnerVolume in your level over the village area, scale the sphere, link the asset.
  5. Optionally add an AWS_Grid_InvalidSphere at the village center to keep the middle clear.

Recipe 3. Camp collection (tent + crates + barrels)

  1. Create GDA_Camp_Collection: SpawnType = Collection.
  2. Add the tent class to Collection_ActorsDatas with Placement.Use_DiskRND = false (it stays at the base point).
  3. Add 3-5 crate / barrel meshes to Collection_StaticMeshDatas with Placement.Use_DiskRND = true, Placement.DiskRND_Size = 600 (scatter around the tent).
  4. Set Collection_ProxyData.UseProxy = true, assign a low-poly silhouette mesh, set ProxySwitchDistance = 50000 (50 m).
  5. SpawnParams: tighten flatness check; Max_Spawn = 2.

Recipe 4. Cascading data assets (modular biome)

  1. Create three small assets: GDA_Biome_Trees, GDA_Biome_Rocks, GDA_Biome_Mushrooms.
  2. Create a master GDA_Biome_Forest with SpawnType = DataAsset.
  3. Add the three child assets to Spawners with their own SpawnScale multipliers.
  4. Add only GDA_Biome_Forest to the Root or volume, it will cascade into the children.

Recipe 5. Server-stripped cosmetic decorations

  1. Create a Grid Data Asset for cosmetic-only items (low grass, particles).
  2. Set SpawnableOnDedicated = false.
  3. The dedicated server will skip this asset entirely; clients will still see it.

Grid in multiplayer

The grid system is not replicated, each peer regenerates the same items locally from the shared Seed + per-asset SeedOffset. See Grid spawning in MP for the full multiplayer model.

Key MP knobs:

  • Per-asset SpawnableOnDedicated, cosmetic items off, gameplay items on.
  • Per-asset SeedOffset, lets you shift placements without changing the global Seed.
  • Root Grid_CheckSpawnBySeed, dedup by seed across cell boundaries (default on, leave on).
  • Root Grid_SkipStaticMeshOnDedicated / Grid_SkipAdjacentCellOnDedicated, coarse DS perf knobs.
  • For replicated actors: set the actor's bNetLoadOnClient = false and let the server replicate, otherwise you'll get two copies on each client (one local, one replicated).

Troubleshooting

SymptomLikely cause & fix
Nothing spawns at allEnabledGrid = false (default). Or your Grid Data Asset is empty / has Enabled = false. Or no list matches the SpawnType (e.g. SpawnType=StaticMesh but StaticMeshDatas is empty).
Items appear far from the player but not nearbyGrid_DistanceToLoad too low, or the player has no UWorldscapeCollisionInvoker component (its presence drives some grid systems too).
Items spawn but are sunk into terrainPlacement.SnapGround = false, or Placement.Z_Offset negative.
Items spawn floating above terrainPlacement.Z_Offset too high, or Placement.SnapGround = false.
Far too few items spawnConstraints too strict: MaxSlope too low, Max_ElevationDifference too tight. Or Max_TestToSpawn too low (raise to 400-600).
Items overlap / bunch upRaise InvalidSize to enforce minimum spacing.
Frame hitches when moving fastLower Grid_MaxSpawnPerSecond, enable Grid_UsePendingSpawn (default on), or reduce Max_Spawn per asset.
Items appear in different places on server vs clientCheck the determinism contract, verify Seed matches, asset list ordering matches, noise asset matches.
Items inside an exclusion zoneCheck that the AWS_Grid_InvalidSphere is registered in Grid_InvalidVolume and that its sphere is large enough.
Items missing on dedicated serverPer-asset SpawnableOnDedicated = true, Root Grid_SkipStaticMeshOnDedicated = false, and ensure soft-class assets are in the server cook (Asset Manager).

Collision Invoker (Component) Beta

The plugin exposes two collision-invocation mechanisms, don't confuse them.

  • Component (UWorldscapeCollisionInvoker): attach to any actor that needs collision around it (player pawn, vehicle, AI). Auto-registers with the subsystem.
  • Volume (Collision Invoker Volume): a placed volume that generates an isolated collision actor in a fixed region (cliffs, structures). Usually used for editor placement, not for moving actors.

For multiplayer: every replicated pawn that needs server-side collision queries should carry a UWorldscapeCollisionInvoker component.

Foliage debug widget

A runtime widget that surfaces every counter the foliage system tracks, the fastest way to understand why your frame budget is being eaten by foliage.

Toggle it via the console:

WorldScape.Foliage.Debug

What it shows

  • Per-foliage active sector count, total instances, actors spawned
  • "Ghost sectors", sectors marked active but never filled (memory leak indicator)
  • Generation state and regen-reason string (so you know why regen happens, e.g. "WS_CleanFoliage")
  • Thread pool alive/done state
  • Pending spawn queue size

The widget is a plain Slate widget (SWSFoliageDebugWidget) so it draws on top of any game.

Performance & best practices

A few tunings make the difference between 30 fps and 120 fps at planet scale.

Terrain LOD

  • Higher TerrainResolution_Depth = more detail but more memory.
  • Sweet spot: 10-12 for altitude-heavy worlds, 8-10 for mostly-flat worlds.
  • Each level doubles the previous sector's coverage.

Foliage

  • FoliageSectorSize: 2000 = 2,000-cm sectors.
  • FoliagesCount: 100 = ~100 instances per sector.
  • Use Is_NaniteMesh: true for high-poly foliage.
  • FoliageCullDistanceMultiplier reduces draw calls in the distance.

Collision

  • bGenerateTerrainCollision: true adds significant cost, only enable if needed.
  • Use EWS_FCP_TypeCompute::GPU for foliage collision pooling on heavy worlds.
  • bUseAsyncCooking: true moves physics cooking off the game thread.

Multiplayer

  • bGenerateOnServer: true (default) for dedicated servers.
  • Subsystem auto-tracks the nearest Root per player.
  • Collision invokers manage movement-based updates, one per significant moving actor.

Troubleshooting

Common symptoms, fixes, and the FAQ from the original docs.

Stair-step heightmap artifacts

Use a 16-bit texture and enable High Resolution on the volume data asset.

Random heightmap values

Caused by non-power-of-two textures or 8-bit textures imported as 16-bit. Re-export at a power of 2, set compression to HDR.

Mountain pop-in

Increase MaxLOD to 10-12.

Heightmap Influencer behaving inconsistently

Restart the level / project to re-apply the data fresh.

Black screen in the demo level

Enable the Volumetric plugin, or disable CloudVolumetric in the level.

Failed packaging

Enable the Water plugin in your project's plugin list.

Hole Volume not cutting

"Edit the master material for the WorldScape manager and multiply the alpha vertex color at the end of the opacity mask lerp."

Floating-point surface artifacts

See Material fix.

Terrain visual artifacts on UE 5.x

Set Velocity Pass to Write After Base Pass, run r.UseVisibilityOctree 0.

FAQ

Can I walk on a planet's surface?

Yes, use the WorldScapePlayer or build a custom MovementComponent (see Custom character).

Can I use Landscape materials on the clipmap?

No. UE Landscape materials are built for LandscapeComponent. The plugin offers a triplanar example as an alternative.

Can I sculpt the terrain in the editor?

No direct sculpt, create heightmaps in external software (WorldMachine, Gaea, etc.), import via Heightmap Influencer. The WS Tools heightmap editor offers in-engine brush sculpting.

Why does my heightmap have artifacts?

Stair-step = precision; use 16-bit + High Quality. Random values = non power-of-two or 8-bit-imported-as-16-bit.

Why do mountains pop in/out?

MaxLOD too low. Recommended 10-12 for altitude-heavy terrain.

Support & community

Stuck? Found a bug? Want to share what you built?

  • Discord: discord.gg/eWuFnPcskQ, join the support channel by sharing your Fab purchase receipt.
  • Fab: marketplace listing for ratings, reviews, version history.
  • Bug reports: via Discord with a repro project (or a clear video).
  • Feature requests: Discord #feature-requests channel.
"Do not hesitate to credit WorldScape in your creation, it is very appreciated!"

Roadmap snapshot

Currently in beta or experimental and being polished:

  • Subsystem (registry, nearest tracking, MPC sync) Beta
  • Gravity Value Beta
  • Volume Pooling Beta
  • Foliage Collision Pooling Beta
  • Foliage Baker Beta
  • Heightmap Editor & Heightmap Tools Volume Beta
  • Collision Invoker Volume Beta
  • Grid Spawner / Snap Actor / Planetary Grid Data Experimental