├── .gitignore
├── Assets
├── Models.meta
├── Models
│ ├── Materials.meta
│ ├── Materials
│ │ ├── m_TileOutline.mat
│ │ ├── m_TileOutline.mat.meta
│ │ ├── m_baseTile.mat
│ │ └── m_baseTile.mat.meta
│ ├── tile.fbx
│ └── tile.fbx.meta
├── Prefabs.meta
├── Prefabs
│ ├── P_NodeView.prefab
│ └── P_NodeView.prefab.meta
├── Scenes.meta
├── Scenes
│ ├── U_Playground.unity
│ └── U_Playground.unity.meta
├── Scripts.meta
└── Scripts
│ ├── Nodes&Graphs.meta
│ ├── Nodes&Graphs
│ ├── GraphController.cs
│ ├── GraphController.cs.meta
│ ├── Node.cs
│ ├── Node.cs.meta
│ ├── NodeView.cs
│ ├── NodeView.cs.meta
│ ├── Pathfinder.cs
│ ├── Pathfinder.cs.meta
│ ├── PriorityQueue.cs
│ └── PriorityQueue.cs.meta
│ ├── UI.meta
│ └── UI
│ ├── RaycastController.cs
│ ├── RaycastController.cs.meta
│ ├── UIController.cs
│ └── UIController.cs.meta
├── LICENSE
├── Packages
├── manifest.json
└── packages-lock.json
├── ProjectSettings
├── AudioManager.asset
├── ClusterInputManager.asset
├── DynamicsManager.asset
├── EditorBuildSettings.asset
├── EditorSettings.asset
├── GraphicsSettings.asset
├── InputManager.asset
├── NavMeshAreas.asset
├── NetworkManager.asset
├── PackageManagerSettings.asset
├── Physics2DSettings.asset
├── PresetManager.asset
├── ProjectSettings.asset
├── ProjectVersion.txt
├── QualitySettings.asset
├── TagManager.asset
├── TimeManager.asset
├── UnityConnectSettings.asset
├── VFXManager.asset
├── VersionControlSettings.asset
└── XRSettings.asset
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # This .gitignore file should be placed at the root of your Unity project directory
2 | #
3 | # Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore
4 | #
5 | /[Ll]ibrary/
6 | /[Tt]emp/
7 | /[Oo]bj/
8 | /[Bb]uild/
9 | /[Bb]uilds/
10 | /[Ll]ogs/
11 | /[Mm]emoryCaptures/
12 |
13 | # Never ignore Asset meta data
14 | !/[Aa]ssets/**/*.meta
15 |
16 | # Storm
17 | /[Aa]ssets/_[Ss]torm
18 |
19 | # Uncomment this line if you wish to ignore the asset store tools plugin
20 | # /[Aa]ssets/AssetStoreTools*
21 |
22 | # Autogenerated Jetbrains Rider plugin
23 | [Aa]ssets/Plugins/Editor/JetBrains*
24 |
25 | # Visual Studio cache directory
26 | .vs/
27 |
28 | # Gradle cache directory
29 | .gradle/
30 |
31 | # Autogenerated VS/MD/Consulo solution and project files
32 | ExportedObj/
33 | .consulo/
34 | *.csproj
35 | *.unityproj
36 | *.sln
37 | *.suo
38 | *.tmp
39 | *.user
40 | *.userprefs
41 | *.pidb
42 | *.booproj
43 | *.svd
44 | *.pdb
45 | *.mdb
46 | *.opendb
47 | *.VC.db
48 |
49 | # Unity3D generated meta files
50 | *.pidb.meta
51 | *.pdb.meta
52 | *.mdb.meta
53 |
54 | # Unity3D generated file on crash reports
55 | sysinfo.txt
56 |
57 | # Builds
58 | *.apk
59 | *.unitypackage
60 |
61 | # Crashlytics generated file
62 | crashlytics-build.properties
63 |
64 | .vscode/settings.json
65 | UserSettings/EditorUserSettings.asset
66 |
--------------------------------------------------------------------------------
/Assets/Models.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fa9f4ff22c229aa49b07ab54ea3d72c1
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Models/Materials.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 43a334cfa90e77242ab350f2f63b2478
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Models/Materials/m_TileOutline.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/Assets/Models/Materials/m_TileOutline.mat
--------------------------------------------------------------------------------
/Assets/Models/Materials/m_TileOutline.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a78b5ef7a3956254d88d0cbb546b62f0
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 0
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Models/Materials/m_baseTile.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/Assets/Models/Materials/m_baseTile.mat
--------------------------------------------------------------------------------
/Assets/Models/Materials/m_baseTile.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: bb9071f32cfb00440be5e58d03ec328b
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 0
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Models/tile.fbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/Assets/Models/tile.fbx
--------------------------------------------------------------------------------
/Assets/Models/tile.fbx.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 07207b35bda0b0a42b326c138182dff2
3 | ModelImporter:
4 | serializedVersion: 20101
5 | internalIDToNameTable: []
6 | externalObjects: {}
7 | materials:
8 | materialImportMode: 1
9 | materialName: 0
10 | materialSearch: 1
11 | materialLocation: 1
12 | animations:
13 | legacyGenerateAnimations: 4
14 | bakeSimulation: 0
15 | resampleCurves: 1
16 | optimizeGameObjects: 0
17 | motionNodeName:
18 | rigImportErrors:
19 | rigImportWarnings:
20 | animationImportErrors:
21 | animationImportWarnings:
22 | animationRetargetingWarnings:
23 | animationDoRetargetingWarnings: 0
24 | importAnimatedCustomProperties: 0
25 | importConstraints: 0
26 | animationCompression: 1
27 | animationRotationError: 0.5
28 | animationPositionError: 0.5
29 | animationScaleError: 0.5
30 | animationWrapMode: 0
31 | extraExposedTransformPaths: []
32 | extraUserProperties: []
33 | clipAnimations: []
34 | isReadable: 0
35 | meshes:
36 | lODScreenPercentages: []
37 | globalScale: 100
38 | meshCompression: 0
39 | addColliders: 0
40 | useSRGBMaterialColor: 1
41 | sortHierarchyByName: 1
42 | importVisibility: 0
43 | importBlendShapes: 0
44 | importCameras: 0
45 | importLights: 0
46 | fileIdsGeneration: 2
47 | swapUVChannels: 0
48 | generateSecondaryUV: 0
49 | useFileUnits: 1
50 | keepQuads: 0
51 | weldVertices: 1
52 | bakeAxisConversion: 0
53 | preserveHierarchy: 0
54 | skinWeightsMode: 0
55 | maxBonesPerVertex: 4
56 | minBoneWeight: 0.001
57 | meshOptimizationFlags: -1
58 | indexFormat: 0
59 | secondaryUVAngleDistortion: 8
60 | secondaryUVAreaDistortion: 15.000001
61 | secondaryUVHardAngle: 88
62 | secondaryUVMarginMethod: 1
63 | secondaryUVMinLightmapResolution: 40
64 | secondaryUVMinObjectScale: 1
65 | secondaryUVPackMargin: 4
66 | useFileScale: 1
67 | tangentSpace:
68 | normalSmoothAngle: 60
69 | normalImportMode: 0
70 | tangentImportMode: 3
71 | normalCalculationMode: 4
72 | legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
73 | blendShapeNormalImportMode: 1
74 | normalSmoothingSource: 0
75 | referencedClips: []
76 | importAnimation: 1
77 | humanDescription:
78 | serializedVersion: 3
79 | human: []
80 | skeleton: []
81 | armTwist: 0.5
82 | foreArmTwist: 0.5
83 | upperLegTwist: 0.5
84 | legTwist: 0.5
85 | armStretch: 0.05
86 | legStretch: 0.05
87 | feetSpacing: 0
88 | globalScale: 1
89 | rootMotionBoneName:
90 | hasTranslationDoF: 0
91 | hasExtraRoot: 0
92 | skeletonHasParents: 1
93 | lastHumanDescriptionAvatarSource: {instanceID: 0}
94 | autoGenerateAvatarMappingIfUnspecified: 1
95 | animationType: 2
96 | humanoidOversampling: 1
97 | avatarSetup: 0
98 | additionalBone: 0
99 | userData:
100 | assetBundleName:
101 | assetBundleVariant:
102 |
--------------------------------------------------------------------------------
/Assets/Prefabs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b8a49e3f8c721ae41ae6a3c1a4a38987
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Prefabs/P_NodeView.prefab:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/Assets/Prefabs/P_NodeView.prefab
--------------------------------------------------------------------------------
/Assets/Prefabs/P_NodeView.prefab.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 62b57766d8885f34f8b8ae4441de8c14
3 | PrefabImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Scenes.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 21769a3b132b2344f8d3b103e818a826
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Scenes/U_Playground.unity:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/Assets/Scenes/U_Playground.unity
--------------------------------------------------------------------------------
/Assets/Scenes/U_Playground.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 19cecb06206eed24fbb0018ecb64b789
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Scripts.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5f3983c1b0297d947b2a10bdca7fb605
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Scripts/Nodes&Graphs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3e7b53ad21f2c924c85ee3372d587193
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Scripts/Nodes&Graphs/GraphController.cs:
--------------------------------------------------------------------------------
1 | ///-----------------------------------------------------------------
2 | /// Class: GraphController
3 | /// Description: Manages the data graph and collection of nodes
4 | /// Author: Lee
5 | /// GitHub: https://github.com/ivuecode
6 | ///-----------------------------------------------------------------
7 | using System.Collections.Generic;
8 | using UnityEngine;
9 |
10 | public class GraphController : MonoBehaviour
11 | {
12 | [Header("Component References")]
13 | public GameObject nodeViewPrefab; // Reference to the world-spaceobject
14 |
15 | [Header("Graph Settings")]
16 | public Color startNodeColor; // Color of the start node
17 | public Color endNodeColor; // Color of the end node
18 | public Color blockedNodeColor; // Color of the wall nodes
19 | public Color frontierColor; // Color of the frontier nodes
20 | public Color exploredColor; // Color of the previous explored nodes
21 | public Color pathColor; // Color of the completed path nodes
22 | public Color defaultColor;
23 |
24 | [HideInInspector] public NodeView[,] nodeViews; // 2D array of all the nodes (visual)
25 | [HideInInspector] public Node[,] nodes; // 2D array of all nodes (data)
26 | [HideInInspector] public int graphWidth; // Graph dimensions
27 | [HideInInspector] public int graphHeight; // Graph dimensions
28 |
29 | [Header("Private Variables")]
30 | private int[,] m_gridSize = new int[48, 24]; // Base grid size
31 | private Vector2[] m_allDirections = { new Vector2(0f, 1f), new Vector2(1f, 0f), new Vector2(-1f, 0f), new Vector2(0f, -1f), }; // directions for checking neighbors
32 |
33 | ///
34 | /// (short-hand function) Check (x,y) within the bounds of the Graph?
35 | ///
36 | private bool IsWithinBounds(int x, int y) => (x >= 0 && x < graphWidth && y >= 0 && y < graphHeight);
37 |
38 | ///
39 | /// (short-hand function) Returns a List of neighboring Nodes
40 | ///
41 | private List GetNeighbors(int x, int y) => GetNeighbors(x, y, nodes, m_allDirections);
42 |
43 |
44 |
45 | ///
46 | /// Initialize the Graph (data)
47 | ///
48 | public void Initialize()
49 | {
50 | // set the dimensions based on the array and initialize
51 | graphWidth = m_gridSize.GetLength(0);
52 | graphHeight = m_gridSize.GetLength(1);
53 | nodes = new Node[graphWidth, graphHeight];
54 |
55 | // at each (x,y) position in the array setup the node
56 | for (int y = 0; y < graphHeight; y++)
57 | {
58 | for (int x = 0; x < graphWidth; x++)
59 | {
60 | NodeType type = (NodeType)m_gridSize[x, y];
61 | Node newNode = new Node(x, y, type);
62 | nodes[x, y] = newNode;
63 | newNode.position = new Vector3(x, 0, y);
64 | }
65 | }
66 | UpdateAllNeighbours();
67 | CreateGraph();
68 | ResetGraph();
69 | }
70 |
71 | ///
72 | /// Create the graph grid (visual)
73 | ///
74 | private void CreateGraph()
75 | {
76 | // setup array of NodeViews
77 | nodeViews = new NodeView[graphWidth, graphHeight];
78 |
79 | foreach (Node n in nodes)
80 | {
81 | // create a NodeView for each corresponding Node
82 | GameObject instance = Instantiate(nodeViewPrefab, Vector3.zero, Quaternion.identity);
83 | NodeView nodeView = instance.GetComponent();
84 | nodeView.Init(n);
85 |
86 | // store each NodeView in the array
87 | nodeViews[n.xIndex, n.yIndex] = nodeView;
88 | }
89 | }
90 |
91 | ///
92 | /// setup the neighbor Nodes for each node in the array
93 | ///
94 | private void UpdateAllNeighbours()
95 | {
96 | for (int y = 0; y < graphHeight; y++)
97 | {
98 | for (int x = 0; x < graphWidth; x++)
99 | {
100 | if (nodes[x, y].nodeType != NodeType.Blocked)
101 | {
102 | nodes[x, y].neighbors = GetNeighbors(x, y);
103 | }
104 | }
105 | }
106 | }
107 |
108 | ///
109 | /// Returns a List of neighboring Nodes from (x,y) coordinate, array of Nodes and compass directions
110 | ///
111 | private List GetNeighbors(int x, int y, Node[,] nodeArray, Vector2[] directions)
112 | {
113 | List neighborNodes = new List();
114 |
115 | // in each direction vector...
116 | foreach (Vector2 dir in directions)
117 | {
118 | // find the (x,y) offset position
119 | int newX = x + (int)dir.x;
120 | int newY = y + (int)dir.y;
121 |
122 | // if the new position is within the graph and not blocked, add to List
123 | if (IsWithinBounds(newX, newY) && nodeArray[newX, newY] != null && nodeArray[newX, newY].nodeType != NodeType.Blocked)
124 | {
125 | neighborNodes.Add(nodeArray[newX, newY]);
126 | }
127 | }
128 | return neighborNodes;
129 | }
130 |
131 | ///
132 | /// Color a List of NodeViews, given a List of Nodes
133 | ///
134 | public void ColorNodes(List nodes, Color color)
135 | {
136 | foreach (Node n in nodes)
137 | {
138 | NodeView nodeView = nodeViews[n.xIndex, n.yIndex];
139 | nodeView.SetColorNode(color);
140 | }
141 | }
142 |
143 | ///
144 | /// Gets the approximate distance between nodes
145 | ///
146 | public float GetNodeDistance(Node source, Node target)
147 | {
148 | int dx = Mathf.Abs(source.xIndex - target.xIndex);
149 | int dy = Mathf.Abs(source.yIndex - target.yIndex);
150 |
151 | int min = Mathf.Min(dx, dy);
152 | int max = Mathf.Max(dx, dy);
153 |
154 | int straightSteps = max - min;
155 |
156 | return (1.4f * min + straightSteps);
157 | }
158 |
159 | ///
160 | /// Toggles the nodeType state (blocked / open)
161 | ///
162 | public void ToggleNodeState(int x, int y)
163 | {
164 | if (nodes[x, y].nodeType == NodeType.Open)
165 | {
166 | nodes[x, y].nodeType = NodeType.Blocked;
167 | nodeViews[x, y].SetColorNode(blockedNodeColor);
168 | }
169 | else
170 | {
171 | nodes[x, y].nodeType = NodeType.Open;
172 | nodeViews[x, y].SetColorNode(defaultColor);
173 | }
174 | UpdateAllNeighbours();
175 | }
176 |
177 | ///
178 | /// Reset the state of the graph
179 | ///
180 | public void ResetGraph()
181 | {
182 | // at each (x,y) position in the array setup the node
183 | for (int y = 0; y < graphHeight; y++)
184 | {
185 | for (int x = 0; x < graphWidth; x++)
186 | {
187 | nodeViews[x, y].SetColorNode(defaultColor);
188 | nodes[x, y].Reset();
189 | nodes[x, y].nodeType = NodeType.Open;
190 | }
191 | }
192 | UpdateAllNeighbours();
193 | }
194 |
195 | ///
196 | /// Keep the layout the same (used in the case where we want to changge algos)
197 | ///
198 | public void RerollGraph()
199 | {
200 | for (int y = 0; y < graphHeight; y++)
201 | {
202 | for (int x = 0; x < graphWidth; x++)
203 | {
204 | if (nodeViews[x, y].node.nodeType != NodeType.Blocked)
205 | {
206 | nodeViews[x, y].SetColorNode(defaultColor);
207 | nodeViews[x, y].node.Reset();
208 | }
209 | }
210 | }
211 | }
212 | }
--------------------------------------------------------------------------------
/Assets/Scripts/Nodes&Graphs/GraphController.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 02f0e608ecf063040b886186c223494b
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Scripts/Nodes&Graphs/Node.cs:
--------------------------------------------------------------------------------
1 | ///-----------------------------------------------------------------
2 | /// Class: Node
3 | /// Description: Data class for the Node which implements the IComparable interface
4 | /// Author: Lee
5 | /// GitHub: https://github.com/ivuecode
6 | ///-----------------------------------------------------------------
7 | using System;
8 | using UnityEngine;
9 | using System.Collections.Generic;
10 |
11 | public enum NodeType { Open, Blocked };
12 | public class Node : IComparable
13 | {
14 | public int xIndex = -1; // x and y index in the graph array
15 | public int yIndex = -1; // x and y index in the graph array
16 | public float priority; // Priority used to set place in queue
17 | public Vector3 position; // (x,y,z) position in 3d space
18 | public Node previous = null; // Referebce to preceding null in the current graph search
19 | public NodeType nodeType = NodeType.Open;
20 | public List neighbors = new List(); // List of neighbor Nodes
21 | public float distanceTraveled = Mathf.Infinity; // Total distance traveled from the start Node
22 |
23 |
24 |
25 | ///
26 | /// Node constructor
27 | ///
28 | public Node(int x, int y, NodeType type)
29 | {
30 | xIndex = x;
31 | yIndex = y;
32 | nodeType = type;
33 | }
34 |
35 | ///
36 | /// Required by IComparable, method to compare this node with another Node based on priority
37 | ///
38 | public int CompareTo(Node other)
39 | {
40 | if (priority < other.priority) return -1;
41 | else if (priority > other.priority) return 1;
42 | else return 0;
43 | }
44 |
45 | ///
46 | /// Reset the state of this node
47 | ///
48 | public void Reset()
49 | {
50 | previous = null;
51 | priority = 0;
52 | distanceTraveled = Mathf.Infinity;
53 | }
54 | }
--------------------------------------------------------------------------------
/Assets/Scripts/Nodes&Graphs/Node.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1ff2e70e7f754da4e8f2fbf69e76eb75
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Scripts/Nodes&Graphs/NodeView.cs:
--------------------------------------------------------------------------------
1 | ///-----------------------------------------------------------------
2 | /// Class: NodeView
3 | /// Description: Visual controller of the node
4 | /// Author: Lee
5 | /// GitHub: https://github.com/ivuecode
6 | ///-----------------------------------------------------------------
7 | using UnityEngine;
8 |
9 | public class NodeView : MonoBehaviour
10 | {
11 | [Header("Component Referneces")]
12 | public GameObject tile;
13 | public MeshRenderer materialRenderer;
14 | public Node node;
15 |
16 |
17 |
18 | ///
19 | /// Initilize the NodeView with the corresponding Node
20 | ///
21 | public void Init(Node _node)
22 | {
23 | // set the name, position and scale of this node
24 | gameObject.name = "Node (" + _node.xIndex + "," + _node.yIndex + ")";
25 | gameObject.transform.position = _node.position;
26 | tile.transform.localScale = new Vector3(1f - 0.1f, 1f, 1f - 0.1f);
27 | node = _node;
28 | }
29 |
30 | ///
31 | /// Set the color of this node (tile) geometry
32 | ///
33 | public void SetColorNode(Color color)
34 | {
35 | materialRenderer.material.color = color;
36 | }
37 | }
--------------------------------------------------------------------------------
/Assets/Scripts/Nodes&Graphs/NodeView.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 70cedc3c83c6416469bbfca58404f2ea
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Scripts/Nodes&Graphs/Pathfinder.cs:
--------------------------------------------------------------------------------
1 | ///-----------------------------------------------------------------
2 | /// Class: Pathfinder
3 | /// Description: Uses different algorithms to find a goal node
4 | /// Author: Lee
5 | /// GitHub: https://github.com/ivuecode
6 | ///-----------------------------------------------------------------
7 | using System.Collections;
8 | using System.Collections.Generic;
9 | using UnityEngine;
10 |
11 | public enum PathFindingAlgo { Dijkstra, AStar, BreadthFirstSearch, GreedyBestFirst, }; // the various pathfinding algorithms
12 | public class Pathfinder : MonoBehaviour
13 | {
14 | [Header("Component References")]
15 | public GraphController graphController; // Refernece to the graph controller
16 | public UIController uIController; // Reference to the ui controller
17 |
18 | [Header("Private Variables")]
19 | private Node m_startNode; // The start node
20 | private Node m_goalNode; // The goal node
21 | private PriorityQueue m_frontierNodes; // The "open set" of Nodes that are next to be explored
22 | private List m_exploredNodes; // The "closed set" of Nodes that have been explored
23 | private List m_pathNodes; // The List of Nodes that make up our final path from start to goal
24 |
25 | [Header("PathFinding Properties")]
26 | [HideInInspector] public PathFindingAlgo pathAlgo; // Active pathfinding mode/algorithm
27 | [HideInInspector] public float timeStep; // Speed of iterations
28 | [HideInInspector] public bool isComplete; // Is the search complete
29 | [HideInInspector] public int iterations; // Current number of iterations
30 | [HideInInspector] public float time; // Total time it took to complete
31 |
32 |
33 |
34 | ///
35 | /// Initialize the pathfinder
36 | ///
37 | public void Initialize(Node start, Node goal)
38 | {
39 | m_startNode = start;
40 | m_goalNode = goal;
41 |
42 | // our frontier begins with the start Node
43 | m_frontierNodes = new PriorityQueue();
44 | m_frontierNodes.Enqueue(start);
45 | m_exploredNodes = new List();
46 | m_pathNodes = new List();
47 |
48 | // reset all Nodes in the graph
49 | for (int x = 0; x < graphController.graphWidth; x++)
50 | {
51 | for (int y = 0; y < graphController.graphHeight; y++)
52 | {
53 | graphController.nodes[x, y].Reset();
54 | }
55 | }
56 |
57 | // setup starting values
58 | isComplete = false;
59 | iterations = 0;
60 | m_startNode.distanceTraveled = 0;
61 | StartCoroutine(SearchRoutine());
62 | }
63 |
64 | ///
65 | /// Updates the nodes on the graph to represent the current status of the algorithm
66 | ///
67 | private void UpdateGraphUI(Node start, Node goal)
68 | {
69 | // color frontier, explored and path Nodes
70 | if (m_frontierNodes != null) graphController.ColorNodes(m_frontierNodes.ToList(), graphController.frontierColor);
71 | if (m_exploredNodes != null) graphController.ColorNodes(m_exploredNodes, graphController.exploredColor);
72 | if (m_pathNodes != null && m_pathNodes.Count > 0) graphController.ColorNodes(m_pathNodes, graphController.pathColor);
73 |
74 | // color start NodeView and goal NodeView directly
75 | NodeView startNodeView = graphController.nodeViews[start.xIndex, start.yIndex];
76 | startNodeView.SetColorNode(graphController.startNodeColor);
77 | NodeView goalNodeView = graphController.nodeViews[goal.xIndex, goal.yIndex];
78 | goalNodeView.SetColorNode(graphController.endNodeColor);
79 | }
80 |
81 | ///
82 | /// Primary graph search routine
83 | ///
84 | private IEnumerator SearchRoutine()
85 | {
86 | // wait one frame
87 | float timeStart = Time.realtimeSinceStartup;
88 | yield return null;
89 |
90 | while (!isComplete && m_frontierNodes != null)
91 | {
92 | if (m_frontierNodes.Count > 0)
93 | {
94 | // get the next Node from the priority queue
95 | Node currentNode = m_frontierNodes.Dequeue();
96 | iterations++;
97 | time = (Time.realtimeSinceStartup - timeStart);
98 | uIController.totalIterations.text = "Total iterations: " + iterations;
99 | uIController.completeTime.text = "Elapsed time: " + time.ToString("F2") + " seconds";
100 |
101 | // mark this Node as explored
102 | if (!m_exploredNodes.Contains(currentNode)) m_exploredNodes.Add(currentNode);
103 |
104 | // expand the frontier based on our search mode
105 | if (pathAlgo == PathFindingAlgo.BreadthFirstSearch) ExpandFrontierBreadthFirst(currentNode);
106 | else if (pathAlgo == PathFindingAlgo.Dijkstra) ExpandFrontierDijkstra(currentNode);
107 | else if (pathAlgo == PathFindingAlgo.GreedyBestFirst) ExpandFrontierGreedyBestFirst(currentNode);
108 | else ExpandFrontierAStar(currentNode);
109 |
110 | // if the goal node is in the frontier
111 | if (m_frontierNodes.Contains(m_goalNode))
112 | {
113 | m_pathNodes = GetPathNodes(m_goalNode);
114 | isComplete = true;
115 | uIController.OnPathFinished();
116 | }
117 |
118 | UpdateGraphUI(m_startNode, m_goalNode);
119 | yield return new WaitForSeconds(timeStep);
120 | }
121 | else
122 | {
123 | isComplete = true;
124 | uIController.OnPathFinished();
125 | }
126 | }
127 | time = (Time.realtimeSinceStartup - timeStart);
128 | uIController.OnPathFinished();
129 | }
130 |
131 | ///
132 | /// Expand the frontier nodes using Breadth First Search
133 | ///
134 | private void ExpandFrontierBreadthFirst(Node node)
135 | {
136 | if (node != null)
137 | {
138 | for (int i = 0; i < node.neighbors.Count; i++)
139 | {
140 | // if the current neighbor has not been explored and is not already part of the frontier
141 | if (!m_exploredNodes.Contains(node.neighbors[i]) && !m_frontierNodes.Contains(node.neighbors[i]))
142 | {
143 | float distanceToNeighbor = graphController.GetNodeDistance(node, node.neighbors[i]);
144 | float newDistanceTraveled = distanceToNeighbor + node.distanceTraveled + (int)node.nodeType;
145 |
146 | // create breadcrumb trail to neighbor node and set cumulative distance traveled
147 | node.neighbors[i].distanceTraveled = newDistanceTraveled;
148 | node.neighbors[i].previous = node;
149 |
150 | // add neighbor to explored Nodes, treat queue as if it were a first in-first out queue
151 | node.neighbors[i].priority = m_exploredNodes.Count;
152 | m_frontierNodes.Enqueue(node.neighbors[i]);
153 | }
154 | }
155 | }
156 | }
157 |
158 | ///
159 | /// Expand the frontier nodes using Dijkstra's algorithm
160 | ///
161 | private void ExpandFrontierDijkstra(Node node)
162 | {
163 | if (node != null)
164 | {
165 | for (int i = 0; i < node.neighbors.Count; i++)
166 | {
167 | if (!m_exploredNodes.Contains(node.neighbors[i]))
168 | {
169 | float distanceToNeighbor = graphController.GetNodeDistance(node, node.neighbors[i]);
170 | float newDistanceTraveled = distanceToNeighbor + node.distanceTraveled + (int)node.nodeType;
171 |
172 | // if a shorter path exists to the neighbor via this node, re-route
173 | if (float.IsPositiveInfinity(node.neighbors[i].distanceTraveled) || newDistanceTraveled < node.neighbors[i].distanceTraveled)
174 | {
175 | node.neighbors[i].previous = node;
176 | node.neighbors[i].distanceTraveled = newDistanceTraveled;
177 | }
178 |
179 | // if the current neighbor is not already part of the frontier
180 | if (!m_frontierNodes.Contains(node.neighbors[i]))
181 | {
182 | // set the priority based on distance traveled from start Node and add to frontier
183 | node.neighbors[i].priority = node.neighbors[i].distanceTraveled;
184 | m_frontierNodes.Enqueue(node.neighbors[i]);
185 | }
186 | }
187 | }
188 | }
189 | }
190 |
191 | ///
192 | /// Expand the frontier nodes using Greedy Best-First search
193 | ///
194 | private void ExpandFrontierGreedyBestFirst(Node node)
195 | {
196 | if (node != null)
197 | {
198 | for (int i = 0; i < node.neighbors.Count; i++)
199 | {
200 | if (!m_exploredNodes.Contains(node.neighbors[i]) && !m_frontierNodes.Contains(node.neighbors[i]))
201 | {
202 | float distanceToNeighbor = graphController.GetNodeDistance(node, node.neighbors[i]);
203 | float newDistanceTraveled = distanceToNeighbor + node.distanceTraveled + (int)node.nodeType;
204 |
205 | // create breadcrumb trail to neighbor node and set cumulative distance traveled
206 | node.neighbors[i].distanceTraveled = newDistanceTraveled;
207 | node.neighbors[i].previous = node;
208 |
209 | // set the priority based on estimated distance to goal Node
210 | node.neighbors[i].priority = graphController.GetNodeDistance(node.neighbors[i], m_goalNode);
211 | m_frontierNodes.Enqueue(node.neighbors[i]);
212 | }
213 | }
214 | }
215 | }
216 |
217 | ///
218 | /// Expand the frontier nodes using AStar search
219 | ///
220 | private void ExpandFrontierAStar(Node node)
221 | {
222 | if (node != null)
223 | {
224 | for (int i = 0; i < node.neighbors.Count; i++)
225 | {
226 | if (!m_exploredNodes.Contains(node.neighbors[i]))
227 | {
228 | float distanceToNeighbor = graphController.GetNodeDistance(node, node.neighbors[i]);
229 | float newDistanceTraveled = distanceToNeighbor + node.distanceTraveled + (int)node.nodeType;
230 |
231 | // if a shorter path exists to the neighbor via this node, re-route
232 | if (float.IsPositiveInfinity(node.neighbors[i].distanceTraveled) || newDistanceTraveled < node.neighbors[i].distanceTraveled)
233 | {
234 | node.neighbors[i].previous = node;
235 | node.neighbors[i].distanceTraveled = newDistanceTraveled;
236 | }
237 |
238 | // if the neighbor is not part of the frontier, add this to the priority queue
239 | if (!m_frontierNodes.Contains(node.neighbors[i]) && graphController != null)
240 | {
241 | // base priority, F score, on G score (distance from start) + H score (estimated distance to goal)
242 | float distanceToGoal = graphController.GetNodeDistance(node.neighbors[i], m_goalNode);
243 | node.neighbors[i].priority = node.neighbors[i].distanceTraveled + distanceToGoal;
244 |
245 | // add to priority queue using the F score
246 | m_frontierNodes.Enqueue(node.neighbors[i]);
247 | }
248 | }
249 | }
250 | }
251 | }
252 |
253 | ///
254 | /// Generate a list of path Nodes working backward from an end Node
255 | ///
256 | private List GetPathNodes(Node endNode)
257 | {
258 | List path = new List();
259 | if (endNode == null) return path;
260 |
261 | // follow the breadcrumb trail backward until we hit a node that has no previous node (usually the start Node)
262 | path.Add(endNode);
263 | Node currentNode = endNode.previous;
264 |
265 | while (currentNode != null)
266 | {
267 | // insert the previous node at the first position in the path
268 | path.Insert(0, currentNode);
269 | currentNode = currentNode.previous;
270 | }
271 | return path;
272 | }
273 | }
--------------------------------------------------------------------------------
/Assets/Scripts/Nodes&Graphs/Pathfinder.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b4a4d2476e0ec3b4294e9297c5cab785
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Scripts/Nodes&Graphs/PriorityQueue.cs:
--------------------------------------------------------------------------------
1 | ///-----------------------------------------------------------------
2 | /// Class: PriorityQueue
3 | /// Description: Priority queue implemented using generic list with a binary heap
4 | /// Author: Lee
5 | /// GitHub: https://github.com/ivuecode
6 | /// Notes: Implementation: https://visualstudiomagazine.com/articles/2012/11/01/priority-queues-with-c.aspx
7 | ///-----------------------------------------------------------------
8 | using System;
9 | using System.Collections.Generic;
10 |
11 | public class PriorityQueue where T : IComparable
12 | {
13 | // List of items in our queue
14 | private List m_data;
15 |
16 | ///
17 | /// Number of items currently in queue
18 | ///
19 | public int Count => m_data.Count;
20 |
21 | ///
22 | /// Check if the item contained in the data List?
23 | ///
24 | public bool Contains(T item) => m_data.Contains(item);
25 |
26 | ///
27 | /// Return the data as a generic List
28 | ///
29 | public List ToList() => m_data;
30 |
31 | ///
32 | /// Constructor
33 | ///
34 | public PriorityQueue() => m_data = new List();
35 |
36 | ///
37 | /// Look at the first item without dequeuing
38 | ///
39 | public T Peek()
40 | {
41 | T frontItem = m_data[0];
42 | return frontItem;
43 | }
44 |
45 | ///
46 | /// Add an item to the queue and sort using a min binary heap
47 | ///
48 | public void Enqueue(T item)
49 | {
50 | m_data.Add(item);
51 | int childindex = m_data.Count - 1;
52 |
53 | // sort using a min binary heap
54 | while (childindex > 0)
55 | {
56 | // find the parent position in the heap
57 | int parentindex = (childindex - 1) / 2;
58 |
59 | // if parent and child are already sorted, stop sorting
60 | if (m_data[childindex].CompareTo(m_data[parentindex]) >= 0) break;
61 |
62 | T tmp = m_data[childindex];
63 | m_data[childindex] = m_data[parentindex];
64 | m_data[parentindex] = tmp;
65 |
66 | // move up one level in the heap and repeat until sorted
67 | childindex = parentindex;
68 | }
69 | }
70 |
71 | ///
72 | /// Remove an item from queue and keep it sorted using a min binary heap
73 | ///
74 | public T Dequeue()
75 | {
76 | int lastindex = m_data.Count - 1;
77 | T frontItem = m_data[0];
78 | m_data[0] = m_data[lastindex];
79 | m_data.RemoveAt(lastindex);
80 | lastindex--;
81 | int parentindex = 0;
82 |
83 | // sort using binary heap
84 | while (true)
85 | {
86 | // left child
87 | int childindex = parentindex * 2 + 1;
88 |
89 | // if there is no left child, stop sorting
90 | if (childindex > lastindex) break;
91 |
92 | // right child
93 | int rightchild = childindex + 1;
94 |
95 | // if the value of the right child is less than the left child, switch to the right branch of the heap
96 | if (rightchild <= lastindex && m_data[rightchild].CompareTo(m_data[childindex]) < 0) childindex = rightchild;
97 |
98 | // if the parent and child are already sorted, then stop sorting
99 | if (m_data[parentindex].CompareTo(m_data[childindex]) <= 0) break;
100 |
101 | // if not, then swap the parent and child
102 | T tmp = m_data[parentindex];
103 | m_data[parentindex] = m_data[childindex];
104 | m_data[childindex] = tmp;
105 |
106 | // move down the heap onto the child's level and repeat until sorted
107 | parentindex = childindex;
108 | }
109 | return frontItem;
110 | }
111 | }
--------------------------------------------------------------------------------
/Assets/Scripts/Nodes&Graphs/PriorityQueue.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 018c6cf83feef3c419f4303365ed4bb2
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Scripts/UI.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f29b03621c5e50e43b9776e94ce8fd90
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Scripts/UI/RaycastController.cs:
--------------------------------------------------------------------------------
1 | ///-----------------------------------------------------------------
2 | /// Class: RaycastController
3 | /// Description: Raycast from the camera to mouse position to interact
4 | /// Author: Lee
5 | /// GitHub: https://github.com/ivuecode
6 | ///-----------------------------------------------------------------
7 | using UnityEngine;
8 |
9 | public class RaycastController : MonoBehaviour
10 | {
11 | [Header("Component References")]
12 | public Camera sceneCamera; // Reference to the main camera
13 | public UIController uIController; // Refernece to the UIController
14 |
15 | [Header("Private Variables")]
16 | private NodeView m_focusedNode; // Node we just click
17 | private NodeView m_currentNode; // Node under the mouse
18 |
19 |
20 |
21 | ///
22 | /// Update is called each frame
23 | ///
24 | void Update()
25 | {
26 | RaycastHit hit;
27 | Ray ray = sceneCamera.ScreenPointToRay(Input.mousePosition);
28 |
29 | if (Physics.Raycast(ray, out hit))
30 | {
31 | m_currentNode = hit.transform.GetComponent();
32 |
33 | if (Input.GetMouseButton(0))
34 | {
35 | if (m_focusedNode == null)
36 | {
37 | m_focusedNode = m_currentNode;
38 | uIController.OnInteract(m_focusedNode.node.xIndex, m_focusedNode.node.yIndex);
39 | }
40 |
41 | if (m_focusedNode != m_currentNode)
42 | {
43 | uIController.OnInteract(m_currentNode.node.xIndex, m_currentNode.node.yIndex);
44 | m_focusedNode = m_currentNode;
45 | }
46 | }
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/Assets/Scripts/UI/RaycastController.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2fbe4e6b4f0420a45b8d9b39c7cc6c67
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Scripts/UI/UIController.cs:
--------------------------------------------------------------------------------
1 | ///-----------------------------------------------------------------
2 | /// Class: UIController
3 | /// Description: Handles creating and starting the graph and pathfinder
4 | /// Author: Lee
5 | /// GitHub: https://github.com/ivuecode
6 | ///-----------------------------------------------------------------
7 | using UnityEngine;
8 | using UnityEngine.UI;
9 |
10 | public class UIController : MonoBehaviour
11 | {
12 | [Header("Component References")]
13 | public GraphController graph; // Reference to the graph component
14 | public Pathfinder pathfinder; // Referrence to the path finder
15 | public Slider timeStepSlider; // Reference to the UI slider for setting time steps
16 | public Text timeStepValue; // Reference to the time step value
17 | public Text completeTime; // Refernece to the text for completion time
18 | public Text totalIterations; // Reference to the total iterations
19 | public Dropdown algorithmDropdown; // Reference to the dropdown
20 | public Button resetButton; // Refernece to the resetButton
21 | public Button startButton; // Reference to the startButton
22 |
23 | [Header("Private Variables")]
24 | private int m_startNodeX; // X coordinate of start Node
25 | private int m_startNodeY; // Y coordinate of start Node
26 | private int m_endNodeX; // X coordinate of end Node
27 | private int m_endNodeY; // Y coordinate of end Node
28 | private float m_timeStep; // Delay between iterations
29 | private int m_UIState; // Internal tracking of the ui build state
30 | private bool hasStarted; // Has this simulation started
31 |
32 |
33 |
34 | ///
35 | /// Initialize the graph
36 | ///
37 | private void Start()
38 | {
39 | graph.Initialize();
40 | OnSetTimestep();
41 | }
42 |
43 | ///
44 | /// Initialize the Pathfinder and begin the search
45 | ///
46 | public void OnStartSimulation()
47 | {
48 | graph.RerollGraph();
49 | Node startNode = graph.nodes[m_startNodeX, m_startNodeY];
50 | Node goalNode = graph.nodes[m_endNodeX, m_endNodeY];
51 |
52 | pathfinder.Initialize(startNode, goalNode);
53 | hasStarted = true;
54 | resetButton.interactable = false;
55 | startButton.interactable = false;
56 | }
57 |
58 | ///
59 | /// Sets the timesetp value from the UISlider
60 | ///
61 | public void OnSetTimestep()
62 | {
63 | m_timeStep = timeStepSlider.value / 10;
64 | timeStepValue.text = "Iterations per second: " + m_timeStep.ToString("F2");
65 | pathfinder.timeStep = m_timeStep;
66 | }
67 |
68 | ///
69 | /// Sets the pathfinder algorithm
70 | ///
71 | public void OnSetAlgorithm()
72 | {
73 | string algo = algorithmDropdown.options[algorithmDropdown.value].text;
74 | switch (algo)
75 | {
76 | case "Dijkstra":
77 | {
78 | pathfinder.pathAlgo = PathFindingAlgo.Dijkstra;
79 | break;
80 | }
81 | case "AStar":
82 | {
83 | pathfinder.pathAlgo = PathFindingAlgo.AStar;
84 | break;
85 | }
86 | case "Breadth First":
87 | {
88 | pathfinder.pathAlgo = PathFindingAlgo.BreadthFirstSearch;
89 | break;
90 | }
91 | case "Greedy Best First":
92 | {
93 | pathfinder.pathAlgo = PathFindingAlgo.GreedyBestFirst;
94 | break;
95 | }
96 | }
97 | }
98 |
99 | ///
100 | /// Resets the board
101 | ///
102 | public void OnResetBoard()
103 | {
104 | startButton.interactable = false;
105 | pathfinder.isComplete = false;
106 | hasStarted = false;
107 | m_UIState = 0;
108 | graph.ResetGraph();
109 | }
110 |
111 | ///
112 | /// Called from the pathfinder when a path is complete
113 | ///
114 | public void OnPathFinished()
115 | {
116 | resetButton.interactable = true;
117 | startButton.interactable = true;
118 | }
119 |
120 | ///
121 | /// Called when we interact with a node based on the state of the UI
122 | ///
123 | public void OnInteract(int xIndex, int yIndex)
124 | {
125 | if (hasStarted) return;
126 | switch (m_UIState)
127 | {
128 | case 0:
129 | {
130 | graph.nodeViews[xIndex, yIndex].SetColorNode(graph.startNodeColor);
131 | m_startNodeX = xIndex;
132 | m_startNodeY = yIndex;
133 | break;
134 | }
135 | case 1:
136 | {
137 | graph.nodeViews[xIndex, yIndex].SetColorNode(graph.endNodeColor);
138 | m_endNodeX = xIndex;
139 | m_endNodeY = yIndex;
140 | startButton.interactable = true;
141 | break;
142 | }
143 | case 2:
144 | {
145 | graph.ToggleNodeState(xIndex, yIndex);
146 | break;
147 | }
148 | }
149 | m_UIState++;
150 | if (m_UIState >= 2) m_UIState = 2;
151 | }
152 | }
--------------------------------------------------------------------------------
/Assets/Scripts/UI/UIController.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3244c30971775624a956a2b4b20f592d
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Vue Code
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Packages/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "com.unity.collab-proxy": "1.3.9",
4 | "com.unity.ide.rider": "1.2.1",
5 | "com.unity.ide.visualstudio": "2.0.5",
6 | "com.unity.ide.vscode": "1.2.3",
7 | "com.unity.test-framework": "1.1.19",
8 | "com.unity.textmeshpro": "3.0.1",
9 | "com.unity.timeline": "1.3.6",
10 | "com.unity.ugui": "1.0.0",
11 | "com.unity.modules.ai": "1.0.0",
12 | "com.unity.modules.androidjni": "1.0.0",
13 | "com.unity.modules.animation": "1.0.0",
14 | "com.unity.modules.assetbundle": "1.0.0",
15 | "com.unity.modules.audio": "1.0.0",
16 | "com.unity.modules.cloth": "1.0.0",
17 | "com.unity.modules.director": "1.0.0",
18 | "com.unity.modules.imageconversion": "1.0.0",
19 | "com.unity.modules.imgui": "1.0.0",
20 | "com.unity.modules.jsonserialize": "1.0.0",
21 | "com.unity.modules.particlesystem": "1.0.0",
22 | "com.unity.modules.physics": "1.0.0",
23 | "com.unity.modules.physics2d": "1.0.0",
24 | "com.unity.modules.screencapture": "1.0.0",
25 | "com.unity.modules.terrain": "1.0.0",
26 | "com.unity.modules.terrainphysics": "1.0.0",
27 | "com.unity.modules.tilemap": "1.0.0",
28 | "com.unity.modules.ui": "1.0.0",
29 | "com.unity.modules.uielements": "1.0.0",
30 | "com.unity.modules.umbra": "1.0.0",
31 | "com.unity.modules.unityanalytics": "1.0.0",
32 | "com.unity.modules.unitywebrequest": "1.0.0",
33 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0",
34 | "com.unity.modules.unitywebrequestaudio": "1.0.0",
35 | "com.unity.modules.unitywebrequesttexture": "1.0.0",
36 | "com.unity.modules.unitywebrequestwww": "1.0.0",
37 | "com.unity.modules.vehicles": "1.0.0",
38 | "com.unity.modules.video": "1.0.0",
39 | "com.unity.modules.vr": "1.0.0",
40 | "com.unity.modules.wind": "1.0.0",
41 | "com.unity.modules.xr": "1.0.0"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Packages/packages-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "com.unity.collab-proxy": {
4 | "version": "1.3.9",
5 | "depth": 0,
6 | "source": "registry",
7 | "dependencies": {},
8 | "url": "https://packages.unity.com"
9 | },
10 | "com.unity.ext.nunit": {
11 | "version": "1.0.5",
12 | "depth": 1,
13 | "source": "registry",
14 | "dependencies": {},
15 | "url": "https://packages.unity.com"
16 | },
17 | "com.unity.ide.rider": {
18 | "version": "1.2.1",
19 | "depth": 0,
20 | "source": "registry",
21 | "dependencies": {
22 | "com.unity.test-framework": "1.1.1"
23 | },
24 | "url": "https://packages.unity.com"
25 | },
26 | "com.unity.ide.visualstudio": {
27 | "version": "2.0.5",
28 | "depth": 0,
29 | "source": "registry",
30 | "dependencies": {},
31 | "url": "https://packages.unity.com"
32 | },
33 | "com.unity.ide.vscode": {
34 | "version": "1.2.3",
35 | "depth": 0,
36 | "source": "registry",
37 | "dependencies": {},
38 | "url": "https://packages.unity.com"
39 | },
40 | "com.unity.test-framework": {
41 | "version": "1.1.19",
42 | "depth": 0,
43 | "source": "registry",
44 | "dependencies": {
45 | "com.unity.ext.nunit": "1.0.5",
46 | "com.unity.modules.imgui": "1.0.0",
47 | "com.unity.modules.jsonserialize": "1.0.0"
48 | },
49 | "url": "https://packages.unity.com"
50 | },
51 | "com.unity.textmeshpro": {
52 | "version": "3.0.1",
53 | "depth": 0,
54 | "source": "registry",
55 | "dependencies": {
56 | "com.unity.ugui": "1.0.0"
57 | },
58 | "url": "https://packages.unity.com"
59 | },
60 | "com.unity.timeline": {
61 | "version": "1.3.6",
62 | "depth": 0,
63 | "source": "registry",
64 | "dependencies": {},
65 | "url": "https://packages.unity.com"
66 | },
67 | "com.unity.ugui": {
68 | "version": "1.0.0",
69 | "depth": 0,
70 | "source": "builtin",
71 | "dependencies": {
72 | "com.unity.modules.ui": "1.0.0",
73 | "com.unity.modules.imgui": "1.0.0"
74 | }
75 | },
76 | "com.unity.modules.ai": {
77 | "version": "1.0.0",
78 | "depth": 0,
79 | "source": "builtin",
80 | "dependencies": {}
81 | },
82 | "com.unity.modules.androidjni": {
83 | "version": "1.0.0",
84 | "depth": 0,
85 | "source": "builtin",
86 | "dependencies": {}
87 | },
88 | "com.unity.modules.animation": {
89 | "version": "1.0.0",
90 | "depth": 0,
91 | "source": "builtin",
92 | "dependencies": {}
93 | },
94 | "com.unity.modules.assetbundle": {
95 | "version": "1.0.0",
96 | "depth": 0,
97 | "source": "builtin",
98 | "dependencies": {}
99 | },
100 | "com.unity.modules.audio": {
101 | "version": "1.0.0",
102 | "depth": 0,
103 | "source": "builtin",
104 | "dependencies": {}
105 | },
106 | "com.unity.modules.cloth": {
107 | "version": "1.0.0",
108 | "depth": 0,
109 | "source": "builtin",
110 | "dependencies": {
111 | "com.unity.modules.physics": "1.0.0"
112 | }
113 | },
114 | "com.unity.modules.director": {
115 | "version": "1.0.0",
116 | "depth": 0,
117 | "source": "builtin",
118 | "dependencies": {
119 | "com.unity.modules.audio": "1.0.0",
120 | "com.unity.modules.animation": "1.0.0"
121 | }
122 | },
123 | "com.unity.modules.imageconversion": {
124 | "version": "1.0.0",
125 | "depth": 0,
126 | "source": "builtin",
127 | "dependencies": {}
128 | },
129 | "com.unity.modules.imgui": {
130 | "version": "1.0.0",
131 | "depth": 0,
132 | "source": "builtin",
133 | "dependencies": {}
134 | },
135 | "com.unity.modules.jsonserialize": {
136 | "version": "1.0.0",
137 | "depth": 0,
138 | "source": "builtin",
139 | "dependencies": {}
140 | },
141 | "com.unity.modules.particlesystem": {
142 | "version": "1.0.0",
143 | "depth": 0,
144 | "source": "builtin",
145 | "dependencies": {}
146 | },
147 | "com.unity.modules.physics": {
148 | "version": "1.0.0",
149 | "depth": 0,
150 | "source": "builtin",
151 | "dependencies": {}
152 | },
153 | "com.unity.modules.physics2d": {
154 | "version": "1.0.0",
155 | "depth": 0,
156 | "source": "builtin",
157 | "dependencies": {}
158 | },
159 | "com.unity.modules.screencapture": {
160 | "version": "1.0.0",
161 | "depth": 0,
162 | "source": "builtin",
163 | "dependencies": {
164 | "com.unity.modules.imageconversion": "1.0.0"
165 | }
166 | },
167 | "com.unity.modules.subsystems": {
168 | "version": "1.0.0",
169 | "depth": 1,
170 | "source": "builtin",
171 | "dependencies": {
172 | "com.unity.modules.jsonserialize": "1.0.0"
173 | }
174 | },
175 | "com.unity.modules.terrain": {
176 | "version": "1.0.0",
177 | "depth": 0,
178 | "source": "builtin",
179 | "dependencies": {}
180 | },
181 | "com.unity.modules.terrainphysics": {
182 | "version": "1.0.0",
183 | "depth": 0,
184 | "source": "builtin",
185 | "dependencies": {
186 | "com.unity.modules.physics": "1.0.0",
187 | "com.unity.modules.terrain": "1.0.0"
188 | }
189 | },
190 | "com.unity.modules.tilemap": {
191 | "version": "1.0.0",
192 | "depth": 0,
193 | "source": "builtin",
194 | "dependencies": {
195 | "com.unity.modules.physics2d": "1.0.0"
196 | }
197 | },
198 | "com.unity.modules.ui": {
199 | "version": "1.0.0",
200 | "depth": 0,
201 | "source": "builtin",
202 | "dependencies": {}
203 | },
204 | "com.unity.modules.uielements": {
205 | "version": "1.0.0",
206 | "depth": 0,
207 | "source": "builtin",
208 | "dependencies": {
209 | "com.unity.modules.ui": "1.0.0",
210 | "com.unity.modules.imgui": "1.0.0",
211 | "com.unity.modules.jsonserialize": "1.0.0",
212 | "com.unity.modules.uielementsnative": "1.0.0"
213 | }
214 | },
215 | "com.unity.modules.uielementsnative": {
216 | "version": "1.0.0",
217 | "depth": 1,
218 | "source": "builtin",
219 | "dependencies": {
220 | "com.unity.modules.ui": "1.0.0",
221 | "com.unity.modules.imgui": "1.0.0",
222 | "com.unity.modules.jsonserialize": "1.0.0"
223 | }
224 | },
225 | "com.unity.modules.umbra": {
226 | "version": "1.0.0",
227 | "depth": 0,
228 | "source": "builtin",
229 | "dependencies": {}
230 | },
231 | "com.unity.modules.unityanalytics": {
232 | "version": "1.0.0",
233 | "depth": 0,
234 | "source": "builtin",
235 | "dependencies": {
236 | "com.unity.modules.unitywebrequest": "1.0.0",
237 | "com.unity.modules.jsonserialize": "1.0.0"
238 | }
239 | },
240 | "com.unity.modules.unitywebrequest": {
241 | "version": "1.0.0",
242 | "depth": 0,
243 | "source": "builtin",
244 | "dependencies": {}
245 | },
246 | "com.unity.modules.unitywebrequestassetbundle": {
247 | "version": "1.0.0",
248 | "depth": 0,
249 | "source": "builtin",
250 | "dependencies": {
251 | "com.unity.modules.assetbundle": "1.0.0",
252 | "com.unity.modules.unitywebrequest": "1.0.0"
253 | }
254 | },
255 | "com.unity.modules.unitywebrequestaudio": {
256 | "version": "1.0.0",
257 | "depth": 0,
258 | "source": "builtin",
259 | "dependencies": {
260 | "com.unity.modules.unitywebrequest": "1.0.0",
261 | "com.unity.modules.audio": "1.0.0"
262 | }
263 | },
264 | "com.unity.modules.unitywebrequesttexture": {
265 | "version": "1.0.0",
266 | "depth": 0,
267 | "source": "builtin",
268 | "dependencies": {
269 | "com.unity.modules.unitywebrequest": "1.0.0",
270 | "com.unity.modules.imageconversion": "1.0.0"
271 | }
272 | },
273 | "com.unity.modules.unitywebrequestwww": {
274 | "version": "1.0.0",
275 | "depth": 0,
276 | "source": "builtin",
277 | "dependencies": {
278 | "com.unity.modules.unitywebrequest": "1.0.0",
279 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0",
280 | "com.unity.modules.unitywebrequestaudio": "1.0.0",
281 | "com.unity.modules.audio": "1.0.0",
282 | "com.unity.modules.assetbundle": "1.0.0",
283 | "com.unity.modules.imageconversion": "1.0.0"
284 | }
285 | },
286 | "com.unity.modules.vehicles": {
287 | "version": "1.0.0",
288 | "depth": 0,
289 | "source": "builtin",
290 | "dependencies": {
291 | "com.unity.modules.physics": "1.0.0"
292 | }
293 | },
294 | "com.unity.modules.video": {
295 | "version": "1.0.0",
296 | "depth": 0,
297 | "source": "builtin",
298 | "dependencies": {
299 | "com.unity.modules.audio": "1.0.0",
300 | "com.unity.modules.ui": "1.0.0",
301 | "com.unity.modules.unitywebrequest": "1.0.0"
302 | }
303 | },
304 | "com.unity.modules.vr": {
305 | "version": "1.0.0",
306 | "depth": 0,
307 | "source": "builtin",
308 | "dependencies": {
309 | "com.unity.modules.jsonserialize": "1.0.0",
310 | "com.unity.modules.physics": "1.0.0",
311 | "com.unity.modules.xr": "1.0.0"
312 | }
313 | },
314 | "com.unity.modules.wind": {
315 | "version": "1.0.0",
316 | "depth": 0,
317 | "source": "builtin",
318 | "dependencies": {}
319 | },
320 | "com.unity.modules.xr": {
321 | "version": "1.0.0",
322 | "depth": 0,
323 | "source": "builtin",
324 | "dependencies": {
325 | "com.unity.modules.physics": "1.0.0",
326 | "com.unity.modules.jsonserialize": "1.0.0",
327 | "com.unity.modules.subsystems": "1.0.0"
328 | }
329 | }
330 | }
331 | }
332 |
--------------------------------------------------------------------------------
/ProjectSettings/AudioManager.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/AudioManager.asset
--------------------------------------------------------------------------------
/ProjectSettings/ClusterInputManager.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/ClusterInputManager.asset
--------------------------------------------------------------------------------
/ProjectSettings/DynamicsManager.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/DynamicsManager.asset
--------------------------------------------------------------------------------
/ProjectSettings/EditorBuildSettings.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/EditorBuildSettings.asset
--------------------------------------------------------------------------------
/ProjectSettings/EditorSettings.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/EditorSettings.asset
--------------------------------------------------------------------------------
/ProjectSettings/GraphicsSettings.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/GraphicsSettings.asset
--------------------------------------------------------------------------------
/ProjectSettings/InputManager.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/InputManager.asset
--------------------------------------------------------------------------------
/ProjectSettings/NavMeshAreas.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/NavMeshAreas.asset
--------------------------------------------------------------------------------
/ProjectSettings/NetworkManager.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/NetworkManager.asset
--------------------------------------------------------------------------------
/ProjectSettings/PackageManagerSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &1
4 | MonoBehaviour:
5 | m_ObjectHideFlags: 61
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | m_GameObject: {fileID: 0}
10 | m_Enabled: 1
11 | m_EditorHideFlags: 0
12 | m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0}
13 | m_Name:
14 | m_EditorClassIdentifier:
15 | m_EnablePreviewPackages: 0
16 | m_EnablePackageDependencies: 0
17 | m_AdvancedSettingsExpanded: 1
18 | m_ScopedRegistriesSettingsExpanded: 1
19 | oneTimeWarningShown: 0
20 | m_Registries:
21 | - m_Id: main
22 | m_Name:
23 | m_Url: https://packages.unity.com
24 | m_Scopes: []
25 | m_IsDefault: 1
26 | m_Capabilities: 7
27 | m_UserSelectedRegistryName:
28 | m_UserAddingNewScopedRegistry: 0
29 | m_RegistryInfoDraft:
30 | m_ErrorMessage:
31 | m_Original:
32 | m_Id:
33 | m_Name:
34 | m_Url:
35 | m_Scopes: []
36 | m_IsDefault: 0
37 | m_Capabilities: 0
38 | m_Modified: 0
39 | m_Name:
40 | m_Url:
41 | m_Scopes:
42 | -
43 | m_SelectedScopeIndex: 0
44 |
--------------------------------------------------------------------------------
/ProjectSettings/Physics2DSettings.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/Physics2DSettings.asset
--------------------------------------------------------------------------------
/ProjectSettings/PresetManager.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/PresetManager.asset
--------------------------------------------------------------------------------
/ProjectSettings/ProjectSettings.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/ProjectSettings.asset
--------------------------------------------------------------------------------
/ProjectSettings/ProjectVersion.txt:
--------------------------------------------------------------------------------
1 | m_EditorVersion: 2020.1.17f1
2 | m_EditorVersionWithRevision: 2020.1.17f1 (9957aee8edc2)
3 |
--------------------------------------------------------------------------------
/ProjectSettings/QualitySettings.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/QualitySettings.asset
--------------------------------------------------------------------------------
/ProjectSettings/TagManager.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/TagManager.asset
--------------------------------------------------------------------------------
/ProjectSettings/TimeManager.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/TimeManager.asset
--------------------------------------------------------------------------------
/ProjectSettings/UnityConnectSettings.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/UnityConnectSettings.asset
--------------------------------------------------------------------------------
/ProjectSettings/VFXManager.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/VFXManager.asset
--------------------------------------------------------------------------------
/ProjectSettings/VersionControlSettings.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivuecode/Unity-Pathfinding/999be056609d023123bd8f24c2c7cff70b20540e/ProjectSettings/VersionControlSettings.asset
--------------------------------------------------------------------------------
/ProjectSettings/XRSettings.asset:
--------------------------------------------------------------------------------
1 | {
2 | "m_SettingKeys": [
3 | "VR Device Disabled",
4 | "VR Device User Alert"
5 | ],
6 | "m_SettingValues": [
7 | "False",
8 | "False"
9 | ]
10 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Path Finding Algorithms :runner:
2 | Pathfinding algorithms implemented in Unity.
3 |
4 | This project implments Dijkstra, AStar, BreadthFirstSearch and GreedyBestFirst on a tiled grid. Set the start position, goal and create walls to visualise the step-by-step process of the algorithm. You can also change the iteration speed as well as color pallet.
5 |
6 | ## Preview :eyes:
7 | 
8 | 
9 |
10 | ## Getting Started :page_with_curl:
11 | Clone or download this repository and open the project with your favourite flavour of Unity.
12 | _This project was built with Unity 2020.1.17f1_
13 |
--------------------------------------------------------------------------------