In my game I have nodes that an agent should navigate to and then do something. The NavMesh, however, does not reach directly to the node position, but only to the table and also a little distance from it. I can pass the node on the table as the target to the NavAgent, but if I do that, it will only navigate to the edge of the NavMesh.
Visually it is then in the right position, but the navigation never “ends” like that, so the navigation_finished event is never sent.
As a solution, I could of course increase TargetDesiredDistance so that “standing near the node” is sufficient to consider the navigation as finished and to receive that signal. However, I then have the problem that the agents always stop too early, even if they could theoretically complete the path at other points (i.e. at targets that are within the NavMesh and are therefore reachable).
You can do a periodic check of the position of your agent, like every 3 seconds compare your last position with your current position. Let’s suppose in a normal situation your agent will move 50 units per second, if some check ends with a distance lesser than the expected, you consider the agent reached the position or its stuck and execute the code you want to do.
How games since ancient times have handled this is, if you have an interactable object you give it one ore more interactable positions around the object that are on navmesh and actually reachable by an agent. Then when an agent should use such an object it queries from that object a free position, maybe also the closest, that it can use and queries a path to that position that is on navmesh.
If you run debug in basically any 3D game with interactables you will see those position around e.g. tables, chairs, ladders, vehicles, and what not …
If you think about what a navmesh does it also makes sense as you are picking navmesh targets, not “visual or physics object” targets because those objects do not even exists as far as the navigation system is concerned so why should it account for any of them.