using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HexMap : MonoBehaviour
{
public int RowCount = 300;
public int ColumnCount = 350;
public Material Mat;
private Map map;
// Start is called before the first frame update
void Start()
{
GenerateHexData();
}
/// <summary>
/// 点击生成网格
/// </summary>
public void OnClickGenerateMesh()
{
float time = Time.realtimeSinceStartup;
GenerateMapMesh();
Debug.LogError("网格生成完成 " + (Time.realtimeSinceStartup - time));
}
private void OnDrawGizmos()
{
}
private void GenerateHexData()
{
map = new Map(RowCount, ColumnCount, 10f);
}
private void GenerateMapMesh()
{
List<List<Hexagon>> allHexs = new List<List<Hexagon>>();
List<Hexagon> hexList = new List<Hexagon>();
foreach (var row in map.hexagonDict)
{
foreach (var hex in row.Value)
{
hexList.Add(hex.Value);
if (hexList.Count > 10000)
{
allHexs.Add(hexList);
hexList = new List<Hexagon>();
}
}
}
allHexs.Add(hexList);
for (int j = 0; j < allHexs.Count; j++)
{
GameObject obj = new GameObject("MapHex" + j);
obj.transform.SetParent(transform);
MeshRenderer meshRender = obj.AddComponent<MeshRenderer>();
meshRender.sharedMaterial = Mat;
MeshFilter filter = obj.AddComponent<MeshFilter>();
hexList = allHexs[j];
Vector3[] vertices = new Vector3[hexList.Count * 6];
int[] triangles = new int[hexList.Count * 12];
Vector2[] uvs = new Vector2[vertices.Length];
for (int i = 0; i < hexList.Count; i++)
{
Hexagon hex = hexList[i];
vertices[i * 6] = hex.Left;
vertices[i * 6 + 1] = hex.TopLeft;
vertices[i * 6 + 2] = hex.TopRight;
vertices[i * 6 + 3] = hex.Right;
vertices[i * 6 + 4] = hex.BottomRight;
vertices[i * 6 + 5] = hex.BottomLeft;
uvs[i * 6] = new Vector2(0, 0.5f);
uvs[i * 6 + 1] = new Vector2(0.25f, 1f);
uvs[i * 6 + 2] = new Vector2(0.75f, 1f);
uvs[i * 6 + 3] = new Vector2(1, 0.5f);
uvs[i * 6 + 4] = new Vector2(0.75f, 0f);
uvs[i * 6 + 5] = new Vector2(0.25f, 0f);
triangles[i * 12] = i * 6;
triangles[i * 12 + 1] = i * 6 + 1;
triangles[i * 12 + 2] = i * 6 + 5;
triangles[i * 12 + 3] = i * 6 + 1;
triangles[i * 12 + 4] = i * 6 + 2;
triangles[i * 12 + 5] = i * 6 + 5;
triangles[i * 12 + 6] = i * 6 + 2;
triangles[i * 12 + 7] = i * 6 + 3;
triangles[i * 12 + 8] = i * 6 + 5;
triangles[i * 12 + 9] = i * 6 + 3;
triangles[i * 12 + 10] = i * 6 + 4;
triangles[i * 12 + 11] = i * 6 + 5;
}
Mesh mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uvs;
mesh.RecalculateNormals();
filter.mesh = mesh;
}
}
}
public class Map
{
public float FaceSideDis;
public float FaceVertexDis;
public int RowCount;
public int ColCount;
public Dictionary<int, Dictionary<int, Hexagon>> hexagonDict = new Dictionary<int, Dictionary<int, Hexagon>>();
public Map(int r, int c, float sideDis)
{
FaceSideDis = sideDis;
FaceVertexDis = sideDis / Mathf.Sin(60 * Mathf.Deg2Rad);
RowCount = r;
ColCount = c;
float time = Time.realtimeSinceStartup;
GenerateMap();
Debug.LogError("GenerateMap Over" + (Time.realtimeSinceStartup - time));
}
public void GenerateMap()
{
float halfFaceSideDis = FaceSideDis / 2;
float halfFaceVertexDis = FaceVertexDis / 2;
float xGap = 0.75f * FaceVertexDis;
for (int r = 0; r < RowCount; r++)
{
float evenCenterY = FaceSideDis * r + FaceSideDis;
float eventTopY = evenCenterY + halfFaceSideDis;
float eventBottomY = evenCenterY - halfFaceSideDis;
float oddCenterY = halfFaceSideDis + FaceSideDis * r;
float oddTopY = oddCenterY + halfFaceSideDis;
float oddBottomY = oddCenterY - halfFaceSideDis;
for (int c = 0; c < ColCount; c++)
{
bool isOdd = c % 2 == 1;
Hexagon hex = new Hexagon(r, c);
if (!hexagonDict.ContainsKey(r))
{
hexagonDict.Add(r, new Dictionary<int, Hexagon>());
}
hexagonDict[r][c] = hex;
hex.Center = Vector3.zero;
hex.Center.x = xGap * c + halfFaceVertexDis;
hex.Center.z = isOdd ? oddCenterY : evenCenterY;
Vector3 left = Vector3.zero;
if (c == 0)
{
left.x = 0;
left.z = hex.Center.z;
}
else
{
left = isOdd ? hexagonDict[r][c - 1].BottomRight : hexagonDict[r][c - 1].TopRight;
}
hex.Left = left;
Vector3 topLeft = Vector3.zero;
if (isOdd)
{
topLeft = hexagonDict[r][c - 1].Right;
}
else
{
topLeft.x = (hex.Center.x + left.x) / 2;
topLeft.z = hex.Center.z + halfFaceSideDis;
}
hex.TopLeft = topLeft;
Vector3 right = Vector3.zero;
if (isOdd && r > 0 && c < ColCount - 1)
{
right = hexagonDict[r - 1][c + 1].TopLeft;
}
else
{
right.x = left.x + FaceVertexDis;
right.z = hex.Center.z;
}
hex.Right = right;
Vector3 topRight = Vector3.zero;
topRight.x = (hex.Center.x + right.x) / 2;
topRight.z = hex.Center.z + halfFaceSideDis;
hex.TopRight = topRight;
Vector3 bottomRight = Vector3.zero;
if (r > 0)
{
bottomRight = hexagonDict[r - 1][c].TopRight;
}
else
{
bottomRight.x = (topRight.x);
bottomRight.z = hex.Center.z - halfFaceSideDis;
}
hex.BottomRight = bottomRight;
Vector3 bottomLeft = Vector3.zero;
if (r > 0)
{
bottomLeft = hexagonDict[r - 1][c].TopLeft;
}
else if (!isOdd && c > 0)
{
bottomLeft = hexagonDict[r][c - 1].Right;
}
else
{
bottomLeft.x = (topLeft.x);
bottomLeft.z = hex.Center.z - halfFaceSideDis;
}
hex.BottomLeft = bottomLeft;
}
}
}
}
public class Hexagon
{
public int Row;
public int Col;
public Hexagon(int row, int col)
{
Row = row;
Col = col;
}
public Vector3 Center;
public Vector3 Left;
public Vector3 TopLeft;
public Vector3 TopRight;
public Vector3 Right;
public Vector3 BottomRight;
public Vector3 BottomLeft;
}
速度不慢,Drawcall少,或者还可以通过设置顶点颜色来更改颜色。
注意的点:
顶点数量太多的话无法创建,需要分成多个物体来渲染。