Recipes
Terrain basics ground heightmap and sculpting
You need a real outdoor ground the player walks on with elevation, not a flat box.
TerrainComponent is a placement/binding component: the geometry lives in a canonical terrain resource asset, and the component points an entity at it.engine v1.0.234since component-field-contract ecs.component-field-contract.v1, action-catalog.v1.0.232, terrain, rendering.v1Copy for LLM
Use this for
an outdoor ground surface; hills and valleys; a heightmap landscape the player walks on; binding a terrain resource to the world
Not for
flat indoor floors (use a box ColliderComponent plus a RenderableComponent); water surfaces (use WaterComponent)
Pairs with: Atmosphere sky lighting fog and time of day, Physics colliders rigid bodies triggers and joints, NPC and enemy navigation chase and patrol behavior
The recipe
- Create or obtain a terrain resource asset (prefer the catalog first, see asset-acquisition-strategy). The dedicated
terrain.resource.createaction isplanned(no AI/MCP tool is mapped for it yet); today an asset created viaproject_create_asset(project.asset.create) backs the binding. - Sculpt the heightmap:
project_apply_terrain_semantic_patch(terrain.patch.apply) applies a terrain semantic patch (raise, lower, flatten, paint layers) to the resource. This is the active, AI-exposed editing verb. - Build the render and collision artifacts:
terrain_build_artifacts(terrain.artifacts.build) turns the sculpted resource into the LOD meshes and collision the runtime consumes. - Bind it to an entity: attach
TerrainComponent{ "type":"TerrainComponent", "enabled": true, "terrainAssetId": <asset id> }withproject_add_component.terrainAssetIdis required and must be a valid asset id. - Sample the terrain from scripts with the
rendering.v1host ops:ctx.terrain.heightAt,ctx.terrain.normalAt,ctx.terrain.slopeAt,ctx.terrain.raycastDown,ctx.terrain.sampleLayerWeights(for placing props on the surface or gating steep slopes).
Pitfalls
TerrainComponentalone renders nothing without a builtterrainAssetId; sculpt and build the resource first, then bind.terrainAssetIdis required (not optional) and pattern-checked as an asset id; a bad id fails validation.- Do not expect terrain to add feature depth beyond placement/projection; the component contract is intentionally thin.
- Nav agents (see npc-enemy-navigation) need the terrain's collision artifacts built to path over it.
Verify
engine_get_component_schemaonTerrainComponent(two fields:enabled,terrainAssetId).project_get_graph_snapshotto confirm the entity carries the terrain binding.qa_capture_renderer_viewportto confirm the landscape renders with elevation.