205 lines
7.6 KiB
C#
205 lines
7.6 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public class astar_vertex : MonoBehaviour
|
|
{
|
|
public Transform VertexGroup;
|
|
[SerializeField]
|
|
public List<Vertex> nodes;
|
|
|
|
Vertex startNode;
|
|
Vertex endNode;
|
|
|
|
public Transform startVisualizer;
|
|
public Transform endVisualizer;
|
|
public PathWalker walker;
|
|
|
|
public List<Vertex> finalPath;
|
|
void Start()
|
|
{
|
|
finalPath = new List<Vertex>();
|
|
nodes = new List<Vertex>();
|
|
foreach(Vertex vertex in VertexGroup.GetComponentsInChildren<Vertex>()){
|
|
NodeData nodeData = vertex.gameObject.AddComponent(typeof(NodeData)) as NodeData;
|
|
nodes.Add(vertex);
|
|
}
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
if(startNode != null){Debug.DrawLine(startVisualizer.position, startNode.transform.position);}
|
|
if(endNode != null){Debug.DrawLine(endVisualizer.position, endNode.transform.position);}
|
|
if(Input.GetKeyDown(KeyCode.E)){
|
|
Vector2 startPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
|
|
startVisualizer.position = startPos;
|
|
|
|
//get closest and reachable node to this location
|
|
float minDist = Mathf.Infinity;
|
|
|
|
foreach(Vertex node in nodes){
|
|
if(Physics2D.Linecast(startPos, node.transform.position)){}else{
|
|
float distToNode = Vector2.Distance(node.transform.position, startPos);
|
|
if(distToNode < minDist){
|
|
minDist = distToNode;
|
|
startNode = node;
|
|
}
|
|
}
|
|
}
|
|
}else if(Input.GetKeyDown(KeyCode.F)){
|
|
Vector2 endPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
|
|
endVisualizer.position = endPos;
|
|
|
|
//get closest and reachable node to this location
|
|
float minDist = Mathf.Infinity;
|
|
|
|
foreach(Vertex node in nodes){
|
|
if(Physics2D.Linecast(endPos, node.transform.position)){}else{
|
|
float distToNode = Vector2.Distance(node.transform.position, endPos);
|
|
if(distToNode < minDist){
|
|
minDist = distToNode;
|
|
endNode = node;
|
|
}
|
|
}
|
|
}
|
|
}else if(Input.GetKeyDown(KeyCode.Return)){
|
|
//Start Calculation
|
|
StartCoroutine(Calculate());
|
|
}else if(Input.GetKeyDown(KeyCode.I)){
|
|
Recalculate();
|
|
}else if(Input.GetKeyDown(KeyCode.S)){
|
|
Recalculate();
|
|
walker.pathNodes = new List<Transform>();
|
|
walker.curIndex = 0;
|
|
walker.pathNodes.Add(startNode.transform);
|
|
for(int i = finalPath.Count-1; i >=0; i--){
|
|
walker.pathNodes.Add(finalPath[i].transform);
|
|
}
|
|
walker.pathNodes.Add(endVisualizer);
|
|
}
|
|
|
|
if(finalPath.Count > 1){
|
|
for(int i = 1; i < finalPath.Count; i++){
|
|
Debug.DrawLine(finalPath[i].transform.position, finalPath[i-1].transform.position, Color.green);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Recalculate(){
|
|
DateTime startTime = DateTime.Now;
|
|
foreach(Vertex node in nodes){
|
|
node.GetComponent<NodeData>().Reset();
|
|
}
|
|
|
|
List<Vertex> open = new List<Vertex>();
|
|
List<Vertex> close = new List<Vertex>();
|
|
open.Add(startNode);
|
|
bool foundPath = false;
|
|
while(!foundPath){
|
|
Vertex current = null;
|
|
float lowestF = Mathf.Infinity;
|
|
foreach(Vertex cell in open){
|
|
if(cell.GetComponent<NodeData>().fCost < lowestF){
|
|
lowestF = cell.GetComponent<NodeData>().fCost;
|
|
current = cell;
|
|
}
|
|
}
|
|
open.Remove(current);
|
|
close.Add(current);
|
|
|
|
if(current == endNode){foundPath=true; continue;}
|
|
foreach(Vertex neighbour in current.neighbours){
|
|
if(close.Contains(neighbour)){continue;}
|
|
bool hasThisNeighbour = open.Contains(neighbour);
|
|
if(neighbour.GetComponent<NodeData>().fCost < lowestF || !hasThisNeighbour){
|
|
calculateCellCost(neighbour.GetComponent<NodeData>());
|
|
if(neighbour.GetComponent<NodeData>().fCost < lowestF || neighbour.GetComponent<NodeData>().parent==null){ neighbour.GetComponent<NodeData>().parent = current;}
|
|
if(!hasThisNeighbour){open.Add(neighbour);}
|
|
}
|
|
}
|
|
// yield return new WaitForSeconds(0.05f);
|
|
}
|
|
|
|
//sort
|
|
bool pathCleared = false;
|
|
Vertex parentCell = endNode;
|
|
finalPath= new List<Vertex>();
|
|
while(!pathCleared){
|
|
|
|
if(parentCell == startNode){pathCleared=true; break;}
|
|
finalPath.Add(parentCell);
|
|
parentCell = parentCell.GetComponent<NodeData>().parent;
|
|
// yield return new WaitForSeconds(0.1f);
|
|
}
|
|
|
|
Debug.Log("Calculation finished in " + (DateTime.Now - startTime).TotalMilliseconds + "ms");
|
|
}
|
|
|
|
IEnumerator Calculate(){
|
|
DateTime startTime = DateTime.Now;
|
|
foreach(Vertex node in nodes){
|
|
node.GetComponent<NodeData>().Reset();
|
|
}
|
|
List<Vertex> open = new List<Vertex>();
|
|
List<Vertex> close = new List<Vertex>();
|
|
open.Add(startNode);
|
|
bool foundPath = false;
|
|
while(!foundPath){
|
|
Vertex current = null;
|
|
float lowestF = Mathf.Infinity;
|
|
foreach(Vertex cell in open){
|
|
if(cell.GetComponent<NodeData>().fCost < lowestF){
|
|
lowestF = cell.GetComponent<NodeData>().fCost;
|
|
current = cell;
|
|
}
|
|
}
|
|
open.Remove(current);
|
|
close.Add(current);
|
|
|
|
if(current == endNode){foundPath=true; continue;}
|
|
foreach(Vertex neighbour in current.neighbours){
|
|
if(close.Contains(neighbour)){continue;}
|
|
bool hasThisNeighbour = open.Contains(neighbour);
|
|
if(neighbour.GetComponent<NodeData>().fCost < lowestF || !hasThisNeighbour){
|
|
calculateCellCost(neighbour.GetComponent<NodeData>());
|
|
if(neighbour.GetComponent<NodeData>().fCost < lowestF || neighbour.GetComponent<NodeData>().parent==null){ neighbour.GetComponent<NodeData>().parent = current;}
|
|
if(!hasThisNeighbour){open.Add(neighbour);}
|
|
}
|
|
}
|
|
// yield return new WaitForSeconds(0.05f);
|
|
}
|
|
|
|
//sort
|
|
bool pathCleared = false;
|
|
Vertex parentCell = endNode;
|
|
finalPath= new List<Vertex>();
|
|
while(!pathCleared){
|
|
|
|
if(parentCell == startNode){pathCleared=true; break;}
|
|
finalPath.Add(parentCell);
|
|
parentCell = parentCell.GetComponent<NodeData>().parent;
|
|
yield return new WaitForSeconds(0.1f);
|
|
}
|
|
Debug.Log("Calculation finished in " + (DateTime.Now - startTime).Milliseconds + "ms");
|
|
}
|
|
|
|
|
|
|
|
bool calculateCellCost(NodeData cell){
|
|
if((int)cell.fCost!=0){return false;}
|
|
cell.hCost = Vector2.Distance(cell.transform.position, endNode.transform.position);
|
|
cell.gCost = Vector2.Distance(cell.transform.position, startNode.transform.position);
|
|
cell.fCost = cell.hCost + cell.gCost;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void OnValidate(){
|
|
if(VertexGroup !=null && VertexGroup.GetComponentInChildren<Vertex>()==null){VertexGroup = null; Debug.LogError("Please assigna a vertex group with vertecies as children");}
|
|
}
|
|
}
|
|
|