Advertisement
Guest User

Untitled

a guest
Apr 24th, 2019
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.28 KB | None | 0 0
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using System.Diagnostics;
  5.  
  6. public class Pathfinding : MonoBehaviour {
  7.  
  8. public Transform seeker, target;
  9. Grid grid;
  10.  
  11. void Start ()
  12. {
  13. grid = GetComponent<Grid> ();
  14. }
  15.  
  16. void Update()
  17. {
  18. if(Input.GetMouseButtonDown(0))
  19. {
  20. FindPath(seeker.position, target.position);
  21. PriorityQueueFindPath(seeker.position, target.position);
  22. }
  23. }
  24.  
  25. void FindPath(Vector3 startPos, Vector3 targetPos)
  26. {
  27. Stopwatch sw = new Stopwatch();
  28. sw.Start();
  29.  
  30. //int j = 0;
  31.  
  32. Node startNode = grid.NodeFromWorldPosition(startPos);
  33. Node targetNode = grid.NodeFromWorldPosition(targetPos);
  34.  
  35. List<Node> openSet = new List<Node> ();
  36. HashSet<Node> closedSet = new HashSet<Node>();
  37. openSet.Add (startNode);
  38.  
  39.  
  40. while (openSet.Count > 0) {
  41. // j++;
  42. // UnityEngine.Debug.Log(j);
  43. //if (j > 1000)
  44. // return;
  45. // OpenSet에서 가장 낮은 fCost를 가지는 노드를 가져온다.
  46. // 만일 fCost가 동일할 경우 gCost가 적은 쪽을 택함.
  47. Node currentNode = openSet[0];
  48.  
  49. /* 해당 코드를 작성할 것 */
  50. for (int i = 0; i < openSet.Count - 1; i++)
  51. {
  52. openSet[i].gCost = GetDistance(startNode, openSet[i]);
  53. openSet[i].hCost = GetDistance(openSet[i], targetNode);
  54. if (currentNode.fCost > openSet[i].fCost)
  55. {
  56. //openSet[i].parent = currentNode;
  57. currentNode = openSet[i];
  58. }
  59. else if (currentNode.fCost == openSet[i].fCost)
  60. {
  61. if (currentNode.gCost > openSet[i].gCost)
  62. {
  63. //openSet[i].parent = currentNode;
  64. currentNode = openSet[i];
  65. }
  66. }
  67. }
  68.  
  69.  
  70. // UnityEngine.Debug.Log(currentNode.worldPosition);
  71.  
  72. // 찾은 노드가 최종 노드면 루프 종료
  73. if (currentNode == targetNode)
  74. {
  75. RetracePath(startNode, targetNode);
  76. sw.Stop();
  77. print("Elapsed Time : " + sw.ElapsedTicks + "ticks");
  78. return;
  79. }
  80.  
  81. // 해당 노드를 ClosedSet으로 이동
  82. /* 해당 코드를 작성할 것 */
  83. openSet.Remove(currentNode);
  84. closedSet.Add(currentNode);
  85.  
  86. // 현재 노드의 이웃들을 모두 가져와 비교
  87. foreach (Node n in grid.GetNeighbours(currentNode))
  88. {
  89. // 이웃 노드가 이미 ClosedSet에 있거나 걸어다니지 못하는 곳이면 제외한다.
  90. /* 해당 코드를 작성할 것 */
  91. if (closedSet.Contains(n) || !n.walkable)
  92. continue;
  93.  
  94. // 현재 노드를 기점에서 파생된 이웃 노드의 fCost를 계산한다.
  95. /* 해당 코드를 작성할 것 */
  96. int g = currentNode.gCost + GetDistance(currentNode, n);
  97. int h = GetDistance(n, targetNode);
  98. int f = g + h;
  99.  
  100. // 오픈셋에 현재 노드가 없으면 노드에 점수를 설정한 후 추가한다.
  101. if (!openSet.Contains(n))
  102. {
  103. /* 해당 코드를 작성할 것 */
  104. n.gCost = g;
  105. n.hCost = h;
  106. n.parent = currentNode;
  107. openSet.Add(n);
  108. }
  109. else
  110. {
  111. // 오픈셋에 현재 노드가 이미 있으면 수치를 비교한 후 경로를 교체한다. 동일하면 g수치가 큰 쪽으로 교체한다.
  112. /* 해당 코드를 작성할 것 */
  113. if (n.fCost > f || (n.fCost == f && n.gCost > g))
  114. {
  115. n.gCost = g;
  116. n.parent = currentNode;
  117. }
  118. }
  119. }
  120. }
  121.  
  122. }
  123.  
  124.  
  125. void PriorityQueueFindPath(Vector3 startPos, Vector3 targetPos)
  126. {
  127. Stopwatch sw = new Stopwatch();
  128. sw.Start();
  129.  
  130. //int j = 0;
  131.  
  132. Node startNode = grid.NodeFromWorldPosition(startPos);
  133. Node targetNode = grid.NodeFromWorldPosition(targetPos);
  134.  
  135. PriorityQueue openSet = new PriorityQueue(1000);
  136. HashSet<Node> closedSet = new HashSet<Node>();
  137. openSet.Enqueue (startNode);
  138.  
  139.  
  140.  
  141. while (openSet.Count > 0) {
  142. // OpenSet에서 가장 낮은 fCost를 가지는 노드를 가져온다.
  143. // 만일 fCost가 동일할 경우 gCost가 적은 쪽을 택함.
  144. Node currentNode = openSet.Dequeue();
  145.  
  146.  
  147.  
  148. // 찾은 노드가 최종 노드면 루프 종료
  149. if (currentNode == targetNode)
  150. {
  151. RetracePath(startNode, targetNode);
  152. sw.Stop();
  153. print("PriorityQueue Time : " + sw.ElapsedTicks + "ticks");
  154. return;
  155. }
  156.  
  157. // 해당 노드를 ClosedSet으로 이동
  158. /* 해당 코드를 작성할 것 */
  159.  
  160. closedSet.Add(currentNode);
  161.  
  162. // 현재 노드의 이웃들을 모두 가져와 비교
  163. foreach (Node n in grid.GetNeighbours(currentNode))
  164. {
  165. // 이웃 노드가 이미 ClosedSet에 있거나 걸어다니지 못하는 곳이면 제외한다.
  166. /* 해당 코드를 작성할 것 */
  167. if (closedSet.Contains(n) || !n.walkable)
  168. continue;
  169.  
  170. // 현재 노드를 기점에서 파생된 이웃 노드의 fCost를 계산한다.
  171. /* 해당 코드를 작성할 것 */
  172. int g = currentNode.gCost + GetDistance(currentNode, n);
  173. int h = GetDistance(n, targetNode);
  174. int f = g + h;
  175.  
  176. // 오픈셋에 현재 노드가 없으면 노드에 점수를 설정한 후 추가한다.
  177. if (!openSet.Contains(n))
  178. {
  179. n.gCost = g;
  180. n.hCost = h;
  181. n.parent = currentNode;
  182. openSet.Enqueue(n);
  183. }
  184. else
  185. {
  186. // 오픈셋에 현재 노드가 이미 있으면 수치를 비교한 후 경로를 교체한다. 동일하면 g수치가 큰 쪽으로 교체한다.
  187. /* 해당 코드를 작성할 것 */
  188. if (n.fCost > f || (n.fCost == f && n.gCost > g))
  189. {
  190. n.gCost = g;
  191. n.parent = currentNode;
  192. }
  193.  
  194.  
  195. }
  196. }
  197. }
  198.  
  199. }
  200.  
  201. // 경로를 보여준다.
  202. void RetracePath(Node startNode, Node endNode)
  203. {
  204. List<Node> path = new List<Node> ();
  205. Node currentNode = endNode;
  206.  
  207. while (currentNode != startNode) {
  208. //UnityEngine.Debug.Log(currentNode.worldPosition);
  209. path.Add (currentNode);
  210. currentNode = currentNode.parent;
  211. }
  212.  
  213. grid.path = path;
  214. }
  215.  
  216. int GetDistance(Node nodeA, Node nodeB)
  217. {
  218. int dstX = Mathf.Abs(nodeA.gridX - nodeB.gridX);
  219. int dstY = Mathf.Abs(nodeA.gridY - nodeB.gridY);
  220.  
  221. if(dstX > dstY)
  222. {
  223. return 14*dstY + 10*(dstX - dstY);
  224. }
  225.  
  226. return 14*dstX + 10*(dstY - dstX);
  227. }
  228. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement