godotengine / godot

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

2D Navigation Polygons are being handled differently than what's being displayed. #81017

Closed TheFoxKnocks closed 10 months ago

TheFoxKnocks commented 1 year ago

Godot version

v4.1.stable.official [970459615]

System information

Godot v4.1.stable - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 3080 (NVIDIA; 31.0.15.3623) - 12th Gen Intel(R) Core(TM) i9-12900KF (24 Threads)

Issue description

I genuinely don't want to make a blank project for this, so excuse some of the fluff.

Let's say you have a NavigationRegion2D with a complex shape:

navpoly1

Now, let's say you have a bunch of nodes you want to spawn in, but limit them to the shape of the NavigationRegion2D. In my case, enemies, which I will represent with simple red dots later:

    while not Geometry2D.is_point_in_polygon(spawn_position, navagent.navigation_polygon.get_vertices()):
        x1 = 0
        y1 = 0
        x2 = 4000
        y2 = 4000
        random_x = randi_range(x1, x2)
        random_y = randi_range(y1, y2)

        spawn_position = Vector2(random_x, random_y)

With the "navagent" being the NavigationRegion2D shown above. Essentially, create a large rectangle, and checking to see if the randomly generated location chosen within is also inside of the NavigationRegion2D.

Now, for demonstration purposes, I turn on this being visible in-game and attempt to spawn in 2,000 enemies all at once. Here are 2 screenshots. Both have a similar problem, but the 2nd screenshot was me redoing the polygons of the NavigationAgent2D to see if I got different results - and I did:

navpoly2

navpoly3

What's happening here is that the Navigation Polygon arrangement being utilized is not representative of what's being shown to me. What I see is a perfectly useable, if not slightly complex large region. What the engine sees is intersecting polygons carving out bit swathes of space as it creates an arrangement much more complex than what I actually did in the engine.

If this is intended behavior, that would be immensely confusing and I'd be interested in hearing why what I'm seeing is not what I'm getting in this case.

Steps to reproduce

Described above.

Minimal reproduction project

Will not be provided.

smix8 commented 1 year ago

A navigation mesh is build with polygon indices, not just vertices.

TheFoxKnocks commented 1 year ago

A navigation mesh is build with polygon indices, not just vertices.

Then what would be the proper way to approach this using NavigationRegion2D? I know there's solutions that don't involve NavigationRegion2D specifically, but in the spirit of figuring out what the problem is, or if there even is one, I'd be curious to know.

smix8 commented 1 year ago

If you want to use Geometry2D functions, which for the most part expect outline arrays, you would need to find the navigation mesh outline edges first and then bring the positions in order to form an array that the function understands.

A more accurate way to place random positions on a navigation mesh would be to weight the area size of the polygons e.g. like pr https://github.com/godotengine/godot/pull/75098 does.

smix8 commented 11 months ago

If there are no further questions I think we can close this issue.

smix8 commented 10 months ago

Closing but feel free to reply if there are still questions.