godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.99k stars 21.17k forks source link

NavigationAgent3D loses velocity and starts orbiting around other NavigationAgent3D when changing "target_position" #78986

Closed enxas closed 1 year ago

enxas commented 1 year ago

Godot version

v4.1.rc.mono.custom_build [e044e13d5]

System information

Godot v4.1.rc.mono (e044e13d5) - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1660 Ti with Max-Q Design (NVIDIA; 31.0.15.3640) - Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz (12 Threads)

Issue description

Properly working Godot v4.1.rc2.mono.official [46424488e] shows controlled NavigationAgent properly snapping to target position when next to another NavigationAgent :

https://github.com/godotengine/godot/assets/8630984/86361c1b-1649-4080-a7e1-b89fcbb6c3e9

After this PR #78857 in Godot v4.1.rc.mono.custom_build [e044e13d5] shows, that when switching target position next to NavigationAgent, controlled NavigationAgent looses velocity and is orbiting around NavigationAgent:

https://github.com/godotengine/godot/assets/8630984/51402f9b-2809-45d2-875d-214681c0cc1c

Steps to reproduce

  1. Run attached MRP
  2. Click space on your keyboard to instantiate NavigationAgent3D
  3. Rapidly click left mouse button to walk around stationary NavigationAgent like shown in the videos to see NavigationAgent oribiting

Minimal reproduction project

MRP_GDScript.zip

smix8 commented 1 year ago

This took me a while to spot but nearly all the problems are more or less caused by the CharacterBody3D node being offset by 1 unit on the y-axis from the navigation mesh "ground" while the collision sphere is lower and the agent properties for distance checks are not adjusting for such a distance. Without collision involved the agent would lower itself to the navigation mesh height while moving "mending" this offset issue but the sphere collision prevents that.

The orbiting is caused by CharacterBody3D collision and a result of the y-axis offset because the agent needs to be super-close to the path point to increase the path index and the position is collision blocked by the other agent. You can increase the path desired distance above 1.0 to "fix" it but this is the wrong fix, the real problem is the large offset of the CharacterBody3D from the navigation mesh "ground" because the NavigationAgent3D uses the parent CharacterBody3D world position.

Regarding the agent not "snapping" to target position, this was always the case. The bug fix from pr https://github.com/godotengine/godot/pull/78850 removed the "drag" velocity that physics had for 1 more frame so it may be more noticeable with certain velocities and distance values.

I am not sure if this removal of the drag velocity should be considered a bug because the old behavior made agents overshoot the target position consistently at higher velocity, so there is no one-size-fits-all and if this should be even handled by the agent internals it should be done with a new segment check, not by bringing the old bug back. Maybe this requires additional documentation as well. The best solution is always if you want to "snap" to the target position to move your agent to that position when very close.

enxas commented 1 year ago

Thank you very much for a detailed explanation. This different behavior should be documented somewhere, because people gonna be confused like me when their agents start acting differently than previously.

smix8 commented 1 year ago

This has turned out to be a unicorn-issue not reported by anyone else since Godot 4.1 release. I don't think it is necessary to be added to the documentation as it is so specific for a version upgrade and a rare case. This issue here might be all the searchable information that is needed.

I think we can close this but feel free to reply if you think there is something actionable to keep this open.