Skip to content

Terrain

Galatrix has a smooth‑voxel Terrain editor — the Roblox‑Studio model, not Unity heightmaps. Terrain is a grid of voxels that each store an occupancy (how full, 0–255) and a material; the engine contours a smooth surface from them. Because it's volumetric, the Subtract tool can dig caves and overhangs a heightmap can't. It works everywhere: the editor play‑test, standalone builds, and multiplayer (the server builds the same collision, so players walk the same hills).

Open the editor with ?example=terrain for a ready‑made island — hills, a swimmable lake, and boulders — then open the Terrain window (Windows → Terrain) to sculpt it.

Terrain is a GameObject

Each terrain is a real object in the Hierarchy (⛰), not a hidden map‑wide field — so a map can hold several terrains, each a bounded tile you place and size like a Unity terrain. Select one and the Inspector configures it:

  • Name and Position (the transform — move it with the gizmo; render, colliders, and NavMesh all follow).
  • Size (W × H × L) — the terrain's bounds box (a blue wireframe in the viewport). Generate fills it and sculpting clamps to it, so a terrain stays the size you set. Default 128 × 64 × 128.
  • Voxel Size — world units per voxel (the resolution).
  • Default Generate settings — biome / relief / roughness / seed, plus a Generate button that fills the Size box.

The active terrain — the one the Terrain window sculpts and the Inspector edits — is simply the terrain selected in the Hierarchy (a single‑terrain map just works with no selection). Add another with + New Terrain in the Terrain window, or delete a terrain object to remove it. Terrains save with the map and render in every runtime, each at its own position.

The Terrain window

Everything lives in one window. Pick a tool, then drag on the terrain in the viewport (a wireframe sphere shows the brush). New maps start empty — click New Flat, Test Hill, or Generate… to get a surface, then sculpt.

Sculpt tools

ToolWhat it does
RaiseAdds material — build up hills, mounds, walls. Raising empty space starts fresh terrain.
LowerCarves material away — dig holes, caves, trenches, overhangs.
GrowExpands existing terrain outward one shell per pass (inherits the neighbour material).
ErodeWeathered removal — eats exposed edges faster than flat ground, for a natural look.
SmoothAverages the surface — softens sharp transitions.
FlattenLevels toward the height you first click — build pads, roads, foundations.
PaintRecolours the surface material without changing the shape.

Radius and Strength sliders control the brush; the material palette (13 built-in materials — grass, rock, sand, mud, snow, ground, slate, concrete, asphalt, glacier, salt, lava, water — plus any custom materials you add) sets what Raise / Flatten / Paint apply. Every stroke is one undo step (Ctrl+Z).

Custom materials (Unity terrain-layer style): the swatch at the end of the palette creates a new material with its own name, colour, and textures — up to 19 per terrain on top of the built-ins. Select a custom swatch to get a name field, a colour picker, and a remove button right under the palette; its Texture / Normal / Rough / Metal rows work exactly like a built-in's. Custom materials paint, splat-blend, save, and publish like any built-in (they're purely visual — water/swim and nav still key off the built-in water material). Removing one hides it from the palette but already-painted ground keeps its look.

Paint blending & filters. For the Paint tool, Strength becomes Opacity, and it paints TRUE splat weights (Unity-style): every voxel stores a primary + secondary material and a blend weight the renderer lerps, so 1.0 replaces outright while lower values lay down a genuinely translucent layer — strokes build up like an airbrush, and painting past full saturation makes the new material the primary. A Falloff select (Smooth / Linear / Sharp) shapes how every brush fades toward its rim, and the Edge Noise slider makes the painted border dissolve in natural ragged fingers/patches (a real snow line) instead of a perfect radial fade — its scale field sets how broad the patches are. Two Paint Filters mask where paint applies (blank = no limit): a Height band (only paint within a height range, e.g. snow up high) and a Slope° range (0 = flat … 90 = vertical, e.g. rock only on cliffs). Together they let you auto-blend biomes. Gameplay (water/swim, nav areas) always follows the primary material — a light wash of water on rock is just a look, not a swim zone.

Material textures

Out of the box, terrain is textured with the built-in block textures (grass, stone, sand, dirt, snow…) — the terrain object's Inspector has a Built-in textures checkbox (on by default). These are bundled engine assets served from /textures/blocks/, so they add nothing to your map's size and are never touched by the export prune. Turn the checkbox off for flat palette colours instead. Standalone builds ship no engine file tree, so the exporter embeds the handful of block textures your terrain actually renders (a few KB) straight into the HTML — exported games stay textured offline, and maps without terrain add nothing.

To override a slot with your own surface, select its swatch and, in the Texture dropdown below the palette, pick a project texture asset (import textures in the Project/Assets panel first) — a slot's own texture always wins over the built-in. The texture is triplanar‑mapped — projected from all three axes and blended by the surface normal — so it wraps cleanly over hills, cliffs, and overhangs with no UV seams. The tiling field sets how many world units one texture tile covers (smaller = more repeats). A textured swatch shows its thumbnail with a small T badge; choose — none — to go back to a flat colour. Textures live in the map's assets (not the engine build), so they only add to a map you choose to texture, and they render identically in the editor, play‑test, standalone, and published multiplayer.

PBR maps (normal · roughness · metalness)

Below the Texture row, each material also takes the full set of physically‑based maps — all triplanar‑blended at the same tiling:

  • Normal — a tangent‑space normal map that adds lit surface relief (bumps, grain, cracks) without any extra geometry. The strength field beside it scales the effect (0 = flat, ~2 = strong). This is the biggest visual upgrade: a flat surface picks up detailed light‑and‑shadow from the map.
  • Rough — a grayscale roughness map (0 = glossy, 1 = matte). With — scalar — selected, the number beside it sets a constant roughness for the whole material instead (default 0.95).
  • Metal — a grayscale metalness map, or a constant scalar (default 0), for shiny metallic surfaces.

All of these are project texture assets (import once, reuse across materials), stored in the map's assets — never the engine build — so they keep builds small and render identically across every runtime.

Texture Filtering (sharpness)

The terrain object's Inspector has a Texture Filtering dropdown (Off → Ultra) — this is anisotropic filtering, the big lever for how sharp the ground textures look at grazing angles and into the distance. Ultra (16×) is the default and the crispest; drop it toward Off (1×) only to claw back a little performance on very large terrains. (There's no separate splatmap/control‑texture resolution like Unity's heightmap terrain — materials are assigned per voxel and sampled in world space, so the remaining sharpness knobs are the source image's resolution and the material's tiling.)

Grass (terrain details)

Unity's terrain-detail grass, on smooth-voxel terrain. Pick the Grass tool and paint waving grass straight onto the ground — it's a painted density (an airbrush that builds up per stroke, like Paint's opacity), stored per voxel and rendered as instanced blades that sit exactly on the sculpted surface, including cave floors and overhang shelves.

  • Layers (Unity's detail prototypes): + adds a layer with its own blade sprite (the built-in procedural blade by default — zero build size — or any project texture via drag-and-drop), Billboard toggle (camera-facing vs crossed quads), Min/Max Width/Height per-blade size range, Healthy/Dry colours blended in noise patches (Spread = patch size), and a name. ✕ removes a layer from the palette — painted grass keeps its data but stops rendering, and the next + reuses the slot.
  • Layers are independent density maps (Unity's per-detail model): paint flowers straight through a grass meadow — grass types mix on the same ground, and painting one layer never changes another.
  • Erase removes the selected layer only (Unity semantics); other layers' grass is untouched.
  • The shared Opacity / Falloff / Edge Noise / Height / Slope filters all apply — paint a ragged meadow edge, or grass only below the snow line and off the cliffs.
  • Per-terrain settings (Inspector): Grass Wind (speed / size / bending — blades sway in the shader, tips lean while roots stay planted), Grass Distance (blades fade out and whole chunks stop drawing past it), and a global Density scale (0–3).
  • Grass is purely visual: no colliders, no NavMesh impact, nothing on the multiplayer server. It grows on up-facing land only — never on cliffs or water. Sculpting away ground removes its grass; painting never reshuffles existing blades.

Trees (prefab brush)

The Trees tool scatter-stamps a prefab onto the terrain surface — pick one in the dropdown or drag a prefab in from the Project panel. Unlike grass, trees are real objects: each stamp spawns the prefab as ordinary entities (tagged tree), so they keep their colliders, physics, scripts, and NavMesh impact, they save with the map, and you can still select/move/delete them individually afterwards.

  • Density (the Opacity slider) sets trees per stamp (1–3); each tree gets a random yaw and a small scale variation so a forest doesn't look copy-pasted.
  • Placement raycasts down onto the terrain and skips cliffs (steep ground), flooded ground (nothing plants below the waterline), and spots too close to an existing tree.
  • Erase removes tree-tagged objects under the brush — hand-placed entities are never touched.
  • Each brush stroke is one undo step.

The AI editor places trees the same way any object goes down — spawnPrefab at surface positions — not through sculptTerrain.

Generate & Import

  • Generate… — a seeded procedural landscape: pick a biome (plains / desert / snow / canyon), relief, roughness, and seed, then Generate. It fills the active terrain's Size box (set the footprint + height in the Inspector's Size field). The result is auto‑painted by height and slope (sand shores → grass → rock cliffs → snow peaks).
  • Import… — build terrain from a heightmap image: brighter pixels become higher ground.
  • Clear Terrain — removes it (undoable).

Water

Water is a terrain material. The Water section floods every air voxel below a Sea Level height, making lakes and seas. Water renders as a translucent surface and is not solid — players swim through it (the existing buoyancy/drag), they don't stand on it. Drain removes all water.

Region

Note: Region Copy/Paste carries the terrain's shape + primary material only — painted texture blends and grass are not copied; a paste lands as clean-painted ground.

Pick corners on terrain to box‑select an area (the yellow wireframe), then:

  • Fill it solid with the current material, or Carve it to air.
  • Copy the box and Paste it elsewhere (duplicate a hill or a rock formation).
  • Replace one material with another inside the box.

Generate → sculpt the big landforms (Raise/Lower) → Smooth → Flatten your gameplay areas → Paint materials → paint Grass → add Water → brush Trees and drop meshes (rocks, buildings) → playtest. Walk the hills, swim the lake, fall into a carved cave.

NPCs on terrain

The NavMesh bake covers terrain automatically — a NavMeshAgent NPC paths across hills and around water (agents don't walk onto a lake). No extra setup: sculpt the ground, add an agent, it walks it.

Building terrain with AI

The AI editor (the chat panel, or applyAi) can author terrain from a prompt — "make a snowy mountain with a frozen lake". It uses these actions:

json
{ "op": "createTerrain", "name": "Island", "position": [96, 0, 0], "size": [96, 48, 96] }
{ "op": "generateTerrain", "terrain": "Island", "seed": 7, "reliefHeight": 18, "biome": "snow" }
{ "op": "sculptTerrain", "terrain": "Island", "tool": "subtract", "center": [96, 14, 0], "radius": 5, "strength": 1 }
{ "op": "paintTerrain", "terrain": "Island", "region": { "min": [90, 0, -6], "max": [102, 30, 6] }, "material": "rock" }
{ "op": "waterTerrain", "terrain": "Island", "seaLevel": 6 }
{ "op": "setTerrainMaterial", "terrain": "Island", "material": "rock", "texture": "RockAlbedo", "normalMap": "RockNormal", "tiling": 3, "roughness": 0.9 }
{ "op": "setTerrainMaterial", "terrain": "Island", "newMaterial": "Moss", "color": [0.2, 0.8, 0.3] }
{ "op": "setTerrainDetailLayer", "terrain": "Island", "newLayer": "Meadow", "healthyColor": [0.4, 0.7, 0.2], "wind": { "bending": 0.2 } }
{ "op": "sculptTerrain", "terrain": "Island", "tool": "grass", "center": [96, 12, 0], "radius": 10, "strength": 0.8, "layer": "Meadow", "noise": 0.5 }
{ "op": "clearTerrain", "terrain": "Island" }

setTerrainMaterial sets how a palette material looks everywhere it's used — assign imported texture assets (albedo + the normalMap / roughnessMap / metalnessMap PBR maps) and/or a color tint. Only reference textures that already exist in the map's assets (a missing name is reported as an error). Pass newMaterial (instead of material) to create a custom material — afterwards sculptTerrain / paintTerrain reference it by that name like any built-in.

Every op takes an optional terrain (name or id) to pick which terrain — omit it for the active/first one (auto‑created on first write). createTerrain places a new empty tile you then Generate into. center and region are world coordinates (converted to the target terrain's local space, so place terrains anywhere); generateTerrain fills that terrain's Size box. material accepts a name or an id; every action is one undo step.

Notes

  • Terrain shape is pure data (RLE‑compressed voxels) — it barely adds to build size. Materials are procedural colours by default; any textures you assign live in the map's texture assets, never the engine build.
  • Sculpting during a play‑test rebuilds only the chunks you touched; entering Play rebuilds terrain colliders from the current voxels.
  • This smooth Terrain is separate from the blocky World Generator (Minecraft‑style cubes) — different tools for different looks.