godotengine / godot

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

NavigationAgent colliding with walls when rounding corners and avoiding collisions #60354

Closed xix-xeaon closed 2 years ago

xix-xeaon commented 2 years ago

Godot version

v3.5.beta4.official [b6968ab06]

System information

Linux

Issue description

The NavigationAgent takes "shortcuts" and travels outside of the navigation mesh when it turns around things. This then causes it to collide with static geometry. It's especially problematic with corners of walls but it also happens with round things like trees. This also happens when it tries to avoid colliding with dynamic obstacles.

The issue can be mitigated by reducing _target_desireddistance, but it also causes the NavigationAgent to get stuck (around 0.2 it seems) and will only give it's current position as the _nextlocation. I don't necessarily want such robotic movements either. It also doesn't help for collision avoidance. NavigationAgents frequently run out of the navigation mesh and thus into walls in order to "avoid" collisions.

Basically, the NavigationAgent shouldn't leave the navigation mesh.

Steps to reproduce

image

The partially transparent red enemy is seeking the green player. Yellow is the _nextlocation. Even though the enemy only has a 0.5 radius the navigation here is baked with 0.9. As you can see, the enemy is well outside the navigation mesh and about to collide with the corner of the gray cube.

Minimal reproduction project

No response

Scony commented 2 years ago

@xix-xeaon could you please provide MRP?

smix8 commented 2 years ago

Without a minimal reproduction project here are my guesses what is wrong here with navigation or expectations.

The navigationmesh is baked with the agent_radius and agent_height setting from the NavigationMesh Resource in the NavigationRegion3D. The NavigationAgent3D radius has nothing to do with it and only counts for the RVO avoidance.

The RVO avoidance does not consider navmesh bounds or level geometry. This is a known, real issue. See https://github.com/godotengine/godot-proposals/issues/4522 what could solve it. The best workaround for now is to place manual NavigationObstacles for the agents that use avoidance.

Shortcuts are encountered if the target_desired_distance is too large for the baked navmesh settings. The path itself is usually far more detailed when baked with default settings. Agents skip multiple pathindex on each physic tick and NavigationAgent.get_next_location() call when the distance is set way to high.

With current 3.5 NavigationAgent update_navigation() code agents can get stuck in an endless update loop when the distances are set too small for the current NavigationMesh bake detail and the used distance check functions. They constantly think they need to refresh the path but the NavigationServer is unable to provide a better path with more detailed pathpoints for such small distances so agents start to run in small circles.

The NavigationAgent.target_desired_distance is not intended as a parameter to simulate steering behavior around corners. User custom movement code is. Same for smoothed pathpoints to get more realistic curve movement around corners if wanted.

Also there is a limit of 1 update for an agent each physics frame. Multiple calls to NavigationAgent3D.update_navigation() do nothing and are blocked until the next physicsframe. If users call update_navigation multiple times in a frame, e.g. cause a script runs in _process(), only the first call goes through. I guess this was done cause the agent position needs to be synced with physicsspace.

smix8 commented 2 years ago

Can be closed due to no MRP and response and this is clearly not a bug but a setup issue explained above. The desired distance is set way to high which creates all these mentioned problems and that the avoidance does not follow navmesh is documented.