Character walks out of walkable NavMesh when seeking target

Wengang

New member
I have trouble with AI agent character seeking target. I tried to reproduce it with this simple scene:
scene and behavior.png
  • capsule: UCC generic character, Third Person Movement, with Behavior Tree and Nav Mesh Agent.
  • green ball: target Game Object
  • orange platform: navigation static game object, walkable, no OffMeshLink
  • big white plane: navigation static Game Object, not walkable
The capsule's behavior is very simple, it keeps seeking the target. What I expect is that the capsule moves towards the target ball and stops at the edge of the orange platform because the white plane is not walkable,. I played the scene, everything worked fine, the capsule moved towards the target and stopped at the edge.

running 1 platform.png

But the problem is that if I added another platform (same as the first one, nav static and walkable) to the scene, baked NavMesh again and played the scene, the capsule moved straight out of the platform and didn't stop at the edge. If the capsule is selected, we can see that a cylinder frame (representing the NavMesh agent?) stoped at the edge.

running 2 platforms.png

In my game the capsule is an enemy, the green ball is the player, the big grey plane is water or something, and only the player can move on it, the orange platforms are ground that the enemy may patrol on them. If the player is seen by the enemy, the enemy starts moving towards the player. But if the player jumps into the water, the enemy stops by the water. The game doesn't matter. I just want to explain why I'm creating a scene like this.

So any advice? Thanks!
 
The character moves according to the movement specified by the NavMeshAgent. Have you tried a regular NavMeshAgent to see if the problem is there as well? If it is then it's related to the pathfinding logic and you could try A* Pathfinding Project.
 
The character moves according to the movement specified by the NavMeshAgent. Have you tried a regular NavMeshAgent to see if the problem is there as well? If it is then it's related to the pathfinding logic and you could try A* Pathfinding Project.
I tried a regular NavMeshAgent and it works fine. Thanks for the quick reply!
regular.jpg

Code:
using UnityEngine;
using UnityEngine.AI;

public class NavTest : MonoBehaviour
{
    [SerializeField] Transform _target;

    NavMeshAgent _navMeshAgent;

    void Start()
    {
        _navMeshAgent = GetComponent<NavMeshAgent>();
        _navMeshAgent.SetDestination(_target.position);
    }

    void Update()
    {      
    }
}
 
when I move SetDestination to the Update loop, the regular NavMeshAgent has the problem too!
C#:
void Update()
{
    _navMeshAgent.SetDestination(_target.position);   
}

So, I guess the problems is related to how the seek action or SetDestination method is executed. Then I changed back to the capsule with behavior tree and removed the Repeater in the tree, just do seek action once, and the capsule stops at the edge now!

Screenshot 2022-06-02 at 12.28.39.png

Does this mean we shouldn't call seek or SetDestination in every loop with NavMeshAgent?
 
That's interesting - thanks for looking deeper into it!

This seems like a bug within the NavMeshAgent - you should be able to call SetPosition and have it return the same results no matter where it is called from. Can you submit a bug report to Unity? Beyond that you could try using the A* Pathfinding Project and see if you get more consistent results.
 
That's interesting - thanks for looking deeper into it!

This seems like a bug within the NavMeshAgent - you should be able to call SetPosition and have it return the same results no matter where it is called from. Can you submit a bug report to Unity? Beyond that you could try using the A* Pathfinding Project and see if you get more consistent results.

I did more test on this problem. I found I only need to adjust two parameters to avoid this problem.

First, increase Motor Rotation Speed. Some movement types (like Third Person Adventure) need a turning radius to make a turn. If the AI Agent happens to be standing on the platform edge, it falls down.

Second, increase Stopping Distance of NavMeshAgent and Arrived Distance of NavMeshAgentMovement ability. By doing so, a safe margin can be left. I took a look at the source code of NavMeshAgentMovement.

C#:
if (m_NavMeshAgent.remainingDistance > 0.01f) {
    // update m_InputVector and rotation
}

In the Update method, m_NavMeshAgent.remainingDistance is used to decide whether to update the input vector and rotation. But it only works in ideal conditions, i.e., the destination is within the walkable area. If the destination is out of the walkable area, the NavMeshAgent stops at the edge, then the value of remainingDistance may be slightly higher than 0.01f, like 0.016, 0.019, etc. So the input vector keeps updating and the AI agent doesn't stop walking.

Finally, I use m_NavMeshAgent.stoppingDistance instead of 0.01f to do the check:

C#:
if (m_NavMeshAgent.remainingDistance > m_NavMeshAgent.stoppingDistance) {
    // update m_InputVector and rotation
}

In my screenshot above, the Stopping Distance was set to 0, this will definitely cause problems. So I simply gave it very large margin, like 0.5f. It works great! I don't know if I understand this correctly but I'm happy with the result so far. :)

A* Pathfinding Project looks very powerful, I will definitely give it a try. It would be great if it had clean and easy to understand APIs. NavMeshAgent is too difficult to understand.
 
Last edited:
Top