Forest is the scene object responsible for rendering, culling, collision, and wind interaction for forest items in a level.
The Forest system is designed for very large numbers of repeated static objects, such as:
Forest items are usually more efficient than placing thousands of individual TSStatic objects. For repeated vegetation and scatter assets, use the Forest system whenever possible.
The Forest object does not usually store individual item placement directly inside items.level.json.
Instead, it loads forest placement files from the level folder:
levels/<levelName>/forest/*.forest4.json
Forest item type definitions are stored separately in:
levels/<levelName>/art/forest/managedItemData.json
The two systems work together:
| File / Object | Purpose |
|---|---|
Forest object |
Scene object that loads and manages forest data. |
managedItemData.json |
Defines forest item types, such as tree/rock/bush definitions. |
*.forest4.json |
Stores placed forest instances. |
ForestItemData |
Runtime/editor object representing one forest item type. |
ForestWindEmitter |
Applies wind to nearby/global forest items. |
ForestBrush / ForestBrushElement |
Editor-only brush setup for painting forest items. |
For the file format itself, see Forest Data (.forest4.json) and managedItemData.json
.
A typical level has one Forest object, usually named:
theForest
Example:
{
"class": "Forest",
"name": "theForest",
"position": [0, 0, 0],
"rotationMatrix": [1, 0, 0, 0, 1, 0, 0, 0, 1],
"scale": [1, 1, 1],
"lodReflectScalar": 2
}
The Forest object uses global bounds and its transform position is not normally meaningful for item placement.
Forest object is not how you move forest items.| Field | Type | Description |
|---|---|---|
dataFile |
string | Legacy source forest data file field. Hidden/no serialization in modern usage. |
lodReflectScalar |
number | LOD scalar used when rendering forest into reflections. |
"lodReflectScalar": 2
lodReflectScalar changes the far clip / LOD behavior when the forest is rendered in reflection passes.
Higher values can make forest reflections use lower detail or cull differently, improving reflection performance.
This is mainly a performance/quality control for reflected forests.
When the Forest object is added to the scene, it:
.forest4.json files if available.Modern files are preferred:
*.forest4.json
Older formats are deprecated:
*.forest
*.forest.json
If old files are found, the engine logs warnings asking the level author to resave and remove old files.
Modern forest data is usually split by forest item type.
Example:
levels/example/forest/oak_large.forest4.json
levels/example/forest/pine_small.forest4.json
levels/example/forest/rock_large.forest4.json
When saving, the Forest system groups items by their ForestItemData internal name and writes one .forest4.json file per type.
Unused forest files may be deleted or backed up when saving, depending on whether any forest items remain.
Forest items are organized into spatial cells.
The cell system is used for:
Cells can subdivide when they contain too many items. This forms a spatial hierarchy, allowing the engine to quickly skip areas outside the camera view or query region.
Forest data uses top-level buckets based on item position. Each bucket contains a ForestCell.
When adding an item:
This makes queries faster than scanning every forest item in the level.
Forest items can be found by:
This is used by:
ForestItemData defines one forest item type.
It includes:
Important fields:
| Field | Description |
|---|---|
shapeFile |
Shape used by this forest item type. |
collidable |
Whether items of this type contribute collision. |
radius |
Placement radius used to avoid crowding. |
snapRotationToTerrain |
Aligns placed items to the surface normal. |
windScale |
Overall wind influence. |
trunkBendScale |
Trunk bend amount. |
branchAmp |
Branch wind amplitude. |
detailAmp |
Leaf/frond/detail wind amplitude. |
detailFreq |
Leaf/frond/detail wind frequency. |
mass |
Used by wind spring simulation. |
rigidity |
Resistance to wind force. |
tightnessCoefficient |
Resistance to bending. |
dampingCoefficient |
Damps oscillation over time. |
annotation |
Annotation/debug classification. |
Each ForestItemData references a shape:
"shapeFile": "/levels/example/art/shapes/trees/oak_large.dae"
The shape is loaded once and shared by all items of that type.
This is one of the main reasons Forest is efficient for repeated assets.
Forest rendering is optimized for many repeated instances.
The renderer:
When the Scene Static Manager is enabled, forest rendering may be routed through that optimized path.
Use Forest for many repeated objects.
Use TSStatic for individually placed objects.
| Use case | Recommended |
|---|---|
| Thousands of trees | Forest |
| Repeated rocks/bushes | Forest |
| Grass/vegetation scatter | Forest / GroundCover depending use |
| Single building | TSStatic |
| Unique bridge | TSStatic |
| Manually placed prop | TSStatic |
| Object needing custom transform/material behavior | TSStatic |
TSStatic is better for individual placed meshes.Forest items use the LODs stored in their shape files.
At render time, the engine estimates the item’s screen-space size and chooses an appropriate detail level. If the lowest detail is a billboard/imposter, the item can be rendered as a batched imposter.
A whole forest cell may be rendered as imposter batches if the largest item in the cell can be billboarded at the current distance.
This improves performance significantly for distant vegetation.
Forest cells can build imposter batches.
A batch groups items that share the same last-detail/imposter type.
This reduces draw overhead for distant forests.
Batching is used when:
Debug settings can force or disable imposters internally:
Forest::smForceImposters
Forest::smDisableImposters
Forest uses lodReflectScalar to adjust rendering in reflection passes.
In reflections, forest detail may be reduced or culled sooner to improve performance.
This is important because rendering forests into reflection passes can be expensive.
Forest can provide collision for forest items if their ForestItemData is collidable.
The collision system:
Collision data is cached by shape file to avoid rebuilding the same collision repeatedly for every item.
Forest supports raycasts against forest items.
Raycasts can use:
This is used by:
If the ray hits a forest item, the returned object is the Forest object, and additional internal item data may be used by tools.
Forest does not support decal projection in the same way terrain and static meshes do.
For decal poly list queries, Forest returns false.
PLC_Decal → false
This means road decals and other projected decals should not rely on forest item geometry as decal receivers.
Forest items can react to wind if their shape/material setup supports it.
Wind requires:
windScale > 0ForestWindEmitter or global wind sourceWind affects:
ForestWindEmitter defines wind in a level.
It can act as:
Important fields:
| Field | Description |
|---|---|
windEnabled |
Enables this emitter. |
radialEmitter |
If true, wind is local/radial instead of global direction. |
strength |
Wind strength. |
radius |
Radius for radial emitters. |
gustStrength |
Maximum gust strength. |
gustFrequency |
Gust frequency in seconds. |
gustYawAngle |
Direction drift angle. |
gustYawFrequency |
Direction drift frequency. |
gustWobbleStrength |
Random wobble added to gusts/turbulence. |
turbulenceStrength |
Turbulence strength. |
turbulenceFrequency |
Turbulence frequency. |
Example:
{
"class": "ForestWindEmitter",
"name": "forest_wind",
"position": [0, 0, 0],
"windEnabled": true,
"radialEmitter": false,
"strength": 1,
"gustStrength": 0.5,
"gustFrequency": 3,
"gustYawAngle": 10,
"gustYawFrequency": 4,
"turbulenceStrength": 0.25,
"turbulenceFrequency": 2
}
The wind manager only gathers nearby wind-reactive trees around the camera.
This is controlled by the engine settings, such as wind effect radius.
Items with:
windScale < 0.001
are skipped from wind update placement info.
This avoids spending CPU time on static rocks or non-wind vegetation.
Forest can apply radial impulses to nearby wind-reactive items.
This is used for effects like:
The impulse affects local wind accumulators and causes nearby vegetation to bend/react temporarily.
The Forest Editor uses the Forest object named:
theForest
If no active forest exists, the editor can create one.
The editor modifies forest data through tools such as:
Changes are stored in the forest data and saved to .forest4.json files.
A ForestBrush is an editor-only container for ForestBrushElement objects.
It is stored under:
ForestBrushGroup
The brush defines which forest item types can be painted and with what placement rules.
A ForestBrushElement defines placement parameters for one forest item type.
Important fields:
| Field | Description |
|---|---|
forestItemData |
Forest item type to place. |
probability |
Relative probability for random selection. |
rotationRange |
Random yaw rotation range. |
scaleMin |
Minimum random scale. |
scaleMax |
Maximum random scale. |
scaleExponent |
Bias between min and max scale. |
sinkMin |
Minimum sink amount. |
sinkMax |
Maximum sink amount. |
sinkRadius |
Radius used for slope sinking. |
slopeMin |
Minimum allowed slope. |
slopeMax |
Maximum allowed slope. |
elevationMin |
Minimum allowed elevation. |
elevationMax |
Maximum allowed elevation. |
ForestBrushTool is the editor tool used to paint, erase, and adjust forest items.
Important brush tool fields:
| Field | Description |
|---|---|
mode |
Paint, erase, erase selected, or snap-to-terrain mode. |
size |
Brush radius. |
pressure |
Density/strength of brush stroke. |
hardness |
Brush falloff/hardness. |
depthOffset |
Offset above/below terrain relative to item pivot. |
forceAlignToTerrain |
Forces alignment to terrain normal. |
snapSinkEnabled |
Enables sinking when snapping to terrain. |
snapSink |
Sink amount for snap operation. |
snapAnyForestItemType |
Snap all item types instead of selected types only. |
Paint mode places forest items randomly inside the brush circle.
The process roughly:
pressure.ForestBrushElement.probability.This produces natural randomized scatter.
Erase mode removes forest items inside the brush.
Modes:
| Mode | Description |
|---|---|
Erase |
Erases any forest item under the brush. |
EraseSelected |
Erases only selected/active forest item types. |
Erase amount is influenced by brush pressure.
Snap-to-terrain mode moves existing forest items onto terrain/static surface.
It can also:
This is useful after terrain edits or when items float/clip incorrectly.
The Forest tools include advanced biome placement workflows.
Biome tools can place or replace forest items based on:
These tools are useful for large-scale vegetation generation.
Example uses:
Forest items can store a tool context ID.
Examples include:
This lets tools identify which items were created by biome tools and selectively remove/replace only those items.
When saving, forest items are grouped by item type and written to:
levels/<levelName>/forest/<type>.forest4.json
The filename is made safe from the forest item type/internal name.
If an item type no longer has any items:
Forest data tracks whether it has been modified.
The editor uses this to know whether forest data needs saving.
Useful commands/methods include:
save()
reload()
clear()
regenCells()
isDirty()
Forest cells update their zone visibility state when scene zoning changes.
This allows forest cells to be culled correctly for indoor/outdoor visibility systems.
The Forest system exposes some debug stats:
$Forest::totalCells
$Forest::cellsRendered
$Forest::cellItemsRendered
$Forest::cellsBatched
$Forest::cellItemsBatched
These can help diagnose forest rendering performance.
Additional debug drawing can show forest cells and bounds.
{
"class": "Forest",
"name": "theForest",
"position": [0, 0, 0],
"rotationMatrix": [1, 0, 0, 0, 1, 0, 0, 0, 1],
"scale": [1, 1, 1],
"lodReflectScalar": 2
}
{
"pine_small": {
"class": "ForestItemData",
"internalName": "pine_small",
"shapeFile": "/levels/example/art/shapes/trees/pine_small.dae",
"collidable": true,
"radius": 1.5,
"snapRotationToTerrain": false,
"windScale": 1,
"trunkBendScale": 0.4,
"branchAmp": 1,
"detailAmp": 0.25,
"detailFreq": 1,
"mass": 5,
"rigidity": 10,
"tightnessCoefficient": 0.4,
"dampingCoefficient": 0.7
}
}
TSStatic for individual unique objects.radius to prevent overcrowding.windScale to 0 for rocks/static props..forest / .forest.json files after upgrading.Possible causes:
Forest object.forest4.json filesmanagedItemData.jsonForestItemData internal name mismatchshapeFilePossible causes:
ForestItemData.forest4.jsonPossible causes:
Check:
windScale is greater than 0ForestWindEmitter exists and is enabledUse Snap to Terrain, check item pivot, or adjust sink/depth offset.
Reduce sink values or check asset pivot.
Create or add a Forest object named theForest.
Forest is the main system for rendering and managing large numbers of repeated static items in a level.
It loads placement data from .forest4.json files, uses ForestItemData definitions from managedItemData.json, organizes items into spatial cells, supports culling and batching, can provide collision, and supports wind deformation for vegetation.
Use Forest for large-scale repeated natural assets, and use TSStatic for individually placed static meshes.
Was this article helpful?