godotengine / godot

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

3.5b1 navigation agent seems to sometimes bump around an obstacle in a way that feels like a bug #57486

Closed BigZaphod closed 2 years ago

BigZaphod commented 2 years ago

I tried throwing together a very simple test of the navigation with an obstacle in the 3.5b1 build and it seems to behave oddly with the agent sometimes jumping or bumping as if it hit something. I can't tell if I've set this up wrong or am missing something or not, but I assume this isn't expected behavior? I used the blog post as a guide to configuring the agent and obstacle, but I can't rule out that I did something stupid here.

https://user-images.githubusercontent.com/453721/151829697-7bb0130c-8faf-40b3-832e-a413231461cb.mov

The scene tree looks like this:

image

And this is the only script (attached to the player):

extends RigidBody2D

var speed = 100

func _ready():
    $NavigationAgent2D.set_target_location(Vector2(0,0))

func _physics_process(delta):
    if $NavigationAgent2D.is_navigation_finished():
        linear_velocity = Vector2.ZERO
    else:
        var target = $NavigationAgent2D.get_next_location()
        var vel = global_position.direction_to(target) * speed
        $NavigationAgent2D.set_velocity(vel)

func _on_NavigationAgent2D_velocity_computed(safe_velocity):
    linear_velocity = safe_velocity

Full project: Godot3.5NavTest.zip

Originally posted by @BigZaphod in https://github.com/godotengine/godot/issues/48395#issuecomment-1025948922

Scony commented 2 years ago

@BigZaphod the behavior on the video you attached is normal - this is how it looks like when small-radius agent avoids big-radius obstacle.

What do you mean by jumping and bumping? Is that smth else than what one can see on the video?

BigZaphod commented 2 years ago

The video is basically what I was seeing - the results seem to depend a lot on where the obstacles are in relation to each other and sometimes the agent acts like it hits an invisible wall pretty far out from where the obstacle actually is. I guess if that's expected behavior then that's fine, but the sudden velocity change feels so jarring that I assumed it was a bug. Are there ways to mitigate this sort of thing? (And if there are, perhaps it could be fodder for the eventual documentation?)

Scony commented 2 years ago

hits an invisible wall

by default obstacle's radius is estimated from collision shape - as for rectangle, the resulting radius will be big enough to include your rectangular collision shape inside the circle it creates. This leads to the obstacle radius being too big around the corners. You can disable estimation and set something smaller to work around that effect. Also, you can increase agent's time horizon.

nathanielhudson commented 2 years ago

FWIW I just tried this project in 3.5b4.

The pathing looks better - it takes the shorter path around the right of the object instead of the left, and doesn't "suddenly" notice the obstacle anymore. One thing that does still seem to be an issue is that the mob's speed isn't constant, and I'm not sure why. The speed being passed in to $NavigationAgent2D.set_velocity is a constant 100, but the magnitude of safe_velocity sent back to _on_NavigationAgent2D_velocity_computed ranges from 100 to 85-ish. I'm not sure why, especially given that the obstacle is static. You can see this by using OP's project, but adjusting _on_NavigationAgent2D_velocity_computed:

func _on_NavigationAgent2D_velocity_computed(safe_velocity):
    linear_velocity = safe_velocity
    print(round(linear_velocity.length()))

Anything I'm missing?

smix8 commented 2 years ago

The speed is not constant cause the RVO avoidance is a number of circles that apply different forces pushing agents in directions and not a perfect "this is your new path highway" calculation were the agent can run along at maximum speed.

For maximum speed you need to not used the avoidance for (static) objects at all. Instead, bake your navmesh or update your navigationpolygon so the agent is aware of the scene geometry at high detail.

The obstacle avoidance is a last resort intended for objects that are constantly moving as it would be too performance costly in many cases to bake them into a navigationmesh every frame.

nathanielhudson commented 2 years ago

Ah, I see. Thank you for your reply!

(I'm not the issue OP, but I wonder if this should be closed since everything seems to be working as expected)

smix8 commented 2 years ago

It is still open cause, while the current 3.5 navigation documentation "exists", it still misses a lot of information like this.