Unity实现六边形网格并获取顶点坐标、支持沿边移动的方案咨询
实现思路与修改方案
1. 六边形中心坐标获取
你现有代码中的CalcWorldPos方法返回的就是对应网格坐标六边形的世界中心坐标,直接存储即可使用:
- 新增二维数组或字典存储所有六边形中心坐标,生成网格时同步写入,后续可直接通过网格坐标
(x,y)快速查询
// 新增字段存储六边形中心 public Dictionary<Vector2Int, Vector3> hexCenterDict = new Dictionary<Vector2Int, Vector3>(); // CreateGrid方法中实例化prefab后添加存储逻辑 hexCenterDict.Add(new Vector2Int(x, y), hex.position);
2. 无重复顶点坐标生成
不需要通过prefab顶点挂载空物体的方式生成顶点,直接通过数学计算生成全局唯一顶点,完全避免重复问题:
核心逻辑
- 先定义边长为1的正六边形相对中心的6个顶点本地偏移,注意要和你调整gap后的尺寸同步缩放
- 用带自定义比较器的哈希集存储全局顶点,解决浮点数精度导致的去重失效问题,也可以直接通过顶点的逻辑坐标规则生成,彻底避免重复
代码示例
using System.Collections.Generic; using UnityEngine; // 新增字段 public HashSet<Vector3> allVertices = new HashSet<Vector3>(new Vector3EqualityComparer()); private Vector3[] localHexVertices; // Start方法中CreateGrid之前添加本地偏移计算 void CalcLocalVertices() { float halfWidth = hexWidth / 2; float halfHeight = hexHeight / 2; localHexVertices = new Vector3[] { new Vector3(0, 0, halfHeight), new Vector3(halfWidth, 0, halfHeight * 0.5f), new Vector3(halfWidth, 0, -halfHeight * 0.5f), new Vector3(0, 0, -halfHeight), new Vector3(-halfWidth, 0, -halfHeight * 0.5f), new Vector3(-halfWidth, 0, halfHeight * 0.5f) }; } // 新增浮点数比较器,精度可自己调整 public class Vector3EqualityComparer : IEqualityComparer<Vector3> { private float tolerance = 0.001f; public bool Equals(Vector3 a, Vector3 b) { return Mathf.Abs(a.x - b.x) < tolerance && Mathf.Abs(a.y - b.y) < tolerance && Mathf.Abs(a.z - b.z) < tolerance; } public int GetHashCode(Vector3 obj) { int x = Mathf.RoundToInt(obj.x / tolerance); int y = Mathf.RoundToInt(obj.y / tolerance); int z = Mathf.RoundToInt(obj.z / tolerance); return HashCode.Combine(x, y, z); } } // CreateGrid方法中每个六边形生成后,计算6个顶点加入哈希集 Vector3 center = CalcWorldPos(gridPos); foreach(var localOffset in localHexVertices) { Vector3 worldVertex = center + localOffset; allVertices.Add(worldVertex); }
生成完成后allVertices里就是所有不重复的全局顶点坐标。
3. 角色沿边线移动实现
可以额外维护顶点的邻接关系表,生成顶点的同时记录每个顶点相连的其他顶点,角色移动时直接查询当前顶点的邻接列表即可得到所有可移动的下一个点位:
- 用
Dictionary<Vector3, List<Vector3>> vertexNeighbors存储邻接关系 - 每个六边形生成时,不仅加顶点,还要把六边形的6条边的两个顶点互相加入对方的邻接列表
优化建议
- 不需要为顶点生成空GameObject,直接用数学计算做点击检测、移动逻辑,性能提升非常明显
- 调试阶段可以用Gizmos绘制顶点和边线,不用额外生成场景物体
// 调试用Gizmos绘制顶点 private void OnDrawGizmos() { if(allVertices == null) return; Gizmos.color = Color.red; foreach(var vertex in allVertices) { Gizmos.DrawSphere(vertex, 0.1f); } }
内容的提问来源于stack exchange,提问作者user2888384
相关产品推荐
相关产品推荐

