178 lines
6.7 KiB
C#
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;
|
|
}
|
|
}
|
|
|