New NavMesh - how to create rotated LocalNavMeshBuilder [SOLVED]

I have LocalNavMeshBuilder on procedurally generated spherical planet using NavMeshSourceTag. NavMeshes are generated correctly on north pole (Y axis pointing up), but not for other positions (differently rotated axes).

I know that NavMeshSurface can create correct NavMeshes on arbitrary rotated gameobjects, but rotating gameobject with LocalNavMeshBuilder does not work well.

Should I rotate gameobject with NavMeshSourceTag? It is hardly achieveable for me, as I would need to rotate gameobject and couter-rotate its mesh that I receive from a terrain engine.

Is there any other way to supply rotation or up direction to LocalNavMeshBuilder or NavMeshSourceTag?

Thank you for all answers.

Update: I’ve tried rotating object with NavMeshSourceTag and navmesh was always oriented with Y axis at the top, so this is definitely not the solution.

My question remains: How can I make LocalNavMeshBuilder to make arbitrary rotated navmeshes just as NavMeshSurface does in 3_free_orientation example?

Hi! You will need to change the code to set the rotation of the NavMeshData object before building the NavMesh. This means adding something like this m_NavMesh.rotation = Quaternion.AngleAxis(41, Vector3.forward); any time before NavMeshBuilder.UpdateNavMeshDataAsync(…) or NavMeshBuilder.UpdateNavMeshData(…) are called.

The NavMeshSurface takes the rotation from its game object when the NavMesh gets built with this call

var data = NavMeshBuilder.BuildNavMeshData(GetBuildSettings(), sources, sourcesBounds, transform.position, transform.rotation);

This effectively creates a NavMeshData object, sets its position and up-vector orientation and then calls UpdateNavMeshData(…).

Please see also the documentation pages for NavMeshData and NavMeshBuilder.BuildNavMeshData .

Hi adriant,

Thank you for your answer. I’ve tried your proposed solution. I have 5 randomly generated LocalNavMeshBuilders in the scene, and one of them showed generated terrain, but wrongly oriented. See attached screenshot. Should I somehow alter the way terrains are displayed to affect their rotation?

Other 4 have no terrain displayed at all.

This is what I’ve done:

void UpdateNavMesh(bool asyncUpdate = false)
{
  NavMeshSourceTag.Collect(ref m_Sources);
  var defaultBuildSettings = NavMesh.GetSettingsByID(0);
  var bounds = QuantizedBounds();

  m_NavMesh.rotation = transform.rotation;  // I've added this line
  if (asyncUpdate)
    m_Operation = NavMeshBuilder.UpdateNavMeshDataAsync(m_NavMesh, defaultBuildSettings, m_Sources, bounds);
  else
    NavMeshBuilder.UpdateNavMeshData(m_NavMesh, defaultBuildSettings, m_Sources, bounds);
}

Do you have any clue, what I do wrong?

When the NavMeshData needs to be aligned with the originating geometry then it has to be added to the NavMesh system with the same position & rotation with which it was built. Try this in your code:

        if (m_NavMesh.rotation != transform.rotation)
        {
            m_NavMesh.rotation = transform.rotation; // I've added this line
            m_Instance.Remove();
            m_Instance = NavMesh.AddNavMeshData(m_NavMesh, m_NavMesh.position, m_NavMesh.rotation);
        }

You get freedom for where to place your NavMesh data in the world. Multiple instances of the same NavMeshData can be used by the NavMesh system in various locations and with whichever orientation you need.
As a side note, changing the position or rotation of the NavMeshData will trigger a full build of that nav mesh, unlike just moving/changing the bounds which doesn’t recompute the nav mesh in unchanged areas.

Please keep in mind though that the bounds passed to UpdateNavMeshData() are local to m_NavMesh. This means that for the LocalNavMeshBuilder class at least the bounds’ center needs to be adjusted. Try adding this in QuantizedBounds():

        if (m_NavMesh)
        {
            var nmMatrix = Matrix4x4.TRS(m_NavMesh.position, m_NavMesh.rotation, Vector3.one);
            center = nmMatrix.inverse.MultiplyPoint(center);   // from world to local space
        }

And make sure to adjust the gizmos’ transform accordingly in OnDrawGizmosSelected() with:

            Gizmos.matrix = Matrix4x4.TRS(m_NavMesh.position, m_NavMesh.rotation, Vector3.one);

Thank you adriant, it seems that it solved the issue.

Great! You’re welcome, Martin. I’m glad it helped.