From c2f412b62e2cc553981064dd8ad3442bec782282 Mon Sep 17 00:00:00 2001 From: juliuse98 Date: Tue, 28 Sep 2021 11:22:17 +0200 Subject: [PATCH] PathMap Class +Made the PathMap into a standalone class --- Assets/Scenes/NPCTest.unity | 13 ++ Assets/Scripts/NPC/NPCController.cs | 45 ++++ Assets/Scripts/NPC/NPCController.cs.meta | 11 + Assets/Scripts/NPC/PathGenerator.cs | 30 ++- Assets/Scripts/NPC/PathMap.cs | 260 ++++++++++++++++------- 5 files changed, 280 insertions(+), 79 deletions(-) create mode 100644 Assets/Scripts/NPC/NPCController.cs create mode 100644 Assets/Scripts/NPC/NPCController.cs.meta diff --git a/Assets/Scenes/NPCTest.unity b/Assets/Scenes/NPCTest.unity index 52c86de..209bdca 100644 --- a/Assets/Scenes/NPCTest.unity +++ b/Assets/Scenes/NPCTest.unity @@ -308,6 +308,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 1438121555} + - component: {fileID: 1438121556} m_Layer: 0 m_Name: Map m_TagString: Untagged @@ -329,3 +330,15 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1438121556 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1438121554} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ef9b1c03bb478e84b931f1cbb3bbab8c, type: 3} + m_Name: + m_EditorClassIdentifier: diff --git a/Assets/Scripts/NPC/NPCController.cs b/Assets/Scripts/NPC/NPCController.cs new file mode 100644 index 0000000..a343cdb --- /dev/null +++ b/Assets/Scripts/NPC/NPCController.cs @@ -0,0 +1,45 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class NPCController : MonoBehaviour +{ + + PathMap Map; + private GameObject[,] ball; + public List path; + + // Start is called before the first frame update + void Start() + { + ball = new GameObject[30, 30]; + Map = new PathMap(new Vector3(0, 0, 0), 30, 30, 30); + for (int r = 0; r < 30; r++) + { + for (int c = 0; c < 30; c++) + { + GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Cube); + sphere.transform.position = Map.map[r, c].Position; + ball[r, c] = sphere; + + + } + } + path = Map.QueryNodes(new Vector3(0,0, 0), new Vector3(100, 0,100)); + //Debug.Log("yeet"); + Debug.Log(path.Count); + Debug.Log((int)path[0].index.x + " "+ (int)path[0].index.y); + for (int i = 0; i < path.Count - 1; i++) { + int x = path[i].index.x; + int y = path[i].index.y; + Destroy(ball[x, y]); + } + + } + + // Update is called once per frame + void Update() + { + + } +} diff --git a/Assets/Scripts/NPC/NPCController.cs.meta b/Assets/Scripts/NPC/NPCController.cs.meta new file mode 100644 index 0000000..098ddac --- /dev/null +++ b/Assets/Scripts/NPC/NPCController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef9b1c03bb478e84b931f1cbb3bbab8c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/NPC/PathGenerator.cs b/Assets/Scripts/NPC/PathGenerator.cs index 4d5b404..10a97a8 100644 --- a/Assets/Scripts/NPC/PathGenerator.cs +++ b/Assets/Scripts/NPC/PathGenerator.cs @@ -1,3 +1,5 @@ + + using System.Collections; using System.Collections.Generic; using UnityEngine; @@ -6,12 +8,32 @@ public class PathNode { private Vector3 position; - public Vector2 index; - private float score; - public PathNode(Vector3 Pos, float Score) { + public Vector2Int index; + private float scoreF; + private float scoreG; + private float scoreH; + public List neigbors; + private PathMap lowerLevel; + private PathNode previous; + + public PathNode(Vector3 Pos) + { + neigbors = new List(); position = Pos; - score = Score; + scoreG = Mathf.Infinity; + scoreF = Mathf.Infinity; + scoreH = Mathf.Infinity; } + + public void activateNextLevel() + { + //lowerLevel = new PathMap(30, 30, float width, float height); + } + public Vector3 Position { get => position; set => position = value; } + public float Hscore { get => scoreH; set => scoreH = value; } + public float Gscore { get => scoreG; set => scoreG = value; } + public float Fscore { get => scoreF; set => scoreF = value; } + public PathNode Previous { get => previous; set => previous = value; } } diff --git a/Assets/Scripts/NPC/PathMap.cs b/Assets/Scripts/NPC/PathMap.cs index 49d1c86..4d71fb8 100644 --- a/Assets/Scripts/NPC/PathMap.cs +++ b/Assets/Scripts/NPC/PathMap.cs @@ -2,118 +2,228 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; -public class PathMap : MonoBehaviour +public class PathMap { + + private Vector3 position; - private PathNode[,] map; - private GameObject[,] ball; - private int rows = 40; - private int cols = 40; + public PathNode[,] map; + + private int rows = 30; + private int cols = 30; private float spacing = 1f; private float height = 0; + public Terrain t; + private float w, h; private PathNode[] uncheckedNodes; private List openList; private List closedList; private List nextList; - void Start() + private List path; + + + public PathMap(Vector3 Position, int Rows, int Cols, float Width) { - map = new PathNode[40, 40]; - ball = new GameObject[rows, cols]; + position = Position; + rows = Rows; + cols = Cols; + w = Width; + + //Array of all pathnodes in this chunk. + map = new PathNode[rows, cols]; + + + //only for debugging + + + openList = new List(); closedList = new List(); - nextList = new List(); + //Path that will be returned at the end. + path = new List(); + + //Add all nodes into the map. for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { - PathNode node = new PathNode(new Vector3(r * spacing, height, c * spacing), 1f); - node.index = new Vector2(r,c); + PathNode node = new PathNode(new Vector3(position.x + r * spacing, position.y + height, position.z + c * spacing)); + node.index = new Vector2Int(r, c); map[r, c] = node; - } - } - - - for (int r = 0; r < rows; r++) - { - for (int c = 0; c < cols; c++) - { - GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); - sphere.transform.position = map[r,c].Position; - ball[r,c] = sphere; - } } - FindClosestNode(new Vector3(0.7f,2,0.7f)); + + //Add the references to the neighbors of all nodes + AddAllNeighbors(); } - private void AddAllNeigbors(Vector2 index) { - if ((int)index.x - 1 >= 0 && (int) index.y - 1 >= 0 && !openList.Contains(map[(int)index.x - 1, (int)index.y - 1])) { - openList.Add(map[(int)index.x - 1, (int)index.y - 1]); - } - if ((int)index.y - 1 >= 0 && !openList.Contains(map[(int)index.x, (int)index.y - 1])) - { - openList.Add(map[(int)index.x, (int)index.y - 1]); - } - if ((int)index.x + 1 <= rows && (int)index.y - 1 >= 0 && !openList.Contains(map[(int)index.x + 1, (int)index.y - 1])) - { - openList.Add(map[(int)index.x + 1, (int)index.y - 1]); - } - if ((int)index.x - 1 >= 0 && !openList.Contains(map[(int)index.x - 1, (int)index.y])) - { - openList.Add(map[(int)index.x - 1, (int)index.y]); - } - if ((int)index.x + 1 <= rows && (int)index.y - 1 >= 0 && !openList.Contains(map[(int)index.x + 1, (int)index.y])) - { - openList.Add(map[(int)index.x + 1, (int)index.y]); - } - - - - if ((int)index.x - 1 >= 0 && (int)index.y + 1 <= cols && !openList.Contains(map[(int)index.x - 1, (int)index.y + 1])) - { - openList.Add(map[(int)index.x - 1, (int)index.y + 1]); - } - if ((int)index.y + 1 <= cols && !openList.Contains(map[(int)index.x, (int)index.y + 1])) - { - openList.Add(map[(int)index.x, (int)index.y + 1]); - } - if ((int)index.x + 1 <= rows && (int)index.y + 1 <= cols && !openList.Contains(map[(int)index.x + 1, (int)index.y + 1])) - { - openList.Add(map[(int)index.x + 1, (int)index.y + 1]); - } - - } - private PathNode FindClosestNode(Vector3 pos) { + private PathNode FindClosestNode(Vector3 pos) + { if (pos.x > 0 && pos.x < rows * spacing && pos.z > 0 && pos.z < cols * spacing) { - Destroy(ball[Mathf.RoundToInt(pos.x / spacing), Mathf.RoundToInt(pos.z / spacing)]); - return map[Mathf.RoundToInt(pos.x / 2), Mathf.RoundToInt(pos.z / 2)]; + + return map[Mathf.RoundToInt(pos.x / spacing), Mathf.RoundToInt(pos.z / spacing)]; } - else { - return null; - } - } - public void QueryNodes() { - PathNode currentNode; + Vector2Int best = new Vector2Int(0,0); + for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { - currentNode = map[r,c]; + if (Vector3.Distance(map[best.x, best.y].Position, pos) > Vector3.Distance(map[r, c].Position, pos)) { + best.Set(r,c); + } } } + return map[best.x,best.y]; + } + public List QueryNodes(Vector3 Vstart, Vector3 Vend) + { + bool finished = false; + + PathNode start = FindClosestNode(Vstart); + start.Gscore = 0; + PathNode end = FindClosestNode(Vend); + + Debug.Log("Searching a path from " + start.index + " to " + end.index); + openList.Add(start); + + PathNode current; + int d = 0; + while (!finished) + { + d++; + if (d > 1000) + { + Debug.Log("Mist! Has not found a path"); + return null; + } + int winner = 0; + for (int i = 0; i < openList.Count; i++) + { + + if (openList[i].Fscore < openList[winner].Fscore) winner = i; + } + current = openList[winner]; + openList.RemoveAt(winner); + closedList.Add(current); + + + + if (current != end) + { + foreach (PathNode p in current.neigbors) + { + if (!closedList.Contains(p)) + { + float tempG = current.Gscore + heuristic(p.Position, current.Position); + bool newPath = false; + if (openList.Contains(p)) + { + if (tempG < p.Gscore) + { + p.Gscore = tempG; + newPath = true; + } + } + else + { + p.Gscore = tempG; + newPath = true; + openList.Add(p); + } + if (newPath) + { + p.Hscore = heuristic(p.Position, end.Position); + p.Fscore = p.Gscore + p.Hscore; + p.Previous = current; + } + + } + + } + } + else + { + Debug.Log("Path Has Been Found"); + PathNode temp = end; + path.Add(temp); + while (temp.Previous != null) + { + path.Add(temp.Previous); + temp = temp.Previous; + } + path.Add(start); + finished = true; + return path; + } + } + return null; + } + + + private float heuristic(Vector3 pos1, Vector3 pos2) + { + //Calculates the HScore for a node. + return Vector3.Distance(pos1, pos2); + + } + private void AddAllNeighbors() + { + for (int r = 0; r < rows; r++) + { + for (int c = 0; c < cols; c++) + { + AddNeighbors(new Vector2(r, c)); + } + } } - - // Update is called once per frame - void Update() + private void AddNeighbors(Vector2 index) { + //Adds references to all neigbors of a node. + if ((int)index.x - 1 >= 0 && (int)index.y - 1 >= 0) + { + map[(int)index.x, (int)index.y].neigbors.Add(map[(int)index.x - 1, (int)index.y - 1]); + } + if ((int)index.y - 1 >= 0) + { + map[(int)index.x, (int)index.y].neigbors.Add(map[(int)index.x, (int)index.y - 1]); + } + if ((int)index.x + 1 < rows && (int)index.y - 1 >= 0) + { + map[(int)index.x, (int)index.y].neigbors.Add(map[(int)index.x + 1, (int)index.y - 1]); + } + + if ((int)index.x - 1 >= 0) + { + map[(int)index.x, (int)index.y].neigbors.Add(map[(int)index.x - 1, (int)index.y]); + } + if ((int)index.x + 1 < rows && (int)index.y >= 0) + { + map[(int)index.x, (int)index.y].neigbors.Add(map[(int)index.x + 1, (int)index.y]); + } + + + + if ((int)index.x - 1 >= 0 && (int)index.y + 1 < cols) + { + map[(int)index.x, (int)index.y].neigbors.Add(map[(int)index.x - 1, (int)index.y + 1]); + } + if ((int)index.y + 1 < cols) + { + map[(int)index.x, (int)index.y].neigbors.Add(map[(int)index.x, (int)index.y + 1]); + } + if ((int)index.x + 1 < rows && (int)index.y + 1 < cols) + { + map[(int)index.x, (int)index.y].neigbors.Add(map[(int)index.x + 1, (int)index.y + 1]); + } } -} +} \ No newline at end of file