void FindPath(Vector3 startPos, Vector3 targetPos)
    {
        Node_nn startNode  = grid.NodeFromWorldPoint(startPos);
        Node_nn targetNode = grid.NodeFromWorldPoint(targetPos);

        if (startNode == targetNode)
        {
            return;
        }

        List <Node_nn>    openSet   = new List <Node_nn>();
        HashSet <Node_nn> closedSet = new HashSet <Node_nn>();

        openSet.Add(startNode);

        while (openSet.Count > 0)
        {
            Node_nn node = openSet[0];
            for (int i = 1; i < openSet.Count; i++)
            {
                if (openSet[i].fCost < node.fCost || openSet[i].fCost == node.fCost)
                {
                    if (openSet[i].hCost < node.hCost)
                    {
                        node = openSet[i];
                    }
                }
            }

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

            if (node == targetNode)
            {
                RetracePath(startNode, targetNode);
                return;
            }

            foreach (Node_nn neighbour in grid.GetNeighbours(node))
            {
                if (!neighbour.walkable || closedSet.Contains(neighbour))
                {
                    continue;
                }

                int newCostToNeighbour = node.gCost + GetDistance(node, neighbour);
                if (newCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour))
                {
                    neighbour.gCost  = newCostToNeighbour;
                    neighbour.hCost  = GetDistance(neighbour, targetNode);
                    neighbour.parent = node;

                    if (!openSet.Contains(neighbour))
                    {
                        openSet.Add(neighbour);
                    }
                }
            }
        }
    }
示例#2
0
    public List<Node_nn> GetNeighbours(Node_nn node)
    {
        List<Node_nn> neighbours = new List<Node_nn>();

        // //logic for diagonals - 8 neighbours 
        // for (int x = -1; x <= 1; x++)
        // {
        //     for (int y = -1; y <= 1; y++)
        //     {
        //         if (x == 0 && y == 0)
        //             continue;

        //         int checkX = node.gridX + x;
        //         int checkY = node.gridY + y;

        //         if (checkX >= 0 && checkX < gridSizeX && checkY >= 0 && checkY < gridSizeY)
        //         {
        //             neighbours.Add(grid[checkX, checkY]);
        //         }
        //     }
        // }


        //logic for 4 instead of 8 expected neighbours
        Vector2Int multiplyDirection = new Vector2Int(); //left right up down, no diagonals
        for (int a = 0; a < 4; a++)
        {
            // too lazy to think of a smart loop, optimize later if you feel like burning some calories
            switch (a)
            {
                case 0:
                multiplyDirection = new Vector2Int(1,0);
                break;
                case 1:
                multiplyDirection = new Vector2Int(-1,0);
                break;
                case 2:
                multiplyDirection = new Vector2Int(0,1);
                break;
                case 3:
                multiplyDirection = new Vector2Int(0,-1);
                break;
                default:
                break;
            }
            
            int checkX = node.gridX + multiplyDirection.x;
            int checkY = node.gridY + multiplyDirection.y;
            if (checkX >= 0 && checkX < gridSizeX && checkY >= 0 && checkY < gridSizeY)
            {
                neighbours.Add(grid[checkX, checkY]);
            }
        }

        return neighbours;
    }
    int GetDistance(Node_nn nodeA, Node_nn nodeB)
    {
        int dstX = Mathf.Abs(nodeA.gridX - nodeB.gridX);
        int dstY = Mathf.Abs(nodeA.gridY - nodeB.gridY);

        if (dstX > dstY)
        {
            return(14 * dstY + 10 * (dstX - dstY));
        }
        return(14 * dstX + 10 * (dstY - dstX));
    }
    void RetracePath(Node_nn startNode, Node_nn endNode)
    {
        List <Node_nn> path        = new List <Node_nn>();
        Node_nn        currentNode = endNode;

        while (currentNode != startNode)
        {
            path.Add(currentNode);
            currentNode = currentNode.parent;
        }
        // Vector3[] waypoints = SimplifyPath(path);
        Vector3[] waypoints = GetLastNodeToFollow(path); // easier and more accurate way

        Array.Reverse(waypoints);

        grid.path      = path;
        grid.waypoints = waypoints;


        if (onlyonce)
        {
            for (int i = 0; i < waypoints.Length; i++)
            {
                // print("Point no");
                // print(i);
                // print("=");
                // print(waypoints[i]);
            }
            onlyonce = false;
        }

        if (waypoints.Length > 0)
        {
            seekerObject.transform.position = Vector3.MoveTowards(seekerObject.transform.position, waypoints[0], speed * Time.deltaTime);
            float dir = seekerObject.transform.position.x - waypoints[0].x;

            if (dir < 0)
            {
                transform.localScale = new Vector3(-1, 1, 1);
            }
            else
            {
                transform.localScale = new Vector3(1, 1, 1);
            }
        }
    }
示例#5
0
    void CreateGrid()
    {
        grid = new Node_nn[gridSizeX, gridSizeY];
        Vector3 worldBottomLeft = transform.position - Vector3.right * gridWorldSize.x / 2 - Vector3.up * gridWorldSize.y / 2;
        
        for (int x = 0; x < gridSizeX; x++)
        {
            for (int y = 0; y < gridSizeY; y++)
            {
                Vector3 worldPoint = worldBottomLeft + Vector3.right * (x * nodeDiameter + nodeRadius) + Vector3.up * (y * nodeDiameter + nodeRadius);
                
                // bool walkable = !(Physics2D.OverlapCircle(worldPoint, nodeRadius, unwalkableMask));
                bool walkable = tilemap.GetTile(tilemap.WorldToCell(worldPoint)) == null ? true : false;  // checking instead if the foreground tilemap has a tile

                grid[x, y] = new Node_nn(walkable, worldPoint, x, y, walkable?false:true);
            }
        }
    }
示例#6
0
    public void UpdateTiles()
    {
        TempNodeCache.Clear();
        RemoveNodeCache.Clear();

        for (float x = -lengthRadius; x < lengthRadius; x += 1)
        {
            for (float y = -heightRadius; y < heightRadius; y += 1)
            {
                getWorldTilesPos = gameObject.transform.position + new Vector3(x + 0.8f, y + 0.59f, 0); // offset values from testing and trying to get it right in the inspector

                // Debug.Log("getWorldTilesPos "+getWorldTilesPos);
                nodeCache = GridRef.NodeFromWorldPoint(getWorldTilesPos);
                TempNodeCache.Add(nodeCache);
                NodeCollisionCache.Add(nodeCache);
                nodeCache.walkable = false;
            }
        }

        // compare the tiles that are no longer present and cache them to be removed
        foreach (Node_nn node in NodeCollisionCache)
        {
            if (!TempNodeCache.Contains(node)) // if the moving platform is no longer over a node/tile
            {
                RemoveNodeCache.Add(node);
                if (!node.isStatic) // incase of static/unwalkable background, dont make it walkable
                {
                    node.walkable = true;
                }
            }
        }

        // remove tiles that the platform is not over
        foreach (Node_nn node in RemoveNodeCache)
        {
            NodeCollisionCache.Remove(node);
        }
    }