Advertisement
Guest User

Untitled

a guest
Apr 18th, 2021
10
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.65 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. using UnityEngine;
  7.  
  8. namespace PathFinding
  9. {
  10. public class PathFinder : MonoBehaviour
  11. {
  12. //TODO: Thread Pool and DictionaryCopy
  13. [SerializeField] private Grid _grid;
  14. [SerializeField] private LayerMask _layers;
  15.  
  16. [SerializeField] private Transform _startPoint;
  17. [SerializeField] private Vector2Int _size;
  18.  
  19. public float CELL_WEIGTH = 1F;
  20. public float CELL_HEIGTH = 0.5F;
  21.  
  22. private Dictionary<Vector3Int, PathNode> _field;
  23. private Pool<PathNode> _pathNodePool;
  24.  
  25. private readonly AStar _aStar = new AStar();
  26. private static SynchronizationContext s_mainThread;
  27.  
  28.  
  29.  
  30.  
  31.  
  32. private readonly Vector3Int[] neigborsCells = new Vector3Int[]
  33. {
  34. Vector3Int.up + Vector3Int.left, Vector3Int.up, Vector3Int.up + Vector3Int.right,
  35. Vector3Int.right, Vector3Int.left,
  36. Vector3Int.down + Vector3Int.left, Vector3Int.down, Vector3Int.down + Vector3Int.right
  37. };
  38.  
  39. private void Awake()
  40. {
  41. _pathNodePool = new Pool<PathNode>(() => { return new PathNode(0, 0, new List<PathNode>()); });
  42. _field = GenerateField(true);
  43. s_mainThread = SynchronizationContext.Current;
  44. Debug.Log(SynchronizationContext.Current.ToString());
  45. }
  46.  
  47. public async void FindPathAsync(Vector2 startPosition, Vector2 targetPosition, Action<List<Vector2>> callBack)
  48. {
  49. var field = GenerateField(false);
  50. PathNode startNode = GetNode(startPosition, field);
  51. PathNode targetNode = GetNode(targetPosition, field);
  52. await Task.Run(() => {
  53. FindPath(startNode, targetNode, callBack, field);
  54. });
  55.  
  56. }
  57.  
  58. private Dictionary<Vector3Int, PathNode> GenerateField(bool isMain)
  59. {
  60. Dictionary<Vector3Int, PathNode> field = new Dictionary<Vector3Int, PathNode>();
  61.  
  62. for(int i = 0; i <= _size.x; i++)
  63. {
  64. for(int j = 0; j <= _size.y; j++)
  65. {
  66. Vector3Int cell = new Vector3Int(i, j, 0);
  67.  
  68. if (isMain)
  69. {
  70. field.Add(cell, InitializePathNode(i, j, CheckForFreeSpace(cell)));
  71. }
  72. else
  73. {
  74. var pathNode = _field[cell];
  75. field.Add(cell, InitializePathNode(pathNode.X, pathNode.Y, pathNode.IsFree));
  76. }
  77. }
  78. }
  79.  
  80. var pathnodes = field.Values.ToList();
  81.  
  82. for (int i = 0; i < pathnodes.Count; i++)
  83. {
  84. for (int j = 0; j < neigborsCells.Length; j++)
  85. {
  86. Vector3Int cell = neigborsCells[j] + new Vector3Int(pathnodes[i].X, pathnodes[i].Y, 0);
  87. if (field.ContainsKey(cell))
  88. {
  89. var neighborPathnode = field[cell];
  90.  
  91. pathnodes[i].Neighbors.Add(neighborPathnode);
  92. }
  93. }
  94. }
  95. return field;
  96. }
  97.  
  98. private PathNode InitializePathNode(int x, int y, bool isFree)
  99. {
  100. var pathNode = _pathNodePool.Get();
  101. pathNode.X = x;
  102. pathNode.Y = y;
  103. pathNode.Neighbors = new List<PathNode>();
  104. pathNode.IsFree = isFree;
  105. return pathNode;
  106. }
  107.  
  108. private void FindPath(PathNode startNode, PathNode targetNode, Action<List<Vector2>> callBack, Dictionary<Vector3Int, PathNode> field)
  109. {
  110.  
  111. if (field.ContainsValue(startNode) == false || field.ContainsValue(targetNode) == false)
  112. {
  113. s_mainThread.Post(_ =>
  114. {
  115. callBack?.Invoke(new List<Vector2>());
  116. _pathNodePool.Add(field.Values.ToList());
  117. }, null);
  118. return;
  119. }
  120. s_mainThread.Post(_ =>
  121. {
  122. callBack?.Invoke(ConvertPathNodeToVector2(_aStar.FindPath(startNode, targetNode)));
  123. _pathNodePool.Add(field.Values.ToList());
  124. }, null);
  125. }
  126. public List<Vector2> ConvertPathNodeToVector2(List<PathNode> pathNodes)
  127. {
  128. if (pathNodes.Count == 0) return new List<Vector2>();
  129. List<Vector2> result = new List<Vector2>();
  130. for (int i = 0; i < pathNodes.Count; i++)
  131. {
  132. result.Add(GetWorldPosition(pathNodes[i]));
  133. }
  134. return result;
  135. }
  136.  
  137. public bool CheckForFreeSpace(Vector3Int cell)
  138. {
  139. return Physics2D.OverlapCircleNonAlloc(GetWorldPosition(cell), 0.2f, new Collider2D[1], _layers) == 0;
  140. }
  141.  
  142. public Vector3 GetWorldPosition(Vector3Int cell)
  143. {
  144. return _grid.GetCellCenterWorld(cell);
  145. }
  146.  
  147. public Vector3 GetWorldPosition(PathNode pathNode)
  148. {
  149. return GetWorldPosition(new Vector3Int(pathNode.X, pathNode.Y, 0));
  150. }
  151.  
  152. public PathNode GetNode(Vector2 worldPosition)
  153. {
  154. return GetNode(worldPosition, _field);
  155. }
  156.  
  157. private PathNode GetNode(Vector2 worldPosition, Dictionary<Vector3Int, PathNode> field)
  158. {
  159. Vector3Int cell = _grid.WorldToCell(worldPosition);
  160. return field.ContainsKey(cell) ? field[cell] : null;
  161. }
  162.  
  163. }
  164. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement