Taos API Reference
    Preparing search index...

    Class Terrain

    A CDLOD heightmap terrain. By default a fully-resident finite slab that's easy to frame in the editor; set bounded to false with a large worldExtent for an "infinite" world that streams pages around the camera.

    Hierarchy (View Summary)

    Index

    Constructors

    Properties

    id: string = ...

    Stable identity for this component, unique within a session. Auto-generated for runtime-created components; the editor overwrites it with a persistent id when projecting a saved document so references survive save / load / undo.

    enabled: boolean = true

    Whether this component participates in simulation and rendering. When false, the GameObject skips its update/updateRender and the scene's render collectors (mesh renderers, camera, lights, …) ignore it — the component stays attached and keeps its state, like Unity's Behaviour.enabled / Renderer.enabled. Defaults to true.

    gameObject: GameObject

    The owning GameObject; assigned by addComponent before onAttach runs.

    _sceneAttached: boolean = false

    True between onAttach and onDetach — i.e. while this component sits on a GameObject that is part of a live Scene. Managed by GameObject. Internal — do not set directly.

    quality: TerrainQualityName = 'medium'

    Mesh + heightmap detail preset.

    heightScale: number = 200

    Vertical height-map scale in world units.

    worldExtent: number = 1024

    Square world extent in world units (the CDLOD root + VT page grid cover it).

    pagesPerSide: number = 8

    Virtual pages per side. For a bounded world pick a value whose square fits the resident slot count so the whole terrain stays resident.

    bounded: boolean = true

    When true (the default), every page is resident at once — a finite region always fully baked, so the whole terrain is visible from any angle without camera-centered streaming. Set false with a large worldExtent (e.g. 8192) for an "infinite" world that streams pages around the camera. Bounded needs pagesPerSide² ≤ resident slots.

    seed: number = 0

    World-generation seed; each value yields a different procedural pattern.

    wireframe: boolean = false

    Render the terrain as wireframe (debug).

    heightmapRef: string | null = null

    Authored heightmap asset ref (raw LE uint16 .r16 or grayscale image); null = procedural heights. The map covers the whole world rect.

    splatARef: string | null = null

    Splat weight maps: splatARef RGBA weights layers 0-3, splatBRef layers 4-7. Null = procedural height/slope splatting.

    splatBRef: string | null = null
    holeRef: string | null = null

    Hole mask asset ref (grayscale image; texel ≥ 50% = hole punched through render, shadows, picking and the physics collider). Null = no holes.

    colorRef: string | null = null

    Painted color/tint map asset ref (RGBA; rgb = overlay multiplier centered at 0.5, a = paint opacity). Null = no tinting.

    autoshader: boolean = false

    Autoshader hybrid: unpainted splat texels fall back to the procedural height/slope rule (layers 0-3) instead of the base layer.

    regionsDir: string | null = null

    Folder (relative to the project's Content/) holding sparse region height tiles named r{rx}_{rz}.r16 — raw LE uint16, (regionTexels+1)² samples (vertex convention; neighbors share their edge row). Non-null switches the terrain to the region-streamed source: heightmapRef is ignored, tiles load through resolveRegionBytes, and a missing file marks the region EMPTY (renders floorHeight). Region (0,0) covers world [0, regionSize)²; indices may be negative.

    regionSize: number = 512

    World meters per region side. Keep it a multiple of the VT page size (worldExtent / pagesPerSide).

    regionTexels: number = 256

    Interior sample cells per region side (tiles carry regionTexels+1 samples).

    regionRadius: number = 3

    Streaming ring radius in regions (window side = 2·radius + 1).

    streamingRing: number = 0

    VT page streaming ring override (0 = engine default). Region worlds with large pages raise it (with enough resident slots) so terrain stays baked further out.

    treeShadowImpostors: boolean = true

    Cast tree shadows from the cheap cone impostor instead of the full authored tree mesh (all cascades draw one batch instead of one per model primitive; the silhouette is close enough at sun angles). Only affects authored treeMeshRef models — the built-in pine is already a single cheap draw.

    floorHeight: number = 0

    World height outside the heightmap rect (sea level).

    layers: TerrainLayerDoc[] = []

    Authored material layers (up to MAX_LAYERS). Empty = the 4 procedural defaults. Changing the layer COUNT rebuilds the system.

    collision: boolean = true

    Build a static physics heightfield from the authored heightmap (needs heightmapRef; the physics module loads on demand).

    collisionResolution: number = 512

    Collider samples per side (power of two; clamped to [64, 2048]).

    grassEnabled: boolean = false

    Grow the grass detail layer.

    grassLayerMask: number = 0b0010

    Bit i set = splat layer i contributes grass density (0 = everywhere when no splatmap is bound).

    grassDensity: number = 1.2

    Blades per square meter where the masked weight is 1.

    grassHeight: number = 0.55

    Mean blade height in meters.

    grassDistance: number = 120

    Blades draw out to this camera distance (meters).

    treesEnabled: boolean = false

    Scatter the tree layer (built-in procedural pine mesh).

    treeLayerMask: number = 0b0010

    Bit i set = splat layer i can grow trees (0 = everywhere when no splatmap is bound).

    treeSpacing: number = 14

    Average spacing between trees in meters.

    treeDistance: number = 500

    Trees draw out to this camera distance (meters).

    treeMeshRef: string | null = null

    Authored tree model asset (.glb/.gltf); null = the built-in procedural pine. Distant trees always use the cheap impostor cone.

    resolveAssetBytes: ((ref: string) => Promise<ArrayBuffer>) | null = null

    Resolves the asset refs above to bytes. Set by the host at build time (the editor plugs a guid→Content-bytes resolver, the bundle player its AssetResolver); when null, refs are treated as fetchable URLs. Not serialized.

    resolveRegionBytes: ((name: string) => Promise<ArrayBuffer | null>) | null = null

    Region-tile reader injected by the host (editor: Content/ file reads; players: bundles/HTTP). Receives the tile FILE NAME (r{rx}_{rz}.r16); resolve against regionsDir. Return null for missing tiles (sparse). Not serialized.

    dataVersion: number = 0

    Bumped by edit tools after a height stroke so derived state (the physics heightfield) rebuilds from the modified data. Not serialized.

    system: TerrainSystem | null = null

    The live TerrainSystem while a terrain feature is driving this component, or null. Set by TerrainLodFeature; scripts can read it to drive the system directly (heightmap source, layer textures). Not serialized.

    Accessors

    • get time(): Time

      The simulation clock of the scene this component belongs to. Read inside update (or any time after the GameObject is added to a scene) for absolute time, frame count, FPS, and timeScale-aware delta — e.g. this.time.elapsed, this.time.delta, this.time.frameCount.

      this.time.delta equals the dt argument passed to update, so components can ignore that argument entirely and pull everything from here.

      Returns Time

      if the owning GameObject is not currently part of a scene.

    Methods

    • Connect to a Signal with automatic disconnect when this component is removed from its GameObject — the safe default for cross-object listening, so a destroyed component never leaks into (or gets called by) a signal it once observed. Typically called from onAttach:

      onAttach(): void {
      const health = this.gameObject.getComponent(Health)!;
      this.listen(health.died, () => this.playDeathEffect());
      }

      Type Parameters

      • A extends unknown[]

      Parameters

      Returns () => void

      The unsubscribe function, for listeners that also want to disconnect early; calling it is optional and idempotent.

    • Called when the component joins a live scene — from addComponent when the GameObject is already in a scene, otherwise when the GameObject is added to one. this.gameObject.scene (and scene.engine) is always set here. Override to acquire references to siblings/children or initialize resources.

      Returns void

    • Called every frame by the GameObject's update traversal.

      Parameters

      • _dt: number

        Frame delta time in seconds.

      Returns void

    • Called when this component's GameObject begins touching another body, with the GameObject it collided with. Dispatched by the physics system after each world step (only while playing), so handlers may freely mutate the scene. Requires a physics body (RigidBody / CharacterBody) on the object.

      Parameters

      • _other: GameObject

        The other GameObject involved in the contact.

      Returns void

    • Called every frame by the GameObject's render traversal, after update and any input/controller mutations to the transform. Override to refresh per-frame state that render passes consume (e.g. Camera recomputes its cached view/projection matrices here).

      Parameters

      • _ctx: RenderContext

        Active render context (provides canvas width/height etc.).

      Returns void