-
Notifications
You must be signed in to change notification settings - Fork 1
/
Pathfinder.cs
120 lines (103 loc) · 4.28 KB
/
Pathfinder.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TilePathFinder
{
public class Pathfinder
{
public Grid TileGrid;
public string BlockingTag;
public string FloorTag = "Floor";
// Start is called before the first frame update
private NodeGrid ng;
public Pathfinder(Grid _TileGrid, string _BlockingTag, string _FloorTag)
{
TileGrid = _TileGrid;
BlockingTag = _BlockingTag;
FloorTag = _FloorTag;
ng = new NodeGrid(TileGrid, BlockingTag, FloorTag);
}
int GetDistance(Node nodeA, Node nodeB)
{
int dstX = Mathf.Abs(nodeA.gridX - nodeB.gridX);
int dstY = Mathf.Abs(nodeA.gridY - nodeB.gridY);
if (dstX > dstY)
return 14 * dstY + 10 * (dstX - dstY);
return 14 * dstX + 10 * (dstY - dstX);
}
List<Node> RetracePath(Node startNode, Node endNode)
{
List<Node> path = new List<Node>();
Node currentNode = endNode;
while (currentNode != startNode)
{
path.Add(currentNode);
currentNode = currentNode.parent;
}
path.Reverse();
return path;
}
public List<Vector3Int> FindPath(Vector3Int from, Vector3Int to)
{
if (from.x + ng.xOffset < 0 || from.y + ng.yOffset < 0 || to.x + ng.xOffset < 0 || to.y + ng.yOffset < 0)
{
return new List<Vector3Int>();
}
if (from.x + ng.xOffset > ng.nodeArray.GetLength(0) || from.y + ng.yOffset > ng.nodeArray.GetLength(1) || to.x + ng.xOffset > ng.nodeArray.GetLength(0) || to.y + ng.yOffset > ng.nodeArray.GetLength(1))
{
return new List<Vector3Int>();
}
Node startNode = ng.nodeArray[from.x + ng.xOffset, from.y + ng.yOffset];
Node targetNode = ng.nodeArray[to.x + ng.xOffset, to.y + ng.yOffset];
if (startNode == null || startNode.walkable == false || targetNode == null || targetNode.walkable == false)
return new List<Vector3Int>();
List<Node> openSet = new List<Node>();
HashSet<Node> closedSet = new HashSet<Node>();
openSet.Add(startNode);
while (openSet.Count > 0)
{
Node node = openSet[0];
for (int i = 1; i < openSet.Count; i++)
{
if (openSet[i].fCost < node.fCost || openSet[i].fCost == node.fCost)
{
if (openSet[i].hCost < node.hCost)
node = openSet[i];
}
}
openSet.Remove(node);
closedSet.Add(node);
if (node == targetNode)
{
return NodePathToIntPath(RetracePath(startNode, targetNode));
}
foreach (Node neighbour in ng.GetNeighbours(node))
{
if (!neighbour.walkable || closedSet.Contains(neighbour))
{
continue;
}
int newCostToNeighbour = node.gCost + GetDistance(node, neighbour);
if (newCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour))
{
neighbour.gCost = newCostToNeighbour;
neighbour.hCost = GetDistance(neighbour, targetNode);
neighbour.parent = node;
if (!openSet.Contains(neighbour))
openSet.Add(neighbour);
}
}
}
return NodePathToIntPath(RetracePath(startNode, targetNode));
}
List<Vector3Int> NodePathToIntPath(List<Node> nodePath)
{
List<Vector3Int> path = new List<Vector3Int>();
foreach (Node node in nodePath)
{
path.Add(new Vector3Int(node.gridX - ng.xOffset, node.gridY - ng.yOffset, 0));
}
return path;
}
}
}