IlludiumPu36
IlludiumPu36

Reputation: 4304

NPC instantiate on Navmesh

I am trying to instantiate a NPC prefab on a NavMesh in a grid fashion. The prefab has the component NavMeshAgent and the NavMesh has been baked. I am getting the errors:

"SetDestination" can only be called on an active agent that has been placed on a NavMesh.
UnityEngine.AI.NavMeshAgent:SetDestination(Vector3)

and

"GetRemainingDistance" can only be called on an active agent that has been placed on a NavMesh.
UnityEngine.AI.NavMeshAgent:get_remainingDistance()

This using the following script on an empty GameObject placed over the NavMesh:

 // Instantiates a prefab in a grid

    public GameObject prefab;
    public float gridX = 5f;
    public float gridY = 5f;
    public float spacing = 2f;

    void Start()
    {
        for (int y = 0; y < gridY; y++)
        {
            for (int x = 0; x < gridX; x++)
            {
                Vector3 pos = new Vector3(x, 0, y) * spacing;
                Instantiate(prefab, pos, Quaternion.identity);
            }
        }
    }

Upvotes: 0

Views: 5568

Answers (3)

IlludiumPu36
IlludiumPu36

Reputation: 4304

OK, sorted the issue. As per my OP, I did have a baked Nav Mesh and prefabs had the Nav Mesh Agent component. The issue was the resolution of the Nav Mesh and the Base Offset on the Nav Mesh Agent which was set to -0.2.

Rebaking the Nav Mesh with the Height Mesh setting made the walkable areas more accurate.

enter image description here

Together with changing the Base Offset on the Nav Mesh Agent to 0.

enter image description here

Upvotes: 1

Ignacio Alorre
Ignacio Alorre

Reputation: 7605

About:

"SetDestination" can only be called on an active agent that has been placed on a NavMesh. UnityEngine.AI.NavMeshAgent:SetDestination(Vector3)

I believe the problem is you are not adding the corresponding NavMeshAgent logic to the prefabs you are instantiating. Do the following:

  • Add a Nav Mesh Agent to the prefab you are instantiating
  • Set, just for testing, a destination point (this can be an empty gameobject), and name it "Destination"
  • Add the following script to the GameObject you want to instantiate

Something like this:

public class Movement : MonoBehaviour {
        //Point towards the instantiated Object will move
        Transform goal;

        //Reference to the NavMeshAgent
        UnityEngine.AI.NavMeshAgent agent;

        // Use this for initialization
        void Start () {
            //You get a reference to the destination point inside your scene
            goal = GameObject.Find("Destination").GetComponent<Transform>();

            //Here you get a reference to the NavMeshAgent
             agent = GetComponent<UnityEngine.AI.NavMeshAgent>();

            //You indicate to the agent to what position it has to move
            agent.destination = goal.position;
        }

}

In case your instantiated prefab needs to chase something, you can update the goal.position from the Update(). Like:

void Update(){
    agent.destination = goal.position;
}

Upvotes: 0

Monza
Monza

Reputation: 755

I'm going to start by saying that NavMesh is very tricky at times. There are so many little quirks etc involved that I ended up moving away from NavMesh and am using an A* (A Star) ray-cast style library. Nowhere as efficient for dozens of simultaneous moving entities but very versatile for dynamic maps AND for objects/model climbing.

Also I'd say that being able to use the simple API commands isn't sufficient to use Nav Mesh - you need to understand the multitude of components that work together and Unity documentation is not as helpful as it should be. Be prepared to pull a fair bit of hair out if you are using dynamic entities and need to recarve, etc.

Anyway, first thing I'd warn you about is that if your entities have colliders around them they may interfere with their own navigation (as their own collider can cut into the nav-mesh, leaving the entity on a small patch of non-mesh).

Secondly, I'd suggest you Warp() your entity onto the nav mesh. This takes your entity's location (possibly not truly on the nav mesh) and warps it to the closes available NavMesh node / link at which point it should be able to navigate

Good luck!

Upvotes: 3

Related Questions