gamedev-unity/skills/unity-skills/skills/terrain/SKILL.md
Operate on Unity Terrain — create TerrainData, sculpt heights, paint texture layers, and smooth/flatten regions. Use when creating or editing terrain, sculpting or smoothing the heightmap, or painting terrain texture layers, even if the user just says "地形" or "刷地面". 操作 Unity Terrain(创建 TerrainData、雕刻高度、绘制纹理层、平滑/压平区域);当用户要创建或编辑地形、雕刻或平滑高度图、或绘制地形纹理层时使用。
npx skillsauth add bernatmv/ai-rules unity-terrainInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Operating Mode (v1.9 three-tier):
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.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_createto generate one.
DO NOT (common hallucinations):
terrain_set_texture does not exist → use terrain_paint_texture with layer index and brush parametersterrain_add_tree / terrain_add_grass do not exist → these require Unity Terrain tools or custom scriptsterrain_set_size does not exist → terrain dimensions are set at creation via terrain_createterrain_import_heightmap / terrain_set_heights do not exist → use terrain_set_heights_batch with a 2D heights array ([z][x] values 0-1)Routing:
material module on terrain's materialgameobject module to create/place objects| 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 |
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}
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}
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}
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}
⚠️ 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}
# 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)
⭐ 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}
# 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))
⭐ 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}
# 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)
⭐ 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}
# Smooth a specific area
call_skill("terrain_smooth",
normalizedX=0.5, normalizedZ=0.5,
radius=0.2, iterations=3)
⭐ 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}
# Create a flat plateau
call_skill("terrain_flatten",
normalizedX=0.5, normalizedZ=0.5,
targetHeight=0.6, radius=0.15, strength=1.0)
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}
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']}")
All terrain operations support workflow undo/redo:
# 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 names, parameters, defaults, and returns are defined by GET /skills/schema or unity_skills.get_skill_schema(), not by this file.
development
Keyword research and validation with real search-demand data — never ship keywords from intuition alone. Probes Google Autocomplete per language (free, no account) to prove demand and discover the exact phrasing people type, checks SERPs for winnability, and uses Keyword Planner/Ahrefs/Semrush exports when the user has access. Activates when: choosing or reviewing SEO keywords, meta keywords, page titles, article topics or slugs, landing page copy targeting search, App Store/ASO keyword fields, multilingual keyword sets, 'what should we rank for', 'keyword analysis', or auditing why a page doesn't rank. Also invoke it as a validation pass whenever another skill or task produces a keyword list.
development
Automate YooAsset hot-update and asset bundles — build bundles, run Editor simulate builds, manage Collector groups, analyze BuildReport, and validate runtime. Use when building or simulating YooAsset bundles, configuring collectors, or validating hot-update assets, even if the user just says "热更" or "打AB包". 自动化 YooAsset 热更新与资源包(构建 bundle、编辑器模拟构建、管理 Collector 分组、分析 BuildReport、运行时校验);当用户要构建或模拟 YooAsset 资源包、配置 collector、或校验热更资源时使用。
development
Source-anchored design rules for YooAsset v2.3.18 — initialization, default-package shortcuts, play modes, asset handles, loading, updates, filesystem, build, and pitfalls. Use when writing or reviewing YooAsset code, initializing packages, loading assets via handles, setting up hot-update/download, or choosing a play mode, even if the user just says "热更" or "资源包". 为 YooAsset v2.3.18 提供源码锚定的设计规则(初始化、默认包快捷方式、运行模式、资源句柄、加载、更新、文件系统、构建、陷阱);当用户要编写或审查 YooAsset 代码、初始化 package、用句柄加载资源、配置热更/下载、或选择运行模式时使用。
data-ai
Last-resort guidance for safely hand-editing Unity serialized YAML (.unity/.prefab/.asset/.meta/ProjectSettings) — reference/fileID repair, GUID safety, and merge-conflict fixes. Use when REST cannot reach the change and YAML must be hand-edited — fixing m_Script GUIDs, broken fileID references, .meta files, or merge conflicts, even if the user just says "场景文件打不开" or "引用丢了". 安全手编 Unity 序列化 YAML(.unity/.prefab/.asset/.meta/ProjectSettings)的最后手段(引用/fileID 修复、GUID 安全、合并冲突修复);当 REST 无法触达、必须手编 YAML 时使用——修复 m_Script GUID、断裂 fileID 引用、.meta 文件或合并冲突。