// NavMeshAgent helper function that returns the nearest valid point for a
    // given destination. This is really useful for click & wsad movement
    // because the player may click into all kinds of unwalkable paths:
    //
    //       ________
    //      |xxxxxxx|
    //      |x|   |x|
    // P   A|B| C |x|
    //      |x|___|x|
    //      |xxxxxxx|
    //
    // if a player is at position P and tries to go to:
    // - A: the path is walkable, everything is fine
    // - C: C is on a NavMesh, but we can't get there directly. CalcualatePath
    //      will return A as the last walkable point
    // - B: B is not on a NavMesh, CalulatePath doesn't work here. We need to
    //   find the nearest point on a NavMesh first (might be A or C) and then
    //   calculate the nearest valid one (A)
    public static Vector2 NearestValidDestination(this NavMeshAgent2D agent, Vector2 destination)
    {
        // can we calculate a path there? then return the closest valid point
        NavMeshPath2D path = new NavMeshPath2D();

        if (agent.CalculatePath(destination, path))
        {
            return(path.corners[path.corners.Length - 1]);
        }

        // otherwise find nearest navmesh position first. we use a radius of
        // speed*2 which works fine. afterwards we find the closest valid point.
        NavMeshHit hit;

        if (NavMesh.SamplePosition(new Vector3(destination.x, 0, destination.y), out hit, agent.speed * 2, NavMesh.AllAreas))
        {
            Vector2 hitPosition2D = new Vector2(hit.position.x, hit.position.z);
            if (agent.CalculatePath(hitPosition2D, path))
            {
                return(path.corners[path.corners.Length - 1]);
            }
        }

        // nothing worked, don't go anywhere.
        return(agent.transform.position);
    }
Beispiel #2
0
    void OnDrawGizmos()
    {
        // only while game is running, otherwise navmeshagent2d has no 3d agent.
        if (Application.isPlaying)
        {
            // can't cache agent because reloading script sometimes clears cached
            NavMeshAgent2D agent = GetComponent <NavMeshAgent2D>();

            // get path
            NavMeshPath2D path = agent.path;

            // color depends on status
            Color color = Color.white;
            switch (path.status)
            {
            case NavMeshPathStatus.PathComplete: color = Color.white; break;

            case NavMeshPathStatus.PathInvalid: color = Color.red; break;

            case NavMeshPathStatus.PathPartial: color = Color.yellow; break;
            }

            // draw the path
            for (int i = 1; i < path.corners.Length; ++i)
            {
                Debug.DrawLine(path.corners[i - 1], path.corners[i], color);
            }

            // draw velocity
            Debug.DrawLine(transform.position, transform.position + (Vector3)agent.velocity, Color.blue, 0, false);
        }
    }
    public bool CalculatePath(Vector2 targetPosition, NavMeshPath2D path)
    {
        var temp = new NavMeshPath();

        if (agent.CalculatePath(NavMeshUtils2D.ProjectTo3D(targetPosition), temp))
        {
            // convert 3D to 2D
            path.corners = temp.corners.Select(NavMeshUtils2D.ProjectTo2D).ToArray();
            path.status  = temp.status;
            return(true);
        }
        return(false);
    }