Files
AIC-Project/Client/Assets/Editor/SceneTool/GroundCreate.cs
T
2026-07-10 10:24:29 +08:00

178 lines
6.7 KiB
C#

using System;
using UnityEditor;
using UnityEngine;
public static class GroundCreate
{
//[MenuItem("GroundTools/GroundCreate")]
/// <summary>
/// 创建一个100x100单位的地表模型
/// </summary>
public static void CreateGround()
{
// 设置网格参数
int width = 128;
int length = 128;
// 创建游戏对象
GameObject ground = new GameObject($"Ground");
// 添加网格过滤器和网格渲染器
MeshFilter meshFilter = ground.AddComponent<MeshFilter>();
MeshRenderer meshRenderer = ground.AddComponent<MeshRenderer>();
UnityEngine.Random.InitState((int)DateTime.Now.Ticks);
float randOffset = UnityEngine.Random.Range(0f, 100f);
// 创建网格
Mesh mesh = new Mesh();
mesh.name = $"Ground_{width}X{length}_Mesh";
float halfWidth = width * 0.5f;
float halfLength = length * 0.5f;
//创建一个随机高度图,并填入到顶点的y上
float[,] heightMap = GenerateHeightMap(width, length);
//for (int z = 0; z <= length; z++)
//{
// for (int x = 0; x <= width; x++)
// {
// heightMap[x, z] = Mathf.PerlinNoise(x * 0.1f, z * 0.1f) * 2f - 1f;
// }
//}
// 创建顶点
Vector3[] vertices = new Vector3[(width + 1) * (length + 1)];
for (int z = 0; z <= length; z++)
{
for (int x = 0; x <= width; x++)
{
vertices[z * (width + 1) + x] = new Vector3(x - halfWidth, heightMap[x, z], z - halfLength);
}
}
// 创建三角形
int[] triangles = new int[width * length * 6];
int triangleIndex = 0;
for (int z = 0; z < length; z++)
{
for (int x = 0; x < width; x++)
{
int vertexIndex = z * (width + 1) + x;
triangles[triangleIndex++] = vertexIndex;
triangles[triangleIndex++] = vertexIndex + width + 1;
triangles[triangleIndex++] = vertexIndex + 1;
triangles[triangleIndex++] = vertexIndex + 1;
triangles[triangleIndex++] = vertexIndex + width + 1;
triangles[triangleIndex++] = vertexIndex + width + 2;
}
}
// 创建UV坐标
Vector2[] uvs = new Vector2[(width + 1) * (length + 1)];
for (int z = 0; z <= length; z++)
{
for (int x = 0; x <= width; x++)
{
uvs[z * (width + 1) + x] = new Vector2((float)x / width, (float)z / length);
}
}
// 设置网格数据
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uvs;
mesh.RecalculateNormals();
mesh.RecalculateBounds();
// 应用网格
meshFilter.sharedMesh = mesh;
// 添加碰撞器
MeshCollider collider = ground.AddComponent<MeshCollider>();
collider.sharedMesh = mesh;
// 设置材质
meshRenderer.material = new Material(Shader.Find("XWorld/XTerrain"));
//设置_LayerTex0 _LayerTex1 _LayerTex2 _LayerTex3 和_Control贴图
meshRenderer.material.SetTexture("_LayerTex0", AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/Arts/scene/Terrain/Texture/grass.png"));
meshRenderer.material.SetTexture("_LayerTex1", AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/Arts/scene/Terrain/Texture/blick.png"));
meshRenderer.material.SetTexture("_LayerTex2", AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/Arts/scene/Terrain/Texture/mud.png"));
meshRenderer.material.SetTexture("_LayerTex3", AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/Arts/scene/Terrain/Texture/sand.png"));
//生成一个rgba四通道的控制贴图,随机分配四种材质的混合度
Texture2D controlTex = new Texture2D(width, length, TextureFormat.RGBA32, false);
float PerlinRandom = 0.05f;
for (int z = 0; z < length; z++)
{
for (int x = 0; x < width; x++)
{
//float h = heightMap[x, z];
float h1 = Mathf.PerlinNoise(randOffset + z * PerlinRandom, randOffset + x * PerlinRandom);
float hLerp;
Color color;// = new Color(0, 0, 0, 0);
if (h1 < 0.33f)
{
hLerp = (0.33f - h1)*3;
color = new Color(0, 0, hLerp, 1 - hLerp);
}
else if (h1 < 0.66f)
{
hLerp = (0.66f - h1) * 3;
color = new Color(0, hLerp, 1- hLerp, 0);
}
else
{
hLerp = (1.0f - h1) * 3;
color = new Color(hLerp, 1 - hLerp, 0, 0);
}
controlTex.SetPixel(x, z, color);
}
}
controlTex.Apply();
meshRenderer.material.SetTexture("_Control", controlTex);
// 注册撤销操作并选中对象
Undo.RegisterCreatedObjectUndo(ground, "Create 100x100 Ground");
Selection.activeGameObject = ground;
}
//生成x * z的高度图,增加一个浮动变化的高度和一个不均匀的高度变化
//heightScale 高度缩放因子
//heightOffset 高度偏移量
public static float[,] GenerateHeightMap(int x, int z, float heightScale = 20f, float PerlinRandom = 0.01f)
{
float[,] heightMap = new float[x + 1, z + 1];
UnityEngine.Random.InitState(Time.frameCount);
Debug.Log("Random Seed: " + Time.frameCount);
//生成一个N分之一宽和高的高度图
int N = 16;
int quarterX = x / N;
int quarterZ = z / N;
float[,] quarterHeightMap = new float[quarterX + 1, quarterZ + 1];
for (int i = 0; i <= quarterX; i++)
{
for (int j = 0; j <= quarterZ; j++)
{
quarterHeightMap[i, j] = Mathf.PerlinNoise(i * 0.1f, j * 0.1f) * heightScale*2;
}
}
//将四分之一高度图叠加到总的高度图上
for (int i = 0; i <= x; i++)
{
for (int j = 0; j <= z; j++)
{
//heightMap[i, j] = Mathf.PerlinNoise(i * 0.1f, j * 0.1f) * heightScale + quarterHeightMap[i / N, j / N];
//heightMap[i, j] = quarterHeightMap[i / N, j / N];
float h1 = Mathf.PerlinNoise(i * PerlinRandom, j * PerlinRandom) * heightScale;
float h2 = Mathf.PerlinNoise(i * PerlinRandom*5, j * PerlinRandom*5) * heightScale;
heightMap[i, j] = h1 > h2? h1 : h2;
}
}
return heightMap;
}
}