Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

How does the NavMeshAgent work internally?

Discussion in 'Navigation' started by Multithreaded_Games, Jan 20, 2017.

  1. Multithreaded_Games

    Multithreaded_Games

    Joined:
    Jul 6, 2015
    Posts:
    122
    Hi all,

    Basically, I'm trying to 'recreate' the behavior of Unity's NavMeshAgent without actually having the NavMeshAgent component enabled and 'driving' the character. Without getting too much into why I'm doing this, I'd like to ask if anyone knows how this is done (perhaps a unity dev could chime in).

    Presently, as the character moves around, I'm calling NavMesh.SamplePosition on the character's transform position to check whether the character is 'bound' to the NavMesh and then resetting the position if the character is in a place where there is no navmesh.

    I am curious as to how the Navmesh internally decides to 'not move' the character. Is the position it checks projected slightly ahead of the character or is it the actual character's position itself, which is then reset to the previous 'sampled' location? I have it mostly working correctly but I'm encountering some jitter and occasionally entering locations where I cannot move at all. I'm guessing I need to check the sampled position slightly 'in front' of the character when deciding whether I can move there or not, but I'm curious as to how it's actually being done behind the scenes.

    Thanks in advance!
     
  2. VengeanceDesign

    VengeanceDesign

    Joined:
    Sep 7, 2014
    Posts:
    84
    The Navmesh has a raycast function that will let you see if the path from start to some position is clear.
     
    Multithreaded_Games likes this.
  3. Multithreaded_Games

    Multithreaded_Games

    Joined:
    Jul 6, 2015
    Posts:
    122
    Let me preface though by saying that I am trying to do something fairly unorthodox, which is to 'correct' my physics update with the sampled NavMesh position. This gives me physics when I need it while forcing the character to be planted on the Navmesh. The NavMesh agent is not actually having its position/rotation updated and I'm updating its velocity with controller input (the same as is sent to the Rigidbody) Physics overhead is drastically reduced since a Navmesh mapping is (well, presumably) quicker than physics collisions.

    Either way, the point is that I have this VERY closely working. I've been using NavMesh.SamplePosition and it works 99.9% of the time. However, for whatever hellish reason, it gets 'stuck' on seams and I think that, in general, there is some underlying issue with these seams and there is some internal fudge that allows an positionally updated NavMesh to traverse them usually. I don't know how to describe this but I guarantee that there is something peculiar about these particular 'spots' where SamplePosition can't actually sample them, but instead returns an incorrect position, which locks the character 'closely' into place. As far as I can tell, NavMesh.Raycast has the same problem.

    These seams are entirely dependent on the geometry and I am positive that I am not the only one that has encountered these as I've seen them alluded to in other posts. On very rare occasions, I've seen actual kinematic NavAgents have difficulty traversing them at times as well. For instance, I cannot pass this confluence of weird lines as shown in this picture. When I am moving perpendicular towards the area enclosed by the box, the interior two lines that are closest together cannot be passed in the region in which the lines almost seem to converge.

    I've ruled out a few things: one, it doesn't seem to be a height-based discrepancy, as I'm able to traverse slopes and steps without issue (unless there are these seams.) It also doesn't occur when I am moving at a sufficiently high velocity (IE running.) This makes sense though, since the velocity vector's length while running extends beyond the 'seam', it's able to sample a position beyond the seam. Is it possible that SamplePosition can occasionally sample more than one 'closest' position at the same distance simultaneously and just 'picks' one?

    I've also tried FindClosestEdge, which actually only returns exterior edges, so no seams. I've also tried playing with building/clearing the height mesh, increasing the voxel size (which does help actually, but ultimately still results in seams, even when cranking it up way higher than I should.), different positional offsets, search radii size and area masks, and still cannot figure out a way to get the actual sampled position when moving over these problem areas.

    I could really use someone who has some in-depth knowledge of the NavMesh system to chime in here, because honestly, I'm at a complete loss. Thanks!
     

    Attached Files: