so every navmesh surface i bake is approximately 0.1 units above the actual surface it’s representing. The result is that all of my character’s are ‘floating in air’. I noticed that there’s a “Base Offset” variable to help alleviate this problem but before i use it i wanted to know if this was expected behavior and if i should be approaching having navmesh agent’s in some other way.
Also, I know that in the original NavMesh you could bake a HeightMesh to solve this problem but that doesn’t seem to be an option anymore
This lack of the bake height mesh option is the sole reason we are still using the legacy NavMesh workflows instead of the new components. We also have the problem of our characters floating in the air above our terrains without that option.
Note that we don’t care about the height mesh itself - we are only using it because it seems to solve the problem of the nav mesh incorrectly reporting positions ABOVE the terrain from which it was built.
What I’m doing for baking navmeshes is instead of using default terrain or objects, creating a multitude of planes and setting them to the only game objects in the scene as static.
I then bake the navmesh and can position the planes beneath the surface of my terrain or floor. After the mesh is baked, just disable the planes so that they’re invisible and then you have just your navmesh. Perhaps throw them in a parent object named “Invisible Obstacle Course” or something for organizations sake.
This will also keep your nav meshes very small, they bake in about a second for me.
Of course if you’re creating a free roaming or large scale game this wouldn’t work, but if you’re creating a large free roaming game you really shouldn’t be using Unity’s native navmesh system in the first place I feel.
Put this in another thread, but if you’re not too concerned about performance in the short term, you can try a solution which corrects for incorrect height positioning at runtime:
private void CorrectBaseHeight()
{
NavMeshHit navhit;
if (NavMesh.SamplePosition(GameObject.transform.position, out navhit, 10f, NavMesh.AllAreas))
{
Ray r = new Ray(navhit.position, Vector3.down);
RaycastHit hit;
if (Physics.Raycast(r, out hit, 10f, LayerMask.GetMask("Level")))
{
_nav.baseOffset = -hit.distance;
}
}
}
Yes there should be offset control somewhere but agents commonly have a root with all control components including the navmesh agent, anyway, so that root is easy to offset.
Hi astra I’m someone trying to create a free large roaming world why would you recommend not using unity’s native navmesh?What other solution is there instead?
I actually just use Unity’s native navmesh. I’m sure there are better ways of doing it, but this works for what I need.
I just use an offset variable for my npc class.
class NPC {
NavMeshAgent navMeshAgent;
float navMeshOffset;
void Awake() {
navMeshAgent = this.gameObject.GetComponent<NavMeshAgent>();
}
void Update() {
navMeshAgent.offset = navMeshOffset; //Not sure if this is correct off the top of my head
}
}
You’re right about not doing it every frame, but the problem is that when changing between slopes and planes, the situation may actually change every frame.
For me, decreasing the voxel size (= increasing accuracy) solved the issue. The bake time didn’t change notably, but my scenes are also not too complex. I would definitely recommend trying this over changing the offset in every frame.