public static PathInfo GetStraightPath(Unit unit, PathSquare start, PathSquare end)
    {
        HashSet <PathSquare> closedSet = new HashSet <PathSquare>();

        ResetPathSquare();

        bool reachedGoal = false;

        var direction = (end.pos.ToVector() - start.pos.ToVector()).normalized;

        var current = start;

        while (current != null)
        {
            if (current == end)
            {
                //return PathInfo.GenerateWaypoints(start, current);
                reachedGoal = true;
            }

            closedSet.Add(current);

            var next = current.pos.ToVector() + direction;

            PathSquareNeighbourInfo nextNeighbour;
            if (current.neighbours.TryGetValue(next.ConvertToIPosition(), out nextNeighbour))
            {
                if (!closedSet.Contains(nextNeighbour.neighbour))
                {
                    if (nextNeighbour.neighbour == end || CanWalkToSquare(unit, nextNeighbour))
                    {
                        nextNeighbour.neighbour.parent = current;
                        current = nextNeighbour.neighbour;
                        continue;
                    }
                }
            }

            break;
        }

        if (reachedGoal)
        {
            return(PathInfo.GenerateWaypoints(start, current));
        }

        return(null);
    }
    public static PathInfo GetShortestPath(Unit unit, PathSquare start, PathSquare end)
    {
        HashSet <PathSquare> closedSet = new HashSet <PathSquare>();
        HashSet <PathSquare> openSet   = new HashSet <PathSquare>();

        PathSquare closestSquare   = null;
        double     closestDistance = 9999;

        openSet.Add(start);

        ResetPathSquare();

        start.gScore = 0;
        start.fScore = start.Distance(end);

        double bestRouteDist = start.Distance(end);

        while (openSet.Count > 0)
        {
            var current = openSet.OrderBy(n => n.fScore).FirstOrDefault();

            if (current == end)
            {
                return(PathInfo.GenerateWaypoints(start, current));
            }

            openSet.Remove(current);
            closedSet.Add(current);

            foreach (var pair in current.neighbours)
            {
                var neighbourInfo = pair.Value;
                var neighbour     = neighbourInfo.neighbour;
                var distance      = neighbourInfo.distance;


                if (closedSet.Contains(neighbour))
                {
                    continue;
                }

                if (!CanWalkToSquare(unit, neighbourInfo))
                {
                    continue;
                }

                var alternativeDistance = current.gScore + distance;

                /*if(alternativeDistance > bestRouteDist * 2)
                 * {
                 *  continue; //stop searching for route that's longer than 2x the optimal path
                 * }*/

                if (!openSet.Contains(neighbour))
                {
                    openSet.Add(neighbour);
                }
                else if (alternativeDistance >= neighbour.gScore)
                {
                    continue;
                }

                var estimatedDistance = neighbour.Distance(end);

                neighbour.parent = current;
                neighbour.gScore = alternativeDistance;
                neighbour.fScore = alternativeDistance + estimatedDistance;

                if (closestDistance > estimatedDistance)
                {
                    closestSquare   = neighbour;
                    closestDistance = estimatedDistance;
                }
            }
        }

        if (closestSquare == null)
        {
            return(null);
        }

        if (closestSquare.Distance(end) < start.Distance(end))
        {
            var path = PathInfo.GenerateWaypoints(start, closestSquare);
            path.reachable = false;

            return(path);
        }
        else
        {
            return(null);
        }
    }