看到好多小伙伴似乎都想做六边形地图,我刚好在之前的demo里基于Unity3d实现了一个。
六边形地图编辑器怎么弄我就不发了,可以看看TX爸爸出的这篇博客http://gad.qq.com/program/translateview/7173811。
主要是关于寻路,AStar寻路有很多的优化方法,想要优化什么的自行百度,我就发个基础的代码(哪天我得空了可以再放一下分步讲解)。
using UnityEngine;
using System.Collections.Generic;
using System;
/// <summary>
/// 六边形地图的A*寻路,在使用时先调用AstarMainFunc方法,之后会根据输入的起始点下表改变路径上需要考虑的cell的父节点;
/// 之后该方法将父节点从终点寻址储存到移动功能类中;
/// 因为该节点是从终点寻址到起点,存在先进后出的读取要求,所以推荐用栈存储;
/// 在存储完后在移动功能类中调用ClearFValueAndGValue方法;
/// 在ClearFValueAndGValue方法被调用后才可以再进行下一次寻路;
/// 因此可以有单位同时移动,但不可以有单位同时寻路=》除非所有节点的父节点元素是一个数组;
/// 如果所有节点的父节点元素是一个数组,则在修改本类源码后,可以有该数组长度的数量的单位同时寻路。
/// 2017年12月14日 14:07:03
/// 最后一次修改人:朱珂杰
/// </summary>
class AStarMain : MonoBehaviour
{
private HexCell[] cellsForAll;
private List<int> cellsForOpenContainer;
private List<int> cellsForOpen;
private List<int> cellsForClose;
private int currentCellIndex;
private int hValue;
/// <summary>
/// HexGrid中的width,需要在代码中赋值
/// </summary>
private int width = 0;
private int height = 0;
/// <summary>
/// 某一点四周所有点的集合,第一个是该点右上角的点,然后按照顺时针直至该点左上角,y坐标为-x-z
/// 以下为备用元素,在地图大改时可能会需要
/// </summary>
//private HexCoordinates[] aroundHexCoordinates = {
// new HexCoordinates (0, 1),
// new HexCoordinates(1, 0),
// new HexCoordinates(1, -1),
// new HexCoordinates(0, -1),
// new HexCoordinates(-1, 0),
// new HexCoordinates(-1, 1),
//};
//private int[] aroundHexCellForIndex;
public void Awake()
{
cellsForOpenContainer = new List<int>();
cellsForOpen = new List<int>();
cellsForClose = new List<int>();
}
public void Start()
{
GetCells();
width = GameObject.Find("HexPlaneRoot").GetComponent<HexGrid>().width;
height = GameObject.Find("HexPlaneRoot").GetComponent<HexGrid>().height;
Debug.Log("得到cells");
}
private void GetCells()
{
cellsForAll = GameObject.Find("HexPlaneRoot").transform.GetComponentsInChildren<HexCell>();
}
/// <summary>
/// 寻路主函数,先不考虑行数很低时的情况;
/// 在运行结束后,根据cellForEndIndex下标对应的cell的父节点寻踪直至起始点得到路径
/// </summary>
/// <param name="cell">起始点</param>
public void AstarMainFunc(int cellForBeginIndex, int cellForEndIndex)
{
//1,将cellForBegin添加到关闭列表
cellsForClose.Add(cellForBeginIndex);
currentCellIndex = cellForBeginIndex;
AddCellsToOpen();
while (!cellsForOpen.Contains(cellForEndIndex))
{
//遍历开放列表找出所有点中F最小的点
int fValueMinIndexInOpen = 0;
if (cellsForOpen.Count > 1)
for (int i = 1; i < cellsForOpen.Count; i++)
{
//hValue
hValue = cellsForAll[cellForEndIndex].coordinates - cellsForAll[cellsForOpen[i]].coordinates;
cellsForAll[cellsForOpen[i]].fValue = cellsForAll[cellsForOpen[i]].gValue + hValue;
if (cellsForAll[cellsForOpen[i]].fValue < cellsForAll[cellsForOpen[fValueMinIndexInOpen]].fValue)
fValueMinIndexInOpen = i;
}
//将该点添加到关闭列表中
cellsForClose.Add(cellsForOpen[fValueMinIndexInOpen]);
//将该点从开放列表移除