unity-terrain
Operate on Unity Terrain
Works with
Agent Skills format with YAML frontmatter. Claude Code reads it as-is.
---
name: "unity-terrain"
description: "Operate on Unity Terrain"
license: "MIT"
---
> **Before calling any skill in this module:** if you are about to call a skill with parameters guessed from its name or description, STOP — read this file (or fetch its schema via `GET /skills/recommend?includeSchema=true`) first. If you already have the parameter definitions from recommend/schema, you may proceed straight to dryRun.
## Triggers
- Creating or editing terrain
- Sculpting or smoothing heightmap
- Painting terrain texture layers
- 创建或编辑地形、雕刻或平滑高度图、绘制地形纹理层
# Unity Terrain Skills
## Guardrails
**Operating Mode** (v1.9 three-tier):
- **Approval** (default): query skills (`terrain_get_info`, `terrain_get_height`) run directly. Create/modify skills (`terrain_create`, `terrain_set_height`, `terrain_set_heights_batch`, `terrain_add_hill`, `terrain_generate_perlin`, `terrain_smooth`, `terrain_flatten`, `terrain_paint_texture`) are FullAuto — on `MODE_RESTRICTED`, run the grant protocol; `/permission/grant` executes the skill server-side and returns the result.
- **Auto** / **Bypass**: SemiAuto and FullAuto run directly.
- This module contains **no** Delete / PlayMode / Reload / `RiskLevel="high"` skills — nothing auto-classifies as forbidden. To remove a terrain delete the asset via `asset_delete` (subject to its own forbidden rules).
> **Note**: All sculpt/paint operations require an existing Terrain in the scene, or use `terrain_create` to generate one.
**DO NOT** (common hallucinations):
- `terrain_set_texture` does not exist → use `terrain_paint_texture` with layer index and brush parameters
- `terrain_add_tree` / `terrain_add_grass` do not exist → these require Unity Terrain tools or custom scripts
- `terrain_set_size` does not exist → terrain dimensions are set at creation via `terrain_create`
- `terrain_import_heightmap` / `terrain_set_heights` do not exist → use `terrain_set_heights_batch` with a 2D heights array (`[z][x]` values 0-1)
**Routing**:
- For terrain material → use `material` module on terrain's material
- For objects on terrain → use `gameobject` module to create/place objects
## Skills Overview
| Skill | Description |
|-------|-------------|
| `terrain_create` | Create new Terrain with TerrainData |
| `terrain_get_info` | Get terrain size, resolution, layers |
| `terrain_get_height` | Get height at world position |
| `terrain_set_height` | Set height at normalized coords |
| `terrain_set_heights_batch` | Batch set heights in region |
| `terrain_add_hill` | ⭐ Add smooth hill with radius and falloff |
| `terrain_generate_perlin` | ⭐ Generate natural terrain using Perlin noise |
| `terrain_smooth` | ⭐ Smooth terrain to reduce sharp edges |
| `terrain_flatten` | ⭐ Flatten terrain to target height |
| `terrain_paint_texture` | Paint texture layer at position |
---
## Skills
### terrain_create
Create a new Terrain GameObject with TerrainData asset.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `name` | string | No | "Terrain" | Terrain name |
| `width` | int | No | 500 | Terrain width (X) |
| `length` | int | No | 500 | Terrain length (Z) |
| `height` | int | No | 100 | Max terrain height (Y) |
| `heightmapResolution` | int | No | 513 | Heightmap resolution (power of 2 + 1) |
| `x`, `y`, `z` | float | No | 0 | Position |
**Returns**: `{success, name, instanceId, terrainDataPath, size, position}`
### terrain_get_info
Get terrain information.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `name` | string | No* | Terrain name |
| `instanceId` | int | No* | Instance ID |
*If neither provided, uses first terrain in scene
**Returns**: `{success, name, instanceId, position, size, heightmapResolution, alphamapResolution, detailResolution, terrainLayerCount, layers}`
### terrain_get_height
Get terrain height at world position.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `worldX` | float | Yes | World X coordinate |
| `worldZ` | float | Yes | World Z coordinate |
| `name` | string | No | Terrain name |
**Returns**: `{success, worldX, worldZ, height, worldY}`
### terrain_set_height
Set height at normalized coordinates.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `normalizedX` | float | Yes | X position (0-1) |
| `normalizedZ` | float | Yes | Z position (0-1) |
| `height` | float | Yes | Height value (0-1) |
| `name` | string | No | Terrain name |
| `instanceId` | int | No | Terrain instance ID |
**Returns**: `{success, normalizedX, normalizedZ, height, pixelX, pixelZ}`
### terrain_set_heights_batch
⚠️ **BATCH SKILL**: Set heights in rectangular region.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `startX` | int | Yes | Start X pixel index |
| `startZ` | int | Yes | Start Z pixel index |
| `heights` | float[][] | Yes | 2D array [z][x] with values 0-1 |
| `name` | string | No | Terrain name |
| `instanceId` | int | No | Terrain instance ID |
**Returns**: `{success, startX, startZ, modifiedWidth, modifiedLength, totalPointsModified}`
```python
# Example: Create a 10x10 hill
heights = [[0.5 - abs(x-5)/10 - abs(z-5)/10 for x in range(10)] for z in range(10)]
call_skill("terrain_set_heights_batch", startX=50, startZ=50, heights=heights)
```
### terrain_add_hill
⭐ **RECOMMENDED**: Add a smooth, natural-looking hill to the terrain.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `normalizedX` | float | Yes | - | X position (0-1) |
| `normalizedZ` | float | Yes | - | Z position (0-1) |
| `radius` | float | No | 0.2 | Hill radius (0-1, relative to terrain size) |
| `height` | float | No | 0.5 | Hill height (0-1) |
| `smoothness` | float | No | 1.0 | Smoothness factor (higher = smoother) |
| `name` | string | No | null | Terrain name |
| `instanceId` | int | No | 0 | Terrain instance ID |
**Returns**: `{success, centerX, centerZ, radius, height, affectedArea}`
```python
# Add a large smooth hill at center
call_skill("terrain_add_hill",
normalizedX=0.5, normalizedZ=0.5,
radius=0.3, height=0.6, smoothness=2.0)
# Add multiple hills for varied terrain
for i in range(5):
call_skill("terrain_add_hill",
normalizedX=random.uniform(0.2, 0.8),
normalizedZ=random.uniform(0.2, 0.8),
radius=random.uniform(0.1, 0.25),
height=random.uniform(0.3, 0.7))
```
### terrain_generate_perlin
⭐ **RECOMMENDED**: Generate natural-looking terrain using Perlin noise algorithm.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `scale` | float | No | 20.0 | Noise scale (lower = larger features) |
| `heightMultiplier` | float | No | 0.3 | Height intensity (0-1) |
| `octaves` | int | No | 4 | Detail layers (more = more detail) |
| `persistence` | float | No | 0.5 | Amplitude decrease per octave |
| `lacunarity` | float | No | 2.0 | Frequency increase per octave |
| `seed` | int | No | 0 | Random seed (0 = random) |
| `name` | string | No | null | Terrain name |
**Returns**: `{success, resolution, scale, heightMultiplier, octaves, persistence, lacunarity, seed}`
```python
# Generate rolling hills
call_skill("terrain_generate_perlin",
scale=25.0, heightMultiplier=0.4, octaves=4)
# Generate mountainous terrain
call_skill("terrain_generate_perlin",
scale=15.0, heightMultiplier=0.6, octaves=6, persistence=0.6)
# Generate with specific seed for reproducibility
call_skill("terrain_generate_perlin",
scale=20.0, heightMultiplier=0.5, seed=12345)
```
### terrain_smooth
⭐ Smooth terrain heights to reduce sharp edges and create natural transitions.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `normalizedX` | float | Yes | - | X position (0-1) |
| `normalizedZ` | float | Yes | - | Z position (0-1) |
| `radius` | float | No | 0.1 | Smoothing radius (0-1) |
| `iterations` | int | No | 1 | Number of smoothing passes |
| `name` | string | No | null | Terrain name |
| `instanceId` | int | No | 0 | Terrain instance ID |
**Returns**: `{success, centerX, centerZ, radius, iterations, affectedArea}`
```python
# Smooth a specific area
call_skill("terrain_smooth",
normalizedX=0.5, normalizedZ=0.5,
radius=0.2, iterations=3)
```
### terrain_flatten
⭐ Flatten terrain to a specific height in a region.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `normalizedX` | float | Yes | - | X position (0-1) |
| `normalizedZ` | float | Yes | - | Z position (0-1) |
| `targetHeight` | float | No | 0.5 | Target height (0-1) |
| `radius` | float | No | 0.1 | Flatten radius (0-1) |
| `strength` | float | No | 1.0 | Flatten strength (0-1) |
| `name` | string | No | null | Terrain name |
| `instanceId` | int | No | 0 | Terrain instance ID |
**Returns**: `{success, centerX, centerZ, targetHeight, radius, strength}`
```python
# Create a flat plateau
call_skill("terrain_flatten",
normalizedX=0.5, normalizedZ=0.5,
targetHeight=0.6, radius=0.15, strength=1.0)
```
### terrain_paint_texture
Paint terrain texture layer. Requires terrain layers already configured.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `normalizedX` | float | Yes | - | X position (0-1) |
| `normalizedZ` | float | Yes | - | Z position (0-1) |
| `layerIndex` | int | Yes | - | Terrain layer index (0-based; use `terrain_get_info` to query available layers) |
| `strength` | float | No | 1.0 | Paint strength |
| `brushSize` | int | No | 10 | Brush size in pixels |
| `name` | string | No | null | Terrain name |
| `instanceId` | int | No | 0 | Terrain instance ID |
**Returns**: `{success, layerIndex, layerName, centerX, centerZ, brushSize, strength}`
---
## Example Usage
```python
import unity_skills
# === Method 1: Quick terrain with Perlin noise (RECOMMENDED) ===
# Create terrain
result = unity_skills.call_skill("terrain_create",
name="MyTerrain", width=200, length=200, height=50)
# Generate natural terrain with Perlin noise
unity_skills.call_skill("terrain_generate_perlin",
scale=20.0, # Larger scale = bigger features
heightMultiplier=0.4, # Height intensity
octaves=5, # More octaves = more detail
persistence=0.5,
lacunarity=2.0)
# === Method 2: Add individual smooth hills ===
# Create flat terrain
result = unity_skills.call_skill("terrain_create",
name="HillyTerrain", width=200, length=200, height=50)
# Add multiple smooth hills
import random
for i in range(8):
unity_skills.call_skill("terrain_add_hill",
normalizedX=random.uniform(0.2, 0.8),
normalizedZ=random.uniform(0.2, 0.8),
radius=random.uniform(0.15, 0.3),
height=random.uniform(0.3, 0.6),
smoothness=1.5) # Higher = smoother
# Smooth the entire terrain for natural transitions
unity_skills.call_skill("terrain_smooth",
normalizedX=0.5, normalizedZ=0.5,
radius=0.5, iterations=2)
# === Method 3: Create specific features ===
# Create a mountain
unity_skills.call_skill("terrain_add_hill",
normalizedX=0.5, normalizedZ=0.5,
radius=0.25, height=0.8, smoothness=2.0)
# Create a flat plateau on top
unity_skills.call_skill("terrain_flatten",
normalizedX=0.5, normalizedZ=0.5,
targetHeight=0.8, radius=0.1, strength=1.0)
# === Method 4: Manual height control (advanced) ===
import math
heights = []
for z in range(64):
row = []
for x in range(64):
# Distance from center
dx = (x - 32) / 32
dz = (z - 32) / 32
dist = math.sqrt(dx*dx + dz*dz)
# Smooth hill with cosine falloff
h = max(0, 0.5 * math.cos(dist * math.pi / 2)) if dist < 1 else 0
row.append(h)
heights.append(row)
unity_skills.call_skill("terrain_set_heights_batch",
startX=100, startZ=100, heights=heights)
# Query height at world position
info = unity_skills.call_skill("terrain_get_height", worldX=100, worldZ=100)
print(f"Height at position: {info['height']}")
```
## Workflow Integration
All terrain operations support workflow undo/redo:
```python
# Start workflow session
unity_skills.call_skill("workflow_session_start", tag="Create Terrain")
# Create and modify terrain
unity_skills.call_skill("terrain_create", name="TestTerrain")
unity_skills.call_skill("terrain_generate_perlin", scale=20, heightMultiplier=0.5)
unity_skills.call_skill("terrain_add_hill", normalizedX=0.3, normalizedZ=0.3, radius=0.2)
# End session
unity_skills.call_skill("workflow_session_end")
# Later: Undo entire terrain creation
sessions = unity_skills.call_skill("workflow_session_list")
unity_skills.call_skill("workflow_session_undo", sessionId=sessions['sessions'][0]['sessionId'])
```
---
## Exact Signatures
Exact names, parameters, defaults, and returns are defined by `GET /skills/schema` or `unity_skills.get_skill_schema()`, not by this file.More General & Other skills
find-skills
vercel-labs/skills
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
grill-me
mattpocock/skills
A relentless interview to sharpen a plan or design.
grill-with-docs
mattpocock/skills
A relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go.

