Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading;
- using System.Threading.Tasks;
- using UnityEngine;
- namespace PathFinding
- {
- public class PathFinder : MonoBehaviour
- {
- //TODO: Thread Pool and DictionaryCopy
- [SerializeField] private Grid _grid;
- [SerializeField] private LayerMask _layers;
- [SerializeField] private Transform _startPoint;
- [SerializeField] private Vector2Int _size;
- public float CELL_WEIGTH = 1F;
- public float CELL_HEIGTH = 0.5F;
- private Dictionary<Vector3Int, PathNode> _field;
- private Pool<PathNode> _pathNodePool;
- private readonly AStar _aStar = new AStar();
- private static SynchronizationContext s_mainThread;
- private readonly Vector3Int[] neigborsCells = new Vector3Int[]
- {
- Vector3Int.up + Vector3Int.left, Vector3Int.up, Vector3Int.up + Vector3Int.right,
- Vector3Int.right, Vector3Int.left,
- Vector3Int.down + Vector3Int.left, Vector3Int.down, Vector3Int.down + Vector3Int.right
- };
- private void Awake()
- {
- _pathNodePool = new Pool<PathNode>(() => { return new PathNode(0, 0, new List<PathNode>()); });
- _field = GenerateField(true);
- s_mainThread = SynchronizationContext.Current;
- Debug.Log(SynchronizationContext.Current.ToString());
- }
- public async void FindPathAsync(Vector2 startPosition, Vector2 targetPosition, Action<List<Vector2>> callBack)
- {
- var field = GenerateField(false);
- PathNode startNode = GetNode(startPosition, field);
- PathNode targetNode = GetNode(targetPosition, field);
- await Task.Run(() => {
- FindPath(startNode, targetNode, callBack, field);
- });
- }
- private Dictionary<Vector3Int, PathNode> GenerateField(bool isMain)
- {
- Dictionary<Vector3Int, PathNode> field = new Dictionary<Vector3Int, PathNode>();
- for(int i = 0; i <= _size.x; i++)
- {
- for(int j = 0; j <= _size.y; j++)
- {
- Vector3Int cell = new Vector3Int(i, j, 0);
- if (isMain)
- {
- field.Add(cell, InitializePathNode(i, j, CheckForFreeSpace(cell)));
- }
- else
- {
- var pathNode = _field[cell];
- field.Add(cell, InitializePathNode(pathNode.X, pathNode.Y, pathNode.IsFree));
- }
- }
- }
- var pathnodes = field.Values.ToList();
- for (int i = 0; i < pathnodes.Count; i++)
- {
- for (int j = 0; j < neigborsCells.Length; j++)
- {
- Vector3Int cell = neigborsCells[j] + new Vector3Int(pathnodes[i].X, pathnodes[i].Y, 0);
- if (field.ContainsKey(cell))
- {
- var neighborPathnode = field[cell];
- pathnodes[i].Neighbors.Add(neighborPathnode);
- }
- }
- }
- return field;
- }
- private PathNode InitializePathNode(int x, int y, bool isFree)
- {
- var pathNode = _pathNodePool.Get();
- pathNode.X = x;
- pathNode.Y = y;
- pathNode.Neighbors = new List<PathNode>();
- pathNode.IsFree = isFree;
- return pathNode;
- }
- private void FindPath(PathNode startNode, PathNode targetNode, Action<List<Vector2>> callBack, Dictionary<Vector3Int, PathNode> field)
- {
- if (field.ContainsValue(startNode) == false || field.ContainsValue(targetNode) == false)
- {
- s_mainThread.Post(_ =>
- {
- callBack?.Invoke(new List<Vector2>());
- _pathNodePool.Add(field.Values.ToList());
- }, null);
- return;
- }
- s_mainThread.Post(_ =>
- {
- callBack?.Invoke(ConvertPathNodeToVector2(_aStar.FindPath(startNode, targetNode)));
- _pathNodePool.Add(field.Values.ToList());
- }, null);
- }
- public List<Vector2> ConvertPathNodeToVector2(List<PathNode> pathNodes)
- {
- if (pathNodes.Count == 0) return new List<Vector2>();
- List<Vector2> result = new List<Vector2>();
- for (int i = 0; i < pathNodes.Count; i++)
- {
- result.Add(GetWorldPosition(pathNodes[i]));
- }
- return result;
- }
- public bool CheckForFreeSpace(Vector3Int cell)
- {
- return Physics2D.OverlapCircleNonAlloc(GetWorldPosition(cell), 0.2f, new Collider2D[1], _layers) == 0;
- }
- public Vector3 GetWorldPosition(Vector3Int cell)
- {
- return _grid.GetCellCenterWorld(cell);
- }
- public Vector3 GetWorldPosition(PathNode pathNode)
- {
- return GetWorldPosition(new Vector3Int(pathNode.X, pathNode.Y, 0));
- }
- public PathNode GetNode(Vector2 worldPosition)
- {
- return GetNode(worldPosition, _field);
- }
- private PathNode GetNode(Vector2 worldPosition, Dictionary<Vector3Int, PathNode> field)
- {
- Vector3Int cell = _grid.WorldToCell(worldPosition);
- return field.ContainsKey(cell) ? field[cell] : null;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement