项目地址:https://github.com/kotomineshiki/AIFindPath
视频地址:多重寻路
综合寻路——包括攻击考量的寻路算法
GamePlay
这是一个《文明》+皇室战争的组合。
UI层使用状态机来实现以下操作
1. 点击棋子再点击格子,棋子移动向格子(AStar算法)
2. 点击棋子会弹出该棋子的属性介绍面板,再点击一次取消
3. 点击格子会弹出该格子的属性介绍面板,再点击一次取消
4. 点击底部召唤板,再点击格子,会在该格子处召唤一个棋子
5. 点击召唤板未点击格子时,会在鼠标停留的格子上出现一个虚影
6. 点击棋子再点击另一个棋子的时候,该棋子移动向另一个棋子,如果他们处于敌对阵营,则该棋子列入攻击列表
一些bug:
AStar算法不要使用多线程,因为如果节点情况有变,则会产生线程合并的冲突导致抖动。
其实Astar算法和作为AI的势能场算法是有冲突的,下次重构的时候应该特别注意只使用势能场。因为势能场本身就已经包括了寻路算法,所以没必要特意写一个寻路算法增加代码复杂度,这是这次经验不足导致的。
两个核心难点
Astar算法
先是自己实现了一遍,后来找到了效率更高的插件就重构了
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MyAStar {
public ArrayList openList;
public ArrayList closeList;
public int targetX;
public int targetY;
public Vector2Int start;
public Vector2Int end;
public Stack<string> parentList;//结果栈,存的格式是xy
public List<Vector2Int> resultPath;//结果队列
//public Transform plane;
//public Transform obstacle;
private float alpha = 0;
private float incrementPer = 0;
public void SetStartGrid(int x, int y)
{
start.x = x;
start.y = y;
GridMap.instance.grids[x, y].SetGridType(GridType.Start);
openList.Add(GridMap.instance.grids[x, y]);
}
public void SetEndGrid(int x, int y)
{
end.x = x;
end.y = y;
GridMap.instance.grids[x, y].SetGridType(GridType.End);
}
public void Clear()
{
GridMap.instance.grids[start.x, start.y].SetGridType(GridType.Normal);
GridMap.instance.grids[end.x, end.y].SetGridType(GridType.Normal);//恢复初始状态
for(int i = 0; i < GridMap.instance.row; ++i)
{
for(int j = 0; j < GridMap.instance.column; ++j)
{
GridMap.instance.grids[i, j].parent = null;
GridMap.instance.grids[i, j].f = 0;
GridMap.instance.grids[i, j].g = 0;
GridMap.instance.grids[i, j].h = 0;
}
}
parentList.Clear();
openList.Clear();
closeList.Clear();
resultPath.Clear();
}
public MyAStar()//初始化函数
{
parentList = new Stack<string>();
openList = new ArrayList();
closeList = new ArrayList();
resultPath = new List<Vector2Int>();
Debug.Log("初始化完成");
}
public void Calculate()
{
Debug.Log("开始寻找路径");
//yield return new WaitForSeconds(0.1f);
//openList.Add(grids[startX, startY]);
MyGrid currentGrid = openList[0] as MyGrid;
while (openList.Count > 0 && currentGrid.gridType != GridType.End)
{
currentGrid = openList[0] as MyGrid;
if (currentGrid.gridType == GridType.End)
{
Debug.Log("找到路径");
GenerateResult(currentGrid);
}
for(int i = -1; i <= 1; i++)
{
for(int j = -1; j <= 1; j++)
{
if (i != 0 || j != 0)
{
in