Reputation: 4304
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
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.
Together with changing the Base Offset on the Nav Mesh Agent to 0.
Upvotes: 1
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:
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
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