# 六边形地图

``````using UnityEngine;

public static class HexMetrics {

public const float outerRadius = 10f;

}
``````

``````public static Vector3[] corners = {
};
``````
1. 网格构造
按最简单的方式来，创建一个默认的plane，把cell组件加上去，然后做成prefab。
``````using UnityEngine;

public class HexCell : MonoBehaviour
{
}
``````

``````using UnityEngine;

public class HexGrid : MonoBehaviour
{

public int width = 6;
public int height = 6;

public HexCell cellPrefab;

}
``````
HexGrid对象

``````HexCell[] cells;

void Awake()
{
cells = new HexCell[height * width];

for (int z = 0, i = 0; z < height; z++)
{
for (int x = 0; x < width; x++)
{
CreateCell(x, z, i++);
}
}
}

void CreateCell(int x, int z, int i)
{
Vector3 position;
position.x = x * 10f;
position.y = 0f;
position.z = z * 10f;

HexCell cell = cells[i] = Instantiate<HexCell>(cellPrefab);
cell.transform.SetParent(transform, false);
cell.transform.localPosition = position;
}
``````

2.1显示坐标

``````void CreateCell(int x, int z, int i)
{
…

Text label = Instantiate<Text>(cellLabelPrefab);
label.rectTransform.SetParent(gridCanvas.transform, false);
label.rectTransform.anchoredPosition = new Vector2(position.x, position.z);
label.text = x.ToString() + "\n" + z.ToString();
}
``````

2.2六边形位置

``````position.x = x * (HexMetrics.innerRadius * 2f);
position.y = 0f;
position.z = z * (HexMetrics.outerRadius * 1.5f);
``````

`````` position.x = (x +（z % 2)*0.5f) * (HexMetrics.innerRadius * 2f);
``````

3.渲染六边形

``````using UnityEngine;
using System.Collections.Generic;

[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class HexMesh : MonoBehaviour
{

Mesh hexMesh;
List<Vector3> vertices;
List<int> triangles;

void Awake()
{
GetComponent<MeshFilter>().mesh = hexMesh = new Mesh();
hexMesh.name = "Hex Mesh";
vertices = new List<Vector3>();
triangles = new List<int>();
}
}
``````

HexMesh对象
``````public void Triangulate(HexCell[] cells)
{
hexMesh.Clear();
vertices.Clear();
triangles.Clear();
for (int i = 0; i < cells.Length; I++)
{
Triangulate(cells[I]);
}
hexMesh.vertices = vertices.ToArray();
hexMesh.triangles = triangles.ToArray();
hexMesh.RecalculateNormals();
}

void Triangulate(HexCell cell)
{
}
``````

``````void AddTriangle(Vector3 v1, Vector3 v2, Vector3 v3)
{
int vertexIndex = vertices.Count;
}
``````

``````void Triangulate(HexCell cell)
{
Vector3 center = cell.transform.localPosition;
center,
center + HexMetrics.corners[0],
center + HexMetrics.corners[1]
);
}
``````

``````Vector3 center = cell.transform.localPosition;
for (int i = 0; i< 6; i++) {
center,
center + HexMetrics.corners[I],
center + HexMetrics.corners[i + 1]
);
}
``````

``````using UnityEngine;

[System.Serializable]
public struct HexCoordinates
{
public int X { get; private set; }
public int Z { get; private set; }
public HexCoordinates(int x, int z)
{
X = x;
Z = z;
}

X轴的偏移。EX:(0,2)原本会在(0,0)隔一行的正上方，而正确的位置应该是往右偏一格。以此类推，偶行+Z/2（注意Z是整型，结果会取整）
public static HexCoordinates FromOffsetCoordinates(int x, int z)
{
return new HexCoordinates(x - z / 2, z);
}
}
``````

``````public int Y
{
get
{
return -X - Z;
}
}

public override string ToString()
{
return "(" +
X.ToString() + ", " + Y.ToString() + ", " + Z.ToString() + ")";
}

public string ToStringOnSeparateLines()
{
return X.ToString() + "\n" + Y.ToString() + "\n" + Z.ToString();
}
``````

4.1 Inspector里的坐标

``````using UnityEngine;
using UnityEditor;

[CustomPropertyDrawer(typeof(HexCoordinates))]
public class HexCoordinatesDrawer : PropertyDrawer
{
}
``````

Property drawers通过`OnGUI`渲染其内容。提供了屏幕坐标、系列化属性和属性名称标签。

``````public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
HexCoordinates coordinates = new HexCoordinates(
property.FindPropertyRelative("x").intValue,
property.FindPropertyRelative("z").intValue
);
position = EditorGUI.PrefixLabel(position, label);
GUI.Label(position, coordinates.ToString());
}
``````

`EditorGUI.PrefixLabel`用来加前缀标签，并且返回新的位置

1. 触摸格子

`Physics.Raycast`实现，前提是给`HexMesh`一个mesh collider。

``````
MeshCollider meshCollider;

void Awake()
{
GetComponent<MeshFilter>().mesh = hexMesh = new Mesh();
…
}
``````

``````public void Triangulate(HexCell[] cells)
{
…
meshCollider.sharedMesh = hexMesh;
}
``````

``````public void TouchCell(Vector3 position)
{
position = transform.InverseTransformPoint(position);
HexCoordinates coordinates = HexCoordinates.FromPosition(position);
Debug.Log("touched at " + coordinates.ToString());
}
``````

``````public static HexCoordinates FromPosition(Vector3 position)
{
float x = position.x / (HexMetrics.innerRadius * 2f);
float y = -x;
}
``````

``````float offset = position.z / (HexMetrics.outerRadius * 3f);
x -= offset;
y -= offset;
``````

``````int iX = Mathf.RoundToInt(x);
int iY = Mathf.RoundToInt(y);
int iZ = Mathf.RoundToInt(-x - y);

return new HexCoordinates(iX, iZ);
``````

``````if (iX + iY + iZ != 0) {
Debug.LogWarning("rounding error!");
}

return new HexCoordinates(iX, iZ)
``````

``````if (iX + iY + iZ != 0)
{
float dX = Mathf.Abs(x - iX);
float dY = Mathf.Abs(y - iY);
float dZ = Mathf.Abs(-x - y - iZ);

if (dX > dY && dX > dZ) {
iX = -iY - iZ;
}
else if (dZ > dY) {
iZ = -iX - iY;
}
}
``````

5.1给六边形着色

`HexGrid`一个默认色和点击色

``````public Color defaultColor = Color.white;
public Color touchedColor = Color.magenta;
``````

`HexCell`一个颜色字段。并在创建格子的时候把默认色给它

``````
public class HexCell : MonoBehaviour
{

public HexCoordinates coordinates;

public Color color;

…
void CreateCell(int x, int z, int i)
{
…
cell.coordinates = HexCoordinates.FromOffsetCoordinates(x, z);
cell.color = defaultColor;
…
}
}
``````

``````List<Color> colors;

void Awake()
{
…
vertices = new List<Vector3>();
colors = new List<Color>();
…
}

public void Triangulate(HexCell[] cells)
{
hexMesh.Clear();
vertices.Clear();
colors.Clear();
…
hexMesh.vertices = vertices.ToArray();
hexMesh.colors = colors.ToArray();
…
}
``````

``````void Triangulate(HexCell cell)
{
Vector3 center = cell.transform.localPosition;
for (int i = 0; i < 6; i++)
{
center,
center + HexMetrics.corners[i],
center + HexMetrics.corners[i + 1]
);
}
}

{
}
``````

``````public void TouchCell(Vector3 position)
{
position = transform.InverseTransformPoint(position);
HexCoordinates coordinates = HexCoordinates.FromPosition(position);
int index = coordinates.X + coordinates.Z * width + coordinates.Z / 2;
HexCell cell = cells[index];
cell.color = touchedColor;
hexMesh.Triangulate(cells);
}
``````

``````Shader "Custom/VertexColors" {
Properties {
_Color("Color", Color) = (1,1,1,1)
_MainTex("Albedo (RGB)", 2D) = "white" {}
_Glossiness("Smoothness", Range(0,1)) = 0.5
_Metallic("Metallic", Range(0,1)) = 0.0
}
Tags { "RenderType"="Opaque" }
LOD 200

CGPROGRAM
#pragma target 3.0

sampler2D _MainTex;

struct Input
{
float2 uv_MainTex;
float4 color : COLOR; //这里加上颜色
};

half _Glossiness;
half _Metallic;
fixed4 _Color;

void surf(Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb * IN.color; //改这里
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
``````