在Unity中,Terrain是一个专门用于制作大规模、自然风格场景的强大工具
什么是Terrain
Terrain是Unity提供的一个内置组件,用于在场景中创建可编辑的地形
它由多个部分组成:
- 地形本体(高度图控制的网格)
- 纹理涂层(地表材质贴图)
- 植被/树木/草
- 光照支持(光照贴图、探针)
- LOD和剔除
Terrain的核心结构
| 模块 | 功能 |
|---|---|
| 高度图(Heightmap) | 决定地形的高低起伏 |
| 绘制材质(Layers) | 地面纹理(如草地、岩石、雪)混合涂刷 |
| 细节对象(Details) | 草、石头、花等低多边形细节(大量渲染优化) |
| 树木系统(Trees) | 批量放置支持 LOD 的树 |
| 碰撞体 | 自动生成地形碰撞 |
| 光照支持 | 支持烘焙光照图、Light Probe、反射探针 |
Terrain Data
Terrain Data是地形的“后端数据容器”,和Terrain组件一起工作,一个Terrain组件绑定一个TerrainData资源
Terrain terrain = GetComponent<Terrain>();
TerrainData data = terrain.terrainData;
TerrainData保存的内容
高度图(Heightmap)
- 用灰度图(float[,])描述地形的高度
- 控制地形表面的形状
float[,] heights = terrainData.GetHeights(0, 0, width, height);
纹理图层(Splatmaps)
- 每层纹理混合信息
- 用来混合多个地形材质(如泥土、草地、雪)
float[,,] alphamaps = terrainData.GetAlphamaps(x, y, w, h);
细节对象(Details/Grass)
- 如草地、灌木,用细节地图存储
int[,] detailMap = terrainData.GetDetailLayer(x, y, w, h, detailLayerIndex);
树对象(Trees)
- 存储每棵树的位置、缩放、原型类型
TreeInstance[] trees = terrainData.treeInstances;
分辨率信息
- 高度图分辨率:决定地形精细度
- 控制图分辨率:纹理混合图精度
- 细节图分辨率:草木布置精度
terrainData.heightmapResolution
terrainData.alphamapResolution
terrainData.detailResolution
示例:运行时生成地形
void GenerateTerrain()
{
TerrainData terrainData = new TerrainData();
terrainData.heightmapResolution = 513;
terrainData.size = new Vector3(1000, 100, 1000);
float[,] heights = new float[513, 513];
for (int x = 0; x < 513; ++x)
for (int y = 0; y < 513; ++y)
heights[x, y] = Mathf.PerlinNoise(x * 0.01f, y * 0.01f) * 0.2f;
terrainData.SetHeights(0, 0, heights);
GameObject terrainGO = Terrain.CreateTerrainGameObject(terrainData);
}
注意事项
| 限制 | 说明 |
|---|---|
| 只能在主线程读写 | 不支持多线程访问(除非用 NativeArray Hack) |
| 修改后需刷新 | 修改 terrainData 后需设置给 Terrain 才生效 |
| 不可跨 Terrain 共享贴图索引 | 每个地形的 TerrainLayer[] 不能乱用,需要独立处理 |
Terrain in Inspector
场景中的Terrain对象一般会包含以下模块
- Terrain(主组件)
- Terrain Collider(自动附加)
- Terrain Tools(各种绘制工具)
- Terrain Settings(参数设置)
Create Neighbor Terrains

这是什么
Unity的每一个Terrain是一个地形快(chunk),当你需要构建更大的世界地图时:
你可以将多个地形快拼接在一起,形成一个无缝连接的大地图
Create Neighbor Terrains就是一个快捷工具,让你快速在上下左右形成新的Terrain,并自动设置它们之间的连接关系(Neighbor)
Unity会做什么
- 自动创建一个或多个相邻的Terrain GameObject
- 与当前的Terrain无缝拼接(边界贴合)
- 自动设置每个地形的Neighbor引用(主要用于LOD过渡等)

创建后的Terrain有哪些特征
- 分辨率与当前Terrain一致
- 初始高度图为空白
- 材质/Detail Layer/树/Layer并不会自动继承,需要手动复制
- 已经自动设置了
SetNeighbor(Unity会在内部管理连接信息)
为什么需要Neighbor信息
Unity Terrain在运行时做:
- LOD边界融合(避免接缝)
- 光照探针插值正确性
- 寻路/NavMesh分布
也就是说,如果你手动创建了多个Terrain,没有设置Neighbor,会出现:
- LOD切换时断裂
- 光照贴图不连续
- 草树渲染突然中断
Tips
多Terrain的场景通常配合:
Streaming(按需加载块)Runtime Stitching(连接边界) 可以使用插件如MicroSplat/Gaia等进行多地形管理
PaintTerrain

这是Unity Terrain系统用于手动“绘制”地形的工具,类似PS中的笔刷,但是用于三维地形,可以用它来:
- 提升/降低地形
- 涂抹纹理(比如:草、图、雪)
- 铺设草和石头(Detail)
- 放置树木(Tree)
- 设置材质混合
- 创建地形孔洞(如山洞入口)
Sub Tools
1.Raise or Lower Terrain
用笔刷将地形向上或向下推动
- Bursh Size:笔刷大小(影响范围)
- Opacity:强度(提升速度)
- Target Strength:单次推拉的力量
- 可用于画山、丘陵、平原
配合Shift反向操作
2.Set Height
把地形调整到某个统一的高度(例如建平台)
- 设置
Target Height,然后绘制地形 - 适合制作建筑平台、河面、平地道路
可以使用Flatten一键铺平当前Terrain
3.Smooth Height(平滑地形)
平滑地形的高低差,让地形更自然
- 常用于锐利山峰边缘平滑处理
- 减少单位移动时的突兀感
4.Paint Texture(涂地表材质)
把不同纹理“画”到地形上,实现草地、雪地、沙漠的混合过渡
- 每个纹理时一个Terrain Layer
- Unity支持多图混合(最多8张)
- 使用笔刷方式混合地表纹理
示例层:
- Layer1:Grass
- Layer2:Dirt
- Layer3:Rock
支持自定义笔刷、混合过渡控制(Opacity)Add Layer添加纹理层,选用PBR材质(支持BaseMap、NormalMap)
5.Terrain Holes
画出洞,让地形有缺口(可用于洞穴、地道入口)
- 类似“橡皮擦”,直接擦掉地形面片
- 可用于:
- 做地下世界入口
- 配合Portal、Volume、Trigger使用 默认不可通过地形下看见,需要你手动铺地板或连接其他网格模型
Paint Trees

Paint Trees是Unity Terrain中用于批量种植树木的工具,它支持使用不同树模型的自动随机分布、缩放、选择、LOD显示等,是创建森林、山地植被的关键工具
添加树模型
点击 “Edit Trees” → “Add Tree…”:
- 在弹出的窗口中选择一个 树的 Prefab
- Unity 支持:
- Tree Creator 制作的树(.tree 文件)
- SpeedTree 模型(.spm 文件)
- 自己导入的 FBX/Prefab 模型(需带有 LOD/Collider)
要求:
- 树不能有刚体或Animator
- 树Prefab中必须包含Mesh Renderer(或SpeedTree)
种树参数设置
添加好树之后,就可以开始“画树”了,主要参数如下:
| 参数 | 作用 |
|---|---|
| Brush Size | 控制笔刷直径(影响范围) |
| Tree Density | 控制单位面积内种植的数量 |
| Tree Height/Width | 控制树的缩放范围(有最小和最大) |
| Color Variation | 控制颜色的随机扰动(偏红、偏绿、偏亮等) |
| Random Rotation | 勾选后自动随机 Y 轴旋转树(防止重复感) |
每画一次,就会在当前区域根据密度、大小、颜色等参数生成多个树
树木渲染和性能优化
Unity的Terrain树有专门的渲染优化方案
Billboard(看板树)
- 当树距离相机较远时,自动变成平面图片
- 极大减少了远距离渲染负担
LOD支持
- 使用SpeedTree模型或LOD Group的树可自动切换模型精度
- 可自定义LOD阶段
GPU Instancing
- 大量相同的树会使用GPU Instancing批处理渲染
- 极大提高性能,适合森林、大面积自然场景
树的碰撞
默认树时没有碰撞器的,但你可以启用碰撞
- 勾选
Tree Collider(取决于添加的树的prefab) - 或者在Runtime中为某些特殊树添加
Capsule Collider等
适用于:
- 玩家可以撞到树
- 砍树系统
- 遮挡判断
几种树的比较
| 工具 | 特点 |
|---|---|
| Tree Creator | Unity 内置的老式树编辑器,支持风、LOD,效率不高,(2022版本已弃用) |
| SpeedTree | 高级树木生成工具,效果好,适合中大型项目(但是商业插件) |
| 普通 Prefab 树 | 自己做的 FBX + LOD,灵活但需优化得当 |
| Terrain 树 | 专为大量地形种树优化,性能最佳但不支持动画/刚体 |
Paint Details

Paint Details是Unity Terrain系统中用于在地形上批量绘制“小型自然细节”的工具,它与Paint Trees类似,但用于体积更小、密度更高的细节对象,是构建自然场景的关键补充
如何添加细节类型
点击面板中的:Edit Details → Add Detail Mesh / Add Grass Texture
Unity提供两种添加方式
| 类型 | 描述 | 适用 |
|---|---|---|
| Detail Mesh | 3D Mesh 物体 | 小石头、蘑菇、落叶、低模草 |
| Grass Texture | Billboard(摄像机对面)草贴图 | 草地、麦田、灌木等 |
Add Grass Texture
用于画贴图式草,性能最高
- 你只需指定一个灰度图草纹理(通常带透明背景)
- Unity会使用Billboard模式渲染草
- 草会随风飘动(可在Terrain Setting设置Wind参数)
- 可调颜色混合范围、尺寸、透明度
Add Detail Mesh
- 可选一个Prefab(如石头、蘑菇、底模模型)
- 用于3D小物件渲染
- 可以勾选GPU Instancing以提升性能
注意:
- 太复杂的Mesh会降低性能
- 太密集的放置会导致Draw Call飙升
Paint参数
| 参数 | 描述 |
|---|---|
| Brush Size | 笔刷范围(单位为世界坐标) |
| Opacity | 笔刷强度(一次能刷多少) |
| Target Strength | 总体密度(越高越密) |
| Random Color / Size | 自动扰动草的颜色、尺寸,提升自然感 |
| Noise Spread | 控制颜色/透明度变化分布程度(更逼真) |
渲染与性能优化
优化特性
| 技术 | 说明 |
|---|---|
| Billboard 渲染 | 仅用平面草贴图,看起来像 3D 实际是贴图 |
| GPU Instancing | Detail Mesh 会批处理,显著降低 Draw Call |
| LOD 剔除 | 距离过远会剔除渲染,节省性能 |
注意:
- 草的渲染非常依赖显卡带宽,大量草可能拖慢帧率
- Detail Mesh应尽量简化为低面数模型
- 尽量不要混用太多不同Detail类型
风动效果设置
- 草地的“飘动”来自于
Terrain Setting中的Wind Settings for Grass - 可调:
- Speed(速度)
- Size(波动幅度)
- Bending(弯曲度)
- Grass Tint(颜色偏移)
默认Terrain草是静态烘焙的,运行时不支持动态添加 但可以:
- 使用脚本控制
DetailPrototype动态添加/刷新 - 使用
GPU Instancing + Compute Shader自制草系统
Terrain Settings

Basic Terrain
| 参数 | 说明 |
|---|---|
| Grouping ID | 地形自动拼接的组编号。多个地形设置相同 ID,可自动连接边界。 |
| Auto Connect | 自动连接相邻地形边缘(启用后根据 Grouping ID)。 |
| Draw | 控制地形是否可见。取消勾选可临时隐藏地形。 |
| Draw Instanced | 使用 GPU Instancing 渲染瓦片,节省 draw call,推荐开启。 |
| Enable Ray Tracing Support | 支持光线追踪(HDRP下使用)。 |
| Pixel Error | 地形 LOD 精度。数值越低越精细,越高越省性能(建议 PC: 1 |
| Minimum/Maximum Detail Limit | 限制 LOD 变化范围(较少使用,可保持默认)。 |
| Base Map Dist. | 多远使用低分辨率贴图(节省远处渲染消耗)。 |
| Cast Shadows | 地形是否投射阴影。 |
| Reflection Probes | 是否使用反射探针,推荐使用 Blend Probes。 |
| Material | 使用的地形材质,默认是 TerrainLit 或 Default-Terrain-Standard。 |
Tree & Detail Objects
| 参数 | 说明 |
|---|---|
| Draw | 控制是否渲染树木和草丛等细节。 |
| Bake Light Probes For Trees | 树木是否参与光照探针烘焙。 |
| Remove Light Probe Ringing | 防止光照探针边界产生光晕伪影。 |
| Preserve Tree Prototype | 保持原始树模型设置。 |
| Tree Motion Vectors | 设置树木是否支持运动矢量(用于动效或后期处理)。 |
| Detail Distance | 草/细节渲染距离(推荐 60~100,性能关键)。 |
| Detail Density Scale | 草的密度百分比(1 = 全密度,调小省性能)。 |
| Tree Distance | 树木的最大渲染距离(推荐 PC: 500~1000)。 |
| Billboard Start | 多远开始使用看板树(节省性能)。 |
| Fade Length | Billboard 淡入淡出的距离,提升视觉平滑度。 |
| Max Mesh Trees | 同屏最多渲染多少真实 Mesh 树,超过则不渲染。 |
| Detail Scatter Mode | 控制草丛分布策略(Coverage 更均匀,推荐)。 |
Wind Settings for Grass
| 参数 | 说明 |
|---|---|
| Speed / Size / Bending | 控制风的速度、大小、弯曲程度。 |
| Grass Tint | 草的全局色调调整(可以统一偏绿、偏黄)。 |
Mesh Resolution
| 参数 | 说明 |
|---|---|
| Terrain Width / Length / Height | 地形尺寸(单位:米) |
| Detail Resolution Per Patch | 每块 Detail Patch 中草的分布密度。 |
| Detail Resolution | 整体地形上草丛/细节的划分格子数。越高越细腻但越耗。 |
Holes Settings
| 参数 | 说明 |
|---|---|
| Compress Holes Texture | 对地形挖洞贴图进行压缩,节省内存。 |
Texture Resolutions
| 参数 | 说明 |
|---|---|
| Heightmap Resolution | 地形高度图精度,建议:513 或 1025(越高越细腻) |
| Control Texture Resolution | 混合贴图精度,控制多种材质混合(如草+土+雪) |
| Base Texture Resolution | 远距离使用的 Base Map 分辨率(节省远处性能) |
Lighting
| 参数 | 说明 |
|---|---|
| Contribute Global Illumination | 地形是否参与全局光照(用于 Lightmap/GI) |
| Receive Global Illumination | 接收 GI 的方式:Lightmaps 或 Light Probes |
Lightmapping
| 参数 | 说明 |
|---|---|
| Scale In Lightmap | 地形占 Lightmap 的比例。越高越清晰(但更占用空间) |
| Lightmap Parameters | 控制烘焙时的精度、抗锯齿、间距等,可选低中高 preset。 |
Quality Settings
| 参数 | 说明 |
|---|---|
| Ignore Quality Settings | 是否忽略当前全局 Quality 设置的控制,强制使用当前面板设定。 |
主要地形制作方式
1.手动笔刷绘制(适用于小项目、快速原型)
- Unity自带Terrain工具,支持高度、纹理、树、草等绘制
- 优点:操作直观,上手快
- 缺点:效率低、不易保持美术风格一致,细节靠人工修
- 使用场景:教学演示、小型独立游戏、快速原型
2.外部DCC工具制作 -> 导入高度图(专业项目常用)
- 使用专业地形软件或美术工具生成高质量地形,再导入Unity:
| 工具 | 说明 |
|---|---|
| World Machine | 高级噪声算法,真实山脉地貌生成 |
| Gaea | 节点式地形设计工具,艺术控制更强 |
| Blender / Houdini | 使用建模 + 程序化节点生成复杂地形 |
| Photoshop | 手绘/合成灰度高度图 |
| Substance Designer | 高度图 + Splatmap生成 |
- Unity支持将这些高度图作为
Raw导入,并通过TerrainData生成地形
3.程序生成地形(Runtime或编译器内)
- 常用于开放世界、沙盒、随机地图类型游戏
- 通过代码控制
TerrainData的高度图、纹理图、细节对象等
float[,] heights = new float[width, height];
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
heights[x, y] = Mathf.PerlinNoise(x * 0.05f, y * 0.05f);
terrainData.SetHeights(0, 0, heights);
- 可加入:
- 噪声函数(Perlin、Simplex)
- 河流生成
- 村庄、道路布置
插件生成(最强大的方式)
Unity商城中有许多强大的地形插件:
| 插件 | 功能特色 |
|---|---|
| Gaia Pro | 一站式地形生成、生态系统、海洋、天气 |
| MapMagic 2 | 节点图式、程序化地形、支持多地形拼接 |
| Terrain Composer 2 | 高自由度、数据驱动生成 |
| MicroSplat / MegaSplat | 高级地形贴图混合、溶解、湿度等效果 |
| Vegetation Studio Pro | 大规模草木渲染优化 |
Terrain LOD 编写/调优
在Unity中,Terrain的LOD是通过高度图分辨率、Pixel Error、以及细节分布分辨率来自动控制网格细分级别。
但Unity也允许通过Shader或代码进一步控制、调优甚至自定义LOD系统
Unity Terrain的LOD原理
Unity的内置Terrain使用以下机制实现LOD:
| 控制项 | 功能 |
|---|---|
Pixel Error | 控制地形 LOD 变化的灵敏度(越高越糙但更快)。 |
Base Map Distance | 多远开始只用 base map 贴图(低分辨率预览) |
Detail Resolution Per Patch | 每块 patch 的细节分辨率,影响草和细节的 LOD。 |
Detail Distance / Tree Distance | 控制草木显示距离。 |
Unity Terrain会自动把地形划分为多个Patch(块),并对每块Patch做LOD
自定义地形LOD Shader
如果想完全控制地形LOD,特别是在自写Mesh Terrain时,可以通过Shader + C#实现
示例:通过高度图动态LOD网格
// 顶点 shader 中使用 distance 控制 mesh LOD 精度
float distanceToCamera = distance(_WorldSpaceCameraPos.xyz, v.vertex.xyz);
float lodLevel = saturate(distanceToCamera / _LodRange); // 0~1
// 然后根据lodLevel选择不同精度的高度图采样
也可以用 Tessellation Shader 来实现更智能的细分控制
[domain("tri")]
[partitioning("fractional_even")]
[outputtopology("triangle_cw")]
[patchconstantfunc("PatchConstantFunction")]
[outputcontrolpoints(3)]
void TessellationHullFunction(...)
{
// 自定义 LOD 控制 tessellationFactor
}
LOD调优策略
| 调优目标 | 技术手段 |
|---|---|
| 提高性能 | 增大 Pixel Error、减小 Patch 分辨率、加大 base map 距离 |
| 增加视觉质量 | 减少 Pixel Error、开启实时阴影、使用高精度高度图 |
| 跨平台支持 | 低端设备禁用草地、禁用阴影、减少树距离 |
| 编程控制 | 使用 terrain.detailObjectDistance = x、terrain.heightmapPixelError = x 动态调节 |
Terrain GPU Instancing(草、树渲染优化)
Terrain GPU Instancing是Unity用于优化草和树渲染性能的关键技术,它能显著减少Draw Call数量,加速大量重复物体的渲染,非常适合用于大场景、开放世界、森林等
什么是GPU Instancing
GPU Instancing(GPU 实例化)是指:
一次提交,多次绘制相同物体,减少CPU->GPU的调用次数
- 普通方式:每棵草都一次Draw Call(开销爆炸)
- Instancing:同一模型、不同位置->1次Draw Call,绘制所有实例
在Unity Terrain中的应用
Details GPU Instancing
Unity 2018+起支持:
- 使用材质类型:Instanced Mesh 或 Grass Mesh
- 并开启“Enable GPU Instancing”选项
操作方法:
1.打开Terrain面板->Paint Details工具
2.点击Edit Details -> Add Detail Mesh
3.在弹窗中:
- 选择一个小草模型(Mesh)
- 勾选Use GPU Instancing
- 设置距离、颜色、密度等参数
4.Unity自动启用GPU实例渲染
注意:草贴图(billboard类型)默认不支持GPU Instancing,需改为Mesh类型或自定义Shader
Trees GPU Instancing
树的GPU Instancing 需要满足两个条件:
- 模型为Mesh(非SpeedTree)
- 树的材质启用GPU Instancing
操作:
1.打开Paint Trees工具
2.添加树种时选择普通Mesh树(非SpeedTree)
3.确保其材质上开启GPU Instancing
注意事项
| 限制 / 要点 | 说明 |
|---|---|
| 草的材质必须使用 支持 Instancing 的 Shader(如 URP Lit 或自写) | |
| Instancing 不等于合批,它是“并行绘制”,但仍然占用 GPU VRAM | |
| 不支持完全随机模型或颜色(需通过 Shader 控制实例差异) | |
| 若草量极大,结合 LOD、Culling、地形剔除工具 更有效 |
高阶优化
| 技术 | 功能 |
|---|---|
| LOD + Crossfade | 减少远距离树模型复杂度 |
| Vegetation Studio Pro / Nature Renderer | 插件增强 GPU 草渲染(支持更远距离、风、阴影) |
| Compute Shader Grass(高级) | 自己写草系统,全 GPU 控制,风、互动等 |
示例:自定义URP Shader支持Instancing
Tags {"RenderType" = "Opaque"}
Pass{
...
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
UNITY_INSTANCING_BUFFER_START(Props)
UNITY_INSTANCING_BUFFER_END(Props)
struct appdata
{
float4 vertex : POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 pos : SV_POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
v2f vert(appdata v)
{
UNITY_SETUP_INSTANCE_ID(v);
...
}
...
ENDCG
}
使用Terrain Toolkit插件或Gaia等地形生成工具
TODO
多地形拼接、无缝过渡
Unity的Terrain是单独的GameObject,每个最多4097*4097高度图/贴图分辨率,单地形很难承载整个世界,因此需要:
将世界划分为多个Terrain块,拼接形成一个整体大地图
拼接方式
方法一:Unity内建 Create Neighbor Terrains
见上文
方法二:代码方式设置Neighbor
terrain.SetNeighbor(left, top, right, bottom);
Unity的渲染系统通过SetNeighbors方法了解哪些Terrain相邻,从而实现:
- 地形LOD平滑衔接
- 避免裂缝/LOD跳跃
- 正确生成相邻地形的阴影、光照探针等
如何实现高度无缝
方法一:在编辑时使用同步工具
- 用Terrain Tools插件中的
Terrain Stitch Tool - 或用插件(如Gaia、Wrold Creator)自动生成高度图并拼接
方法二:手动同步边界高度
当你修改Terrain A的边缘时,要同步更新Terrain B相邻边缘的高度(可通过代码或工具完成)
如何实现纹理无缝
使用相同的SplatMap(地形图层)
- 确保所有Terrain使用相同的Terrain Layer(纹理材质)
- 地形混合时,使用相同规则的笔刷强度
- 地图边缘刷贴图时过渡得要自然(如混合2~3中Layer)
生态系统(草/树)边界过渡
- 插件会对自动边界进行生态镜像过渡
- 自定义草系统需处理边界草的“半草”同步问题
- 植被生成算法需考虑相邻Terrain的坐标范围
LOD无缝过渡与裂缝问题(Crack)
Unity Terrain会自动处理LOD,但如果没有设置邻居关系或高度差距大,会出现裂缝
解决办法:
- 一定调用
SetNeighbors - 保证相邻Terrain的边缘高度一致
- 使用LOD抗裂缝策略(如添加额外边界顶点)
结合导航烘焙(NavMesh + Terrain)
Runtime地形修改(Voxel、地形破坏)
运行时地形修改的主流方案概览
| 模式 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| Voxel Terrain | 使用体素数据构建地形并动态生成 Mesh | 灵活,可完全修改、破坏、挖掘 | 实现复杂,需要自定义系统 |
| Custom Mesh Terrain | 自定义网格,允许直接编辑 Mesh 顶点 | 控制精细,可用于挤压、凹陷 | 不适合大地图或地形细节 |
| Shader-Based Deformation | 用 Shader 或 Compute Shader 动态修改高度图 | 实时效率高,可 GPU 运算 | 精度有限,修改不可永久保存 |
| Unity Terrain Heightmap 修改 | 修改 TerrainData.SetHeights() | 保留 Unity Terrain 优势 | 修改粒度受限,效率较低 |
方案一:体素地形(Voxel Terrain)
类似Minecraft风格的可破坏地形
实现流程:
1.创建体素数据结构(3D数组)
byte[,,] voxels = new byte[width, height, depth];
2.定义每种方块类型(空气、土、石头等)
3.使用Marching Cubes或Greedy Mesh算法生成Mesh
4.实现挖掘、填充逻辑(修改数组,重新生成Mesh)
5.使用Chunk分块机制优化性能
方案二:修改Unity Terrain高度图(SetHeights)
适用于地形凹陷、爆炸坑、地形塑形
示例
void DigHole(Terrain terrain, Vector3 worldPos, float radius, float depth)
{
TerrainData tData = terrain.terrainData;
int xRes = tData.heightmapResolution;
int yRes = tData.heightmapResolution;
Vector3 terrainPos = worldPos = terrain.transform.position;
int x = (int)((terrainPos.x / tData.size.x) * xRes);
int y = (int)((terrainPos.z / tData.size.z) * yRes);
int r = Mathf.RoundToInt((radius / tData.size.x) * xRes);
float[,] heights = tData.GetHeights(x - r, y - r, r * 2, r * 2);
for (int i = 0; i < r * 2; ++i)
{
for (int j = 0; j < r * 2; j++)
{
float dist = Vector2.Distance(new Vector2(i, j), new Vector2(r, r));
if (dist < r) heights[i, j] -= depth * (1f - dist / r);
}
}
tData.SetHeights(x - r, y - r, heights);
}
注意:
- 每次
SetHeights开销较大,频繁修改可能掉帧 - 修改后不会自动更新NavMesh,需要手动
NavMeshSurface.BuildNavMesh()
方案三:自定义Mesh地形修改
可以用Procedural Mesh创建“可破坏”的Mesh地面,然后直接修改顶点高度
核心点:
Mesh.vertices+Mesh.RecalculateNormals()- 可用于地形凹陷、打击坑
- 可结合Shader实现更复杂视觉反馈
GPU地形修改(Shader/Compute Shader)
适合需要大量实时修改的场景,如地面波纹、动态地形变化
常用技巧:
- 通过
RenderTexture存储高度图 - 通过Compute Shader修改像素
- 在Shader中将高度图应用为
vertex displacement
可参考:Unity官方例子GPU Terrain Stamp或Amplify Shader Editor示例
Terrain API
Static Properies
| 属性名 | 中文说明 |
|---|---|
activeTerrain | 当前活动的 Terrain(场景中主地形) |
activeTerrains | 场景中所有激活的 Terrain 列表 |
compressedHolesFormat | 压缩后地形洞孔纹理的图形格式 |
compressedHolesTextureFormat | 压缩后地形洞孔纹理的纹理格式 |
heightmapFormat | 地形高度图的图形格式 |
heightmapRenderTextureFormat | 地形高度图的 RenderTextureFormat |
holesFormat | 未压缩的地形洞孔纹理的图形格式 |
holesRenderTextureFormat | 地形洞孔纹理的 RenderTextureFormat |
normalmapFormat | 地形法线贴图的图形格式 |
normalmapRenderTextureFormat | 地形法线贴图的渲染纹理格式 |
normalmapTextureFormat | 地形法线贴图的纹理格式 |
Properties
| 属性名 | 中文说明 |
|---|---|
allowAutoConnect | 是否自动连接邻近地形 |
bakeLightProbesForTrees | 是否为树烘焙内部光照探针(仅编辑器) |
basemapDistance | 超过该距离时使用预计算的低分辨率底图 |
bottomNeighbor | 下方邻接地形 |
collectDetailPatches | 从内存中收集细节贴片 |
deringLightProbesForTrees | 去除树上的光照探针振铃(仅编辑器) |
detailObjectDensity | 草和细节对象的密度 |
detailObjectDistance | 草和细节对象的最大可视距离 |
drawHeightmap | 是否绘制地形几何(高度图) |
drawInstanced | 是否启用 GPU Instancing 渲染地形 |
drawTreesAndFoliage | 是否绘制树和细节对象 |
editorRenderFlags | 控制地形在编辑器中显示哪些内容 |
enableHeightmapRayTracing | 是否启用地形高度图的光线追踪加速结构 |
groupingID | 地形自动连接的分组 ID |
heightmapMaximumLOD | 地形最大渲染 LOD 级别 |
heightmapMinimumLODSimplification | 最简化的渲染精度 |
heightmapPixelError | LOD 切换时的误差控制 |
ignoreQualitySettings | 是否忽略 QualitySettings 中的地形配置 |
keepUnusedRenderingResources | 是否在一定帧数后释放未使用的摄像机渲染资源 |
leftNeighbor | 左侧邻接地形(X 方向负方向) |
lightmapIndex | 静态光照贴图索引 |
lightmapScaleOffset | 静态光照贴图的缩放和偏移 |
materialTemplate | 渲染地形使用的材质模板 |
normalmapTexture | 从高度图生成的法线贴图 |
patchBoundsMultiplier | 地形边界框的缩放倍率 |
preserveTreePrototypeLayers | 树实例的图层处理方式 |
realtimeLightmapIndex | 实时光照贴图索引 |
realtimeLightmapScaleOffset | 实时光照贴图的缩放和偏移 |
reflectionProbeUsage | 反射探针使用方式 |
renderingLayerMask | 地形渲染器的渲染图层遮罩 |
rightNeighbor | 右侧邻接地形(X 方向正方向) |
shadowCastingMode | 地形阴影模式 |
terrainData | 地形数据资源,包含高度图、纹理等 |
topNeighbor | 上方邻接地形 |
treeBillboardDistance | 树木转为 billboard 的距离 |
treeCrossFadeLength | 树从 Mesh 到 billboard 的过渡距离 |
treeDistance | 树的最大渲染距离 |
treeLODBiasMultiplier | 树 LOD 偏差乘数 |
treeMaximumFullLODCount | 完整 LOD 树的最大数量 |
treeMotionVectorModeOverride | SpeedTree 的运动矢量渲染模式 |
Public Methods
| 方法名 | 中文说明 |
|---|---|
AddTreeInstance(TreeInstance) | 向地形添加一个树实例 |
Flush() | 强制刷新 Terrain 更改 |
GetClosestReflectionProbes(List) | 获取与地形相交的反射探针及其权重 |
GetKeepUnusedCameraRenderingResources() | 查询摄像机资源是否被保留 |
GetPosition() | 获取地形在世界空间中的位置 |
GetSplatMaterialPropertyBlock() | 获取混合材质的参数设置 |
SampleHeight(Vector3) | 采样地形在某世界位置的高度 |
SetKeepUnusedCameraRenderingResources(bool) | 设置是否保留摄像机的地形资源 |
SetNeighbors(left, top, right, bottom) | 设置地形的邻居(用于 LOD 缝合) |
SetSplatMaterialPropertyBlock() | 设置混合材质渲染属性 |
Static Methods
| 方法名 | 中文说明 |
|---|---|
CreateTerrainGameObject(TerrainData) | 从 TerrainData 创建带碰撞器的地形 GameObject |
GetActiveTerrains(List<Terrain>) | 填充一个列表,获取当前激活的所有 Terrain |
SetConnectivityDirty() | 标记当前连接状态为无效(需重新连接) |
