Unity如何通过代码地形凹凸和修改地形纹理(地形贴图)
实现效果(具体形状可以在代码中更改)
主要方法
SetAlphamaps和SetHeights
using System;
using System.Collections;
using UnityEngine;
public class TerrainUtil
{
#region 地形控制
/**
* Terrain的HeightMap坐标原点在左下角
* y
* ↑
* 0 → x
*/
/// <summary>
/// 返回Terrain上某一点的HeightMap索引。
/// </summary>
/// <param name="terrain">Terrain</param>
/// <param name="point">Terrain上的某点</param>
/// <returns>该点在HeightMap中的位置索引</returns>
public static int[] GetHeightmapIndex(Terrain terrain, Vector3 point)
{
TerrainData tData = terrain.terrainData;
float width = tData.size.x;
float length = tData.size.z;
// 根据相对位置计算索引
int x = (int)((point.x - terrain.GetPosition().x) / width * tData.heightmapWidth);
int y = (int)((point.z - terrain.GetPosition().z) / length * tData.heightmapHeight);
//mapX = (int)(((point.x - terrainPosition.x) / terrainData.size.x) * heightmapWidth);
//mapY = (int)(((point.z - terrainPosition.z) / terrainData.size.z) * heigtmapHeight);
return new int[2] {
x, y };
}
public static float[] GetHeightmapIndex(Terrain terrain, Vector3 point, bool Float)
{
TerrainData tData = terrain.terrainData;
float width = tData.size.x;
float length = tData.size.z;
// 根据相对位置计算索引
float x = (float)((point.x - terrain.GetPosition().x) / width * tData.heightmapWidth);
float y = (float)((point.z - terrain.GetPosition().z) / length * tData.heightmapHeight);
//mapX = (int)(((point.x - terrainPosition.x) / terrainData.size.x) * heightmapWidth);
//mapY = (int)(((point.z - terrainPosition.z) / terrainData.size.z) * heigtmapHeight);
return new float[2] {
x, y };
}
/// <summary>
/// 返回GameObject在Terrain上的相对(于Terrain的)位置。
/// </summary>
/// <param name="terrain">Terrain</param>
/// <param name="go">GameObject</param>
/// <returns>相对位置</returns>
public static Vector3 GetRelativePosition(Terrain terrain, GameObject go)
{
return go.transform.position - terrain.GetPosition();
}
/// <summary>
/// 返回Terrain上指定点在世界坐标系下的高度。
/// </summary>
/// <param name="terrain">Terrain</param>
/// <param name="point">Terrain上的某点</param>
/// <param name="vertex">true: 获取最近顶点高度 false: 获取实际高度</param>
/// <returns>点在世界坐标系下的高度</returns>
public static float GetPointHeight(Terrain terrain, Vector3 point, bool vertex = false)
{
// 对于水平面上的点来说,vertex参数没有影响
if (vertex)
{
// GetHeight得到的是离点最近的顶点的高度
int[] index = GetHeightmapIndex(terrain, point);
return terrain.terrainData.GetHeight(index[0], index[1]);
}
else
{
// SampleHeight得到的是点在斜面上的实际高度
return terrain.SampleHeight(point);
}
}
/// <summary>
/// 返回Terrain的HeightMap,这是一个 height*width 大小的二维数组,并且值介于 [0.0f,1.0f] 之间。
/// </summary>
/// <param name="terrain">Terrain</param>
/// <param name="xBase">检索HeightMap时的X索引起点</param>
/// <param name="yBase">检索HeightMap时的Y索引起点</param>
/// <param name="width">在X轴上的检索长度</param>
/// <param name="height">在Y轴上的检索长度</param>
/// <returns></returns>
public static float[,] GetHeightMap(Terrain terrain, int xBase = 0, int yBase = 0, int width = 0, int height = 0)
{
if (xBase + yBase + width + height == 0)
{
width = terrain.terrainData.heightmapWidth;
height = terrain.terrainData.heightmapHeight;
}
return terrain.terrainData.GetHeights(xBase, yBase, width, height);
}
/// <summary>
/// 升高Terrain上某点的高度。
/// </summary>
/// <param name="terrain">Terrain</param>
/// <param name="point">Terrain上的点</param>
/// <param name="opacity">升高的高度</param>
/// <param name="size">笔刷大小</param>
/// <param name="amass">当笔刷范围内其他点的高度已经高于笔刷中心点时是否同时提高其他点的高度</param>
public static void Rise(