Skip to content
smartargs
VantageDocumentation

Terrain cliffs reference

The scene grid, the cliff map and its wall styles, the cell data, and the ground height API. For how to use it, see Terrain cliffs.

VtCliffMap

Component. Add it with Add Component → Vantage → Terrain → VtCliffMap. Adds VtWorldGrid automatically.

Grid-based cliffs for a scene: every cell of the VtWorldGrid on the same object holds a whole level, cliffs appear where neighbouring levels differ and flagged cells become ramps. With a Unity Terrain the map writes its levels into the heightmap and either paints a cliff layer along the slopes or stands wall meshes on the edges, see VtCliffTerrainMode. Without a terrain it builds its own ground and walls through a VtCliffStyle. Paint it with the Cliff Editor tool in the Scene view. Place one per scene.

Inspector fields

Field Type Default Range Description
Grid (grid) VtCliffGrid — Level, ramp and blocked flag of every cell. Paint it with the Cliff Editor tool in the Scene view.
Level Height (levelHeight) float 2 ≥ 0.1 World height of one level.
Terrain (terrain) Terrain None Terrain that carries the ground. Its heightmap is rewritten under every cell that touches a cliff or ramp. Empty builds a ground mesh instead.
Terrain Mode (terrainMode) VtCliffTerrainMode PaintedSlopes Painted Slopes: the heightmap slope is the cliff and Cliff Layer is painted along it. Wall Meshes: the style builds walls on the edges.
Cliff Layer (cliffLayer) TerrainLayer None Terrain layer painted along every level change in Painted Slopes mode. Added to the terrain when missing.
Ground Layer (groundLayer) TerrainLayer None Terrain layer that takes over where a cliff was painted before and is gone now. Optional; the texel’s other layers are used when it has any.
Slope Width (slopeWidth) float 1.5 ≥ 0 World width of the slope between two levels in Painted Slopes mode, centred on the cell edge. Wider is gentler and stretches the cliff texture less. Capped at one cell.
Cliff Paint Padding (cliffPaintPadding) float 0.25 ≥ 0 Extra width of the painted cliff band on each side of the slope, in world units, so the rock wraps over the lip.
Style (style) VtCliffStyle None How the walls look in Wall Meshes mode and without a terrain. Empty uses plain procedural walls.
Generate Ground Without Terrain (generateGroundWithoutTerrain) bool On Without a terrain, also generate a walkable ground mesh at each cell’s level.

Scripting API

Member Description
static VtCliffMap Instance { get; } The scene’s cliff map, or null when none is placed.
VtCliffGrid Grid { get; } The level data.
float LevelHeight { get; } World height of one level.
Terrain Terrain { get; } The terrain the map writes into, or null.
VtCliffTerrainMode TerrainMode { get; } How cliffs show on the terrain. Irrelevant without one.
TerrainLayer CliffLayer { get; } Terrain layer painted along cliffs in Painted Slopes mode.
TerrainLayer GroundLayer { get; } Terrain layer restored where a painted cliff disappears.
VtCliffStyle Style { get; } The style in use; the shared procedural default when none is assigned.
VtWorldGrid WorldGrid { get; } The grid this map is laid out on.
float CellSize { get; } Cell edge in world units, from the world grid.
float BuildCellSize { get; } Build cell edge in world units, from the world grid. Footprints count in these cells.
Vector3 Origin { get; } World corner of cell (0, 0). Its Y is level zero.
bool NeedsGroundMesh { get; } True when the map has no terrain and builds its own ground mesh.
bool BuildsWalls { get; } True when the style builds wall meshes: always without a terrain, and with one in Wall Meshes mode.
bool PaintsTerrain { get; } True when the map paints a cliff layer on the terrain.
Transform GeneratedRoot { get; } The generated child holding walls and ground, or null before the first build.
float TerrainSampleSpacing { get; } Distance between two heightmap samples of the assigned terrain, in world units. 0 without a terrain.
float RimDepth { get; } How far the rock rim on top of a wall mesh reaches into the higher cell: twice the terrain’s sample spacing, where the heightmap slope can lie. 0 without a terrain or in Painted Slopes mode.
float TerrainAlphamapTexel { get; } Size of one control-map texel of the assigned terrain, in world units. 0 without a terrain.
float SlopeWidth { get; } World width of the slope between two levels in Painted Slopes mode, capped at one cell. 0 in other modes.
float CliffBandWidth { get; } Width of the painted cliff band on each side of a level change: half the slope width, half a heightmap sample for the discretisation, plus the padding, and never under three quarters of a control-map texel so every drop reaches a texel row.
int RecommendedHeightmapResolution { get; } Heightmap resolution that keeps the slope under an eighth of a cell: the smallest power of two plus one, capped at 4097.
bool NeedsRebuild { get; } True when the levels, ramps, cell size, level height or mode changed since the last build, for example through undo.
bool TerrainNeedsSync { get; } True when the terrain heights under the slopes were written for other levels, ramps or slope settings than the current ones.
Rect WholeRegion { get; } World rectangle of the whole map.
int RecommendedAlphamapResolution { get; } Control-map resolution that matches RecommendedHeightmapResolution: one texel per heightmap step, capped at 4096.
event Action OnRebuilt Fires after Rebuild or RebuildGeometry replaced the generated geometry.
const string GeneratedRootName Name of the generated child that holds walls and ground. Never saved; rebuilt on load.
const string BlockedRootName Name of the child of GeneratedRoot that holds the NavMesh volumes over blocked cells.
const int NotWalkableArea NavMesh area index of Unity’s built-in Not Walkable area.
Vector2Int WorldToCell(Vector3 world) Cell under a world point.
Vector3 CellToWorldCenter(Vector2Int cell) World centre of a cell at its ground level.
int GetLevelAtWorld(Vector3 world) Whole level of the cell under a world point; 0 outside the map.
float SampleHeight(Vector3 world) World height of the cell’s level under a point, including ramp slopes. Outside the map returns level zero. This is the grid’s idea of the ground and ignores sculpting; use SampleGroundHeight to place things on the actual surface.
float SampleGroundHeight(Vector3 world) World height of the actual ground under a point: the terrain surface, sculpting and slopes included, where the terrain covers the point, otherwise SampleHeight.
bool IsBlockedAtWorld(Vector3 world) True when the cell under a world point is blocked.
bool AnyBlocked(IEnumerable<Vector2Int> cells) True when any of the cells is blocked.
bool IsOnOneFlatLevel(IEnumerable<Vector2Int> cells) True when every cell is flat and on the same level, so a footprint over them sits on one plane. Cells outside the map count as flat level zero. Ramps fail.
List<Vector2Int> CellsUnder(Vector3 worldCenter, Vector2Int footprintCells, float yawDegrees) Cells covered by a footprint centred on a world point, counted in BuildCellSize cells.
List<Vector2Int> CellsUnder(Vector3 worldCenter, Vector2Int footprintCells, float yawDegrees, float footprintCellSize) Every map cell a footprint overlaps. The footprint is footprintCells times footprintCellSize world units, centred on worldCenter; quarter turns swap its X and Z. A footprint that only touches a cell edge does not cover the cell beyond it, and one that covers part of a cell covers that cell.
Rect WorldRegion(IEnumerable<Vector2Int> cells, int marginCells) World rectangle on the XZ plane covering the given cells, grown by marginCells on every side.
void Rebuild() Replace the generated geometry, rewrite the terrain the map owns and repaint every cliff.
void RebuildGeometry() Replace the generated geometry and blocked-cell volumes only. Never touches the terrain.
int SyncOwnedTerrain() Write the terrain heights the map owns: the slope bands and ramps in Painted Slopes mode, every cell beside a wall or ramp in Wall Meshes mode. Sculpted ground outside them is kept.
int SyncTerrain(Func<Vector2Int, bool> cellFilter) Write terrain heights under the cells that pass the filter; null writes the whole map.
bool SyncTerrainIfChanged() Sync and repaint the terrain only when TerrainNeedsSync. Returns true when it wrote.
void SyncTerrainRegion(IEnumerable<Vector2Int> cells) Update the terrain under the given cells and their neighbours: heights first, then the painted cliff layer. The terrain’s LOD update is postponed until FinishTerrainEdit, so call that once a stroke ends.
void FinishTerrainEdit() Let the terrain finish the LOD work postponed by SyncTerrainRegion, and record the terrain as matching the levels.
int PaintTerrain(Rect worldRegion) Paint the cliff layer along every level change inside a world rectangle. Does nothing unless PaintsTerrain.
void Resize(int width, int height) Change the map size in cells, keeping existing cells, then rebuild.
bool FitToTerrain() Move the grid origin to the terrain’s corner and size the grid so its cells cover the whole terrain, rounding up to whole cells. Returns false without a terrain.
bool ApplyRecommendedHeightmapResolution() Change the terrain’s heightmap resolution to RecommendedHeightmapResolution, raise its control-map resolution to RecommendedAlphamapResolution when it is lower, then write every level back and repaint. Unity clears the heightmap and the painted layers when their resolution changes, so sculpting and texture painting are lost. Returns false without a terrain.
void SetTerrain(Terrain value) Set the terrain from code, then rebuild.
void SetTerrainMode(VtCliffTerrainMode value) Set the terrain mode from code, then rebuild.
void SetSlopeWidth(float value) Set the painted slope width from code, then rebuild.
void SetTerrainLayers(TerrainLayer cliff, TerrainLayer ground) Set the painted layers from code, then rebuild.
void SetStyle(VtCliffStyle value) Set the style from code, then rebuild.
void SetLevelHeight(float value) Set the level height from code, then rebuild.
bool ApplyFromNet(int[] levels, bool[] ramps) Mirror replicated or loaded levels and ramps, then rebuild. Blocked cells are kept. Arrays must match the grid size.
bool ApplyFromNet(int[] levels, bool[] ramps, bool[] blocked) Mirror replicated or loaded levels, ramps and blocked cells, then rebuild. The terrain is only rewritten when the levels or ramps differ from what it holds. Arrays must match the grid size; a null blocked keeps the blocked cells.

VtWorldGrid

Component. Add it with Add Component → Vantage → World → VtWorldGrid.

The one ground grid of a scene. Building snaps to it and terrain cliffs are laid out on it, so a wall footprint and a cliff cell always agree. Place one per scene; its transform position is the grid origin and CellSize the cell edge in world units. BuildSubdivisions splits each cell for building, so terrain can keep large cells while pieces snap finer; build lines always include the cell edges. Systems that need a grid read Instance and fall back to a one-unit grid at the world origin when the scene has none.

Inspector fields

Field Type Default Range Description
Cell Size (cellSize) float 1 ≥ 0.05 Edge of one cell in world units. Cliff cells use it; building uses it divided by Build Subdivisions.
Build Subdivisions (buildSubdivisions) int 1 ≥ 1 How many build cells fit along one cell edge. 2 on 2-unit cells lets building snap to 1 unit while cliffs keep 2-unit cells.

Scripting API

Member Description
static VtWorldGrid Instance { get; } The scene’s grid, or null when none is placed.
float CellSize { get; } Edge of one cell in world units.
int BuildSubdivisions { get; } How many build cells fit along one cell edge. At least 1.
float BuildCellSize { get; } Edge of one build cell in world units: CellSize divided by BuildSubdivisions.
Vector3 Origin { get; } World position of the corner of cell (0, 0).
static float SceneCellSize { get; } Cell size of the scene grid, or DefaultCellSize without one.
static float SceneBuildCellSize { get; } Build cell size of the scene grid, or DefaultCellSize without one.
static Vector3 SceneOrigin { get; } Origin of the scene grid, or the world origin without one.
const float DefaultCellSize Cell size used when the scene has no grid.
static float ResolveCellSize(float overrideCellSize) Build cell size to use: overrideCellSize when above zero, otherwise the scene grid’s BuildCellSize.
void SetCellSize(float size) Set the cell size from code. Cliff maps rebuild on their next edit.
void SetBuildSubdivisions(int subdivisions) Set how many build cells fit along one cell edge. Cliffs are unaffected.
Vector2Int WorldToCell(Vector3 world) Cell containing a world point, on the XZ plane.
Vector3 CellToWorldCenter(Vector2Int cell) World centre of a cell, at the grid’s height.
Vector3 CellToWorldCorner(Vector2Int cell) World position of a cell’s minimum corner, at the grid’s height.
static Vector2Int WorldToCell(Vector3 world, Vector3 origin, float cellSize) Cell containing a world point for an explicit origin and cell size.
static Vector3 CellToWorldCenter(Vector2Int cell, Vector3 origin, float cellSize) World centre of a cell for an explicit origin and cell size.
static Vector3 CellToWorldCorner(Vector2Int cell, Vector3 origin, float cellSize) World minimum corner of a cell for an explicit origin and cell size.

VtCliffProceduralStyle

Asset. Create it with Create → Vantage → Terrain → Cliff Style (Procedural). Inherits VtCliffStyle.

Cliff walls generated as one mesh with a tiling material. Needs no models: assign a rock material, or leave it empty for a plain grey. The default style of a map with no style assigned.

Inspector fields

Field Type Default Range Description
Wall Material (wallMaterial) Material None Material on the walls. Empty uses a plain grey. A triplanar or world-space tiling shader hides the stretching on tall walls.
Ground Material (groundMaterial) Material None Material on the generated ground, used only when the map has no terrain. Empty uses the wall material.
Uv Scale (uvScale) float 2 ≥ 0.01 World units per texture repeat.
Add Collider (addCollider) bool On Add a mesh collider so units path around walls and cursor rays hit them.

Scripting API

Member Description
override void Build(VtCliffMap map, Transform root) Build the walls and rims as one mesh with the wall material, plus the ground mesh when the map has no terrain.

VtCliffKitStyle

Asset. Create it with Create → Vantage → Terrain → Cliff Style (Kit). Inherits VtCliffStyle.

Cliff walls assembled from modelled pieces, the way tile-based map editors do it. Author each piece one cell wide and one level high in a unit box: local X runs along the wall from left to right, local Y is up, and the front faces local -Z. The style scales pieces to the map’s cell size and level height. Any shape the kit has no piece for is built procedurally with fallbackMaterial.

Inspector fields

Field Type Default Range Description
Wall Piece (wallPiece) GameObject None One cell wide, one level high, flat top and bottom. Stacked for taller walls.
Ramp Side Rising (rampSideRising) GameObject None Triangle that rises from nothing at the left to one level at the right. Sits beside a ramp. Optional.
Ramp Side Falling (rampSideFalling) GameObject None Triangle that falls from one level at the left to nothing at the right. Sits beside a ramp. Optional.
Piece Size (pieceSize) Vector3 (1, 1, 1) Size of the authored pieces. (1, 1, 1) means a unit box; the style divides by it when scaling.
Fallback Material (fallbackMaterial) Material None Material for shapes the kit has no piece for, and for the generated ground when the map has no terrain.
Uv Scale (uvScale) float 2 ≥ 0.01 World units per texture repeat on procedural fallback geometry.
Add Fallback Collider (addFallbackCollider) bool On Add a mesh collider to procedural fallback geometry. Kit pieces keep their own colliders.

Scripting API

Member Description
override void Build(VtCliffMap map, Transform root) Place the kit pieces along every wall, build the shapes the kit has no piece for procedurally, and add the ground mesh when the map has no terrain.

VtCliffStyle

Abstract asset base. Shipped subclasses: VtCliffKitStyle, VtCliffProceduralStyle.

How a cliff map looks. The map hands a style its grid and an empty root; the style fills the root with renderers and colliders. Subclass to place your own art; the package ships VtCliffProceduralStyle for textured walls and VtCliffKitStyle for modelled pieces.

Scripting API

Member Description
static Material FallbackMaterial { get; } A plain lit material for styles with no material assigned. Created once, never saved.
abstract void Build(VtCliffMap map, Transform root) Populate root for the map. The root is empty and parented under the map, at the grid origin.
protected static GameObject CreateMeshChild(Transform root, string childName, VtCliffMeshData data, Material material, bool withCollider) Create a child with a mesh filter, renderer and optional collider from mesh data. Returns the child.
protected static void BuildGroundIfNeeded(VtCliffMap map, Transform root, Material material, float uvScale, bool withCollider) Build a ground mesh child when the map has no terrain to carry the levels.

VtCliffGrid

Serializable class.

The level data behind a cliff map: one integer level per cell plus a ramp flag and a blocked flag. Levels are clamped to 0..MaxLevel. Cells outside the grid read as their nearest neighbour’s level, so the map edge never grows a wall.

Inspector fields

Field Type Description
Width (width) int Cells along X.
Height (height) int Cells along Z.
Max Level (maxLevel) int Highest level a cell can hold.
Levels (levels) int[] Level of every cell, row by row along Z. Paint it with the Cliff Editor tool.
Ramps (ramps) bool[] Ramp flag of every cell, row by row along Z. A flagged cell becomes a ramp when the neighbour on one side is one level higher and the one opposite is on its level.
Blocked (blocked) bool[] Blocked flag of every cell, row by row along Z. Units cannot walk or build on a blocked cell.

Scripting API

Member Description
int Width { get; } Cells along X.
int Height { get; } Cells along Z.
int MaxLevel { get; } Highest level a cell can hold.
bool HasBlockedCells { get; } True when any blocked cell exists.
event Action<Vector2Int> OnCellChanged Raised whenever a cell changes, with the cell.
bool Contains(int x, int z) True when the cell lies inside the grid.
bool Contains(Vector2Int cell) True when the cell lies inside the grid.
int GetLevel(int x, int z) Level of a cell; 0 outside the grid.
int GetLevel(Vector2Int cell) Level of a cell; 0 outside the grid.
bool SetLevel(int x, int z, int level) Set a cell’s level, clamped to the allowed range. Returns true when it changed.
bool SetLevel(Vector2Int cell, int level) Set a cell’s level, clamped to the allowed range. Returns true when it changed.
bool Raise(Vector2Int cell) Raise a cell by one level.
bool Lower(Vector2Int cell) Lower a cell by one level.
bool IsRampFlagged(int x, int z) Whether a cell is flagged as a ramp. The flag only takes effect when the neighbours form a valid ramp, see TryGetRamp.
bool IsRampFlagged(Vector2Int cell) Whether a cell is flagged as a ramp.
bool SetRamp(int x, int z, bool ramp) Flag or unflag a cell as a ramp. Returns true when it changed.
bool SetRamp(Vector2Int cell, bool ramp) Flag or unflag a cell as a ramp. Returns true when it changed.
bool IsBlocked(int x, int z) True when units may not walk or build on the cell, whatever its level. False outside the grid.
bool IsBlocked(Vector2Int cell) True when units may not walk or build on the cell, whatever its level. False outside the grid.
bool SetBlocked(int x, int z, bool value) Block or open a cell. Returns true when it changed.
bool SetBlocked(Vector2Int cell, bool value) Block or open a cell. Returns true when it changed.
static Vector2Int Neighbor(Vector2Int cell, VtCliffDirection direction) Neighbour cell in a direction.
static VtCliffDirection Opposite(VtCliffDirection direction) The opposite direction.
int GetNeighborLevel(Vector2Int cell, VtCliffDirection direction) Level of the neighbour in a direction. Outside the grid returns the cell’s own level.
bool TryGetRamp(Vector2Int cell, out VtCliffDirection uphill) Whether the cell is a working ramp: flagged, with the neighbour on one side exactly one level up and the neighbour opposite on the cell’s own level. uphill points towards the higher side.
VtCliffCellShape GetShape(Vector2Int cell) Classify a cell against its neighbours.
float SampleLevel(Vector2Int cell, float u, float v) Ground height at a point inside a cell, in levels. Flat and edge cells return the cell level; a ramp rises from its level to one above along the uphill axis. u and v run 0..1 across the cell on X and Z.
bool HasWall(Vector2Int cell, VtCliffDirection direction) True when a wall stands along the cell’s edge in a direction: the neighbour is on another level and no working ramp joins the two across that edge.
bool IsHeightOwned(Vector2Int cell) True when the cell is a ramp, touches a wall, or borders a ramp. Its ground height then belongs to the cliff map.
void Resize(int newWidth, int newHeight) Resize the grid, keeping the overlapping cells. New cells start at level 0.
void SetMaxLevel(int value) Change the highest allowed level, clamping existing cells down to it.
void EnsureStorage() Make the serialized arrays match the size fields after a broken deserialization.
int ComputeContentHash() A hash of size, levels, ramps and blocked cells. Two grids with the same content hash alike; cheap enough to compare after every undo.
int ComputeShapeHash() A hash of size, levels and ramps only: everything that shapes the ground. Blocked cells do not change it.
int[] LevelsCopy() Raw levels, row-major by Z then X. For save files and replication.
bool[] RampsCopy() Raw ramp flags, row-major by Z then X. For save files and replication.
bool[] BlockedCopy() Raw blocked flags, row-major by Z then X. For save files and replication.
bool Load(int[] newLevels, bool[] newRamps) Replace every level and ramp at once, keeping the blocked cells. Arrays must match Width * Height.
bool Load(int[] newLevels, bool[] newRamps, bool[] newBlocked) Replace every level, ramp and blocked flag at once. Arrays must match Width * Height; a null newBlocked keeps the blocked cells.

VtGroundHeight

Static class.

Height of the ground under a point, for visuals that lie on the relief such as range rings and grid patches: the VtCliffMap surface when the scene has one, else the first surface a downward ray hits on surfaceMask, else the fallback height.

Scripting API

Member Description
const float RayStartHeight How far above the point the downward ray starts, and half its length.
static float Sample(Vector3 world, LayerMask surfaceMask, float fallbackY) World height of the ground under world. fallbackY is returned when there is no cliff map and nothing on surfaceMask lies under the point.

Enums

VtCliffTerrainMode

How a cliff map shows its cliffs on a Unity Terrain.

Value Description
PaintedSlopes The heightmap slope is the cliff and a cliff terrain layer is painted along it. No meshes.
WallMeshes Wall meshes from the style stand on the cell edges, with a rim that hides the heightmap slope.

VtCliffDirection

One of the four edges of a cliff cell.

Value Description
North Towards positive Z.
East Towards positive X.
South Towards negative Z.
West Towards negative X.

VtCliffCellShape

How a cliff cell sits against its neighbours.

Value Description
Flat Every neighbour is on the same level, or the map edge. Flat ground.
Edge At least one neighbour is on another level. A wall runs along that edge.
Ramp A ramp cell: sloped ground between a lower and a higher neighbour on opposite sides.