Hey nathanjams,
I wanted to make sure I understood what you were doing correctly. Some of your posts mention multiple NavMeshes, which would actually require you connect them with a NavMeshLink, and possibly (depending on your bake settings) that you change the NavMeshAgent’s type to swap between being able to walk on one NavMesh or the other, since all NavMeshes using the NavMesh Components are bound to an Agent Type.
It’s really important to understand the difference between the NavMesh area and a separate NavMesh.
More info on the manual about it here: https://docs.unity3d.com/Manual/class-NavMeshSurface.html
It is probably more convenient to manage the road as a different NavMesh Area.
Swapping a NavMeshAgent over to totally different NavMeshes requires a NavMeshLink component to allow the agent to traverse between them, but you still have to consider swapping the Agent’s type there which ends up having other ramifications as well (such as possibly inconsistent agent radiuses for the bake).
If you are able to swap to a single NavMesh baked per NavMeshAgent and have the road configured as a different NavMeshArea, you can use **FindClosestEdge **as you were trying to do before.
The example code below requires that you have only 1 NavMesh with multiple NavMeshAreas, configured via NavMeshModifiers / NavMeshModifierVolumes.
However if you do want to keep 2 separate NavMeshes still, FindClosestEdge also accepts a NavMeshQueryFilter which could be used in place of the NavMesh.GetAreaFromName(“Water”) that would find the closest edge on a separate NavMesh as well. You just have to pass it the Agent ID used to bake the second NavMesh.
I set up a scene to replicate it that looks like this:
The blue area is configured to be the Water layer, everything else is Walkable.:
I’ve attached a very simple script to the Agent that shows a button that, when clicked, will make the agent go to the blue area.
using UnityEngine;
using UnityEngine.AI;
[RequireComponent(typeof(NavMeshAgent))]
public class GoToWater : MonoBehaviour
{
private NavMeshAgent Agent;
private void Awake()
{
Agent = GetComponent<NavMeshAgent>();
}
private void OnGUI()
{
if (GUI.Button(new Rect(20, 20, 300,50), "Go To Water"))
{
if (NavMesh.FindClosestEdge(Agent.transform.position, out NavMeshHit hit, NavMesh.GetAreaFromName("Water")))
{
Debug.Log("Found closest edge at: " + hit.position);
Agent.SetDestination(hit.position);
}
else
{
Debug.Log("Could not find closest edge");
}
}
}
}