コード例 #1
0
    public void FindPath(PathRequest request, Action <PathResult> callback)
    {
        Stopwatch sw = new Stopwatch(); //check how long the method takes

        sw.Start();

        Vector3[] waypoints   = new Vector3[0];                       //contains the path
        bool      pathSuccess = false;                                //if path could be found

        Node startNode  = grid.NodeFromWorldPoint(request.pathStart); //get start and end in node
        Node targetNode = grid.NodeFromWorldPoint(request.pathEnd);

        Heap <Node>    openSet   = new Heap <Node>(grid.MaxSize); //create heap for all nodes that can be moved to
        HashSet <Node> closedSet = new HashSet <Node>();          //hash set for all nodes that can't be moved to

        openSet.Add(startNode);                                   //add the startnode for a starting point

        if (startNode.walkable && targetNode.walkable)
        {
            while (openSet.Count > 0)                     //only breaks if target node is unreacheble
            {
                Node currentNode = openSet.RemoveFirst(); //set current node to the first one in openSet and remove it from the openset
                closedSet.Add(currentNode);               //so you can't move to current node again

                if (currentNode == targetNode)            //if goal is reached
                {
                    sw.Stop();
                    print("Path found: " + sw.ElapsedMilliseconds + " ms");
                    pathSuccess = true;
                    break;
                }

                foreach (Node neighbour in grid.GetNeighbours(currentNode))   //if an open neighbour to the current node gets a lower gcost from using currents path (patrents), current is the neighbours parent
                {
                    if (!neighbour.walkable || closedSet.Contains(neighbour)) //if neighbour is not walkable or on the closed set skip it
                    {
                        continue;
                    }

                    int movenCostToNeighbour = currentNode.gCost + GetDistance(currentNode, neighbour) + neighbour.movementPenalty; //the cost for moving to the neighbour
                    if (movenCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour))                                     //if the new cost is lower than the old or neighbour has not yet been added to openset
                    {
                        neighbour.gCost  = movenCostToNeighbour;                                                                    //set g cost
                        neighbour.hCost  = GetDistance(neighbour, targetNode);                                                      //set h cost
                        neighbour.parent = currentNode;                                                                             //set parent to backtrack to start from goal

                        if (!openSet.Contains(neighbour))                                                                           //if node was not in openset, add it
                        {
                            openSet.Add(neighbour);
                        }
                        else
                        {
                            openSet.UpdateItem(neighbour); //else, just update heap
                        }
                    }
                }
            }
        }
        if (pathSuccess)
        {
            waypoints   = RetracePath(startNode, targetNode); //if path was found, save it in the array
            pathSuccess = waypoints.Length > 0;
        }
        callback(new PathResult(waypoints, pathSuccess, request.callback)); //tell request manager that the path is found
        //UnityEngine.Debug.Log(GC.GetTotalMemory(true) + " Bytes");
    }
コード例 #2
0
    IEnumerator FindPath(Vector3 startPos, Vector3 targetPos)
    {
        Stopwatch sw = new Stopwatch();

        sw.Start();

        Vector3[] waypoints   = new Vector3[0];
        bool      pathSuccess = false;

        Node startNode  = grid.NodeFromWorldPoint(startPos);
        Node targetNode = grid.NodeFromWorldPoint(targetPos);

        Heap <Node>    openSet   = new Heap <Node>(grid.MaxSize);
        HashSet <Node> closedSet = new HashSet <Node>();

        openSet.Add(startNode);

        if (startNode.walkable && targetNode.walkable)
        {
            while (openSet.Count > 0) //only breaks if target node is unreacheble
            {
                Node currentNode = openSet.RemoveFirst();
                closedSet.Add(currentNode);

                if (currentNode == targetNode) //if goal is reached
                {
                    sw.Stop();
                    print("Path found: " + sw.ElapsedMilliseconds + " ms");
                    pathSuccess = true;
                    break;
                }

                foreach (Node neighbour in grid.GetNeighbours(currentNode)) //if open neighbour to current gets a lower gcost from using currents path(patrents), current is the neighbours parent, basically starts here
                {
                    if (!neighbour.walkable || closedSet.Contains(neighbour))
                    {
                        continue;
                    }

                    int movenCostToNeighbour = currentNode.gCost + getDistance(currentNode, neighbour);
                    if (movenCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour))
                    {
                        neighbour.gCost  = movenCostToNeighbour;
                        neighbour.hCost  = getDistance(neighbour, targetNode);
                        neighbour.parent = currentNode;

                        if (!openSet.Contains(neighbour))
                        {
                            openSet.Add(neighbour);
                        }
                        else
                        {
                            openSet.UpdateItem(neighbour);
                        }
                    }
                }
            }
        }
        yield return(null);

        if (pathSuccess)
        {
            waypoints = RetracePath(startNode, targetNode);
        }
        requsetManager.FinishedProcessingPath(waypoints, pathSuccess);
    }
コード例 #3
0
    IEnumerator FollowPath() //basiclly same as Update but can be started and stoped. for moving to target along path
    {
        bool    grounded      = false;
        Vector3 lastPos       = transform.position;
        bool    followingPath = true;
        int     pathIndex     = 0;
        //transform.LookAt(path.lookpoints[0]); //face first waypoint

        float speedPercent = 1;

        while (followingPath)
        {
            Vector2 pos2D = new Vector2(transform.position.x, transform.position.z);
            while (path.turnBoundaries[pathIndex].HasCrossedLine(pos2D))
            {
                if (pathIndex == path.finishLineIndex)
                {
                    followingPath = false;
                    //FindNextPath();
                    break;
                }
                else
                {
                    pathIndex++;
                }
            }

            if (followingPath)
            {
                speedPercent = 1;
                if (pathIndex >= path.slowDownIndex && stoppingDst > 0 && slowDown)
                {
                    speedPercent = Mathf.Clamp01(path.turnBoundaries[path.finishLineIndex /*- 1*/].DistanceFromPoint(pos2D) / stoppingDst + 0.2f); //add to avoid stopping compleatly
                }
                Quaternion targetRotation = Quaternion.LookRotation(path.lookpoints[pathIndex] - transform.position);
                transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, Time.deltaTime * turnSpeed);
                transform.rotation = new Quaternion(0, transform.rotation.y, 0, transform.rotation.w);
                transform.Translate(Vector3.forward * Time.deltaTime * speed, Space.Self);

                frontCheck  = new Ray(transform.position + Vector3.up / 3, transform.forward + Vector3.up * maxJumpHeight / 2);
                topCheck    = new Ray(transform.position + Vector3.up * maxJumpHeight, transform.forward);
                groundCheck = new Ray(transform.position + Vector3.up / 2, Vector3.down);
                RaycastHit obstacle;

                timeSinceJump += Time.deltaTime;
                grounded       = Physics.Raycast(groundCheck, 1);                                                                                       //check if AI is standing on ground

                if (Physics.Raycast(frontCheck.origin, frontCheck.direction, out obstacle, 4, grid.walkableMask.value, QueryTriggerInteraction.Ignore)) //something is in the way
                {
                    if (!Physics.Raycast(topCheck, 5))                                                                                                  //check that the obstacle can be jumped over
                    {
                        if (grounded)                                                                                                                   //if AI is standing on the ground
                        {
                            if (timeSinceJump > 1)                                                                                                      //this is to prevent the AI from jumping more than once per second
                            {
                                rb.velocity = new Vector3(rb.velocity.x, Mathf.Sqrt(maxJumpHeight * Physics.gravity.magnitude * 2), rb.velocity.z);
                                //rb.AddForce(Vector3.up * Mathf.Sqrt(maxJumpHeight * Physics.gravity.magnitude * 2), ForceMode.Impulse);
                                timeSinceJump = 0;
                            }
                        }
                    }
                    else
                    {
                        grid.NodeFromWorldPoint(obstacle.point).walkable = false; //tried jumping, didnt work. set this to unwalkable
                    }
                }

                if (slowDown)
                {
                    transform.Translate(Vector3.forward * Time.deltaTime * speed * speedPercent, Space.Self);
                }
            }

            yield return(null); //wait one frame
        }
        //Vector3.MoveTowards(transform.position, target.position, Time.deltaTime * speed);
        //yield return null; //wait one frame
    }