Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add NavigationServer NavMesh and NavMeshInstances #6317

Open
Tracked by #73566
smix8 opened this issue Feb 18, 2023 · 0 comments
Open
Tracked by #73566

Add NavigationServer NavMesh and NavMeshInstances #6317

smix8 opened this issue Feb 18, 2023 · 0 comments

Comments

@smix8
Copy link

smix8 commented Feb 18, 2023

Describe the project you are working on

Godot Navigation.

Describe the problem or limitation you are having in your project

NavigationMesh and NavigationPolygon are Resources used to hold navigation mesh data inside the SceneTree.
Resources by default use shared data until made unique / duplicated in Godot.

If you have two NavigationRegion3D that use the same NavigationMesh resource you only have one data copy for both of them.
If you have a TileMap with 10000 cells that all use the same NavigationPolygon you still have only one data copy for all of them.

The problem is that Resource reuse and data sharing is not supported by the NavigationServer.

Every navigation region commits its NavigationMesh or NavigationPolygon to the server individually and creates its own unique data on the server. If you use the same TileMap with 10000 cells you end up with 10000 unique navigation polygons on the server.

While not the only reason it is one of the bigger reasons why larger TileMaps or GridMaps have so many performance issues with navigation runtime changes. They are currently creating a ton of redundant data on the NavigationServer that requires a lot of extra processing that is not needed.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

The NavigationServer should support reuse of the same data from a shared NavigationMesh / NavigationPolygon resource.

Not only allows this the same data sharing as with the Resources but it also allows the NavigationServer to do internal optimizations when synchronizing or other processing, e.g. it only needs to process the polygons of a unique navmesh once cause every navmesh instance that uses a copy of the same navmesh will have the same polygons.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

The NavigationServer should have a NavMesh and NavMeshInstance class with their own RID so it can hold navigation mesh data internally on the server with the NavMesh and share it with many other NavMeshInstances similar to how e.g. meshes are handled by the RenderingServer with base and instance.

The NavigationMesh and NavigationPolygon Resources will create the unique NavMesh RID so it can be received with the get_rid() function by users like with many other resources. The NavigationRegion2D or NavigationRegion3D will only create and use NavMeshInstances that use the NavigationMesh / NavigationPolygon RID as their base.

Both NavigationMesh and NavigationPolygon receive a commit_changes() function that syncs changes with the NavigationServer NavMesh. This will only be ever needed to be called manually when doing procedural navigation as all other functions or processes like 3D navigation mesh baking do this automatically.

Ideally both NavigationPolygon and NavigationMesh would stop using local vertices and polygon data arrays on the resources at runtime and instead only load them from the resource once, send it to the server and remove the now redundant local copy. This would make them work similar to how meshes store all data on the RenderingServer and GPU where it is actually needed and used. Large navmeshes can have a problematic memory footprint when constantly duplicated and especially the NavigationPolygon keeps even another data copy on top from the internal wrapped NavigationMesh.

Server and Resource API

For the most part this will be a copy how Godot already handles Mesh Resources.

The API for NavigationServer and NavigationMesh / NavigationPolygon could look like this.

# Example with NavigationServer API
var navmesh_rid : RID = NavigationServer3D.navmesh_create()

var navmesh_arrays : Array = []
navmesh_arrays.resize(NavigationServer3D.NAVMESH_ARRAY_MAX)

var vertices : PackedVector3Array
var polygons : TypedArray[PackedInt32Array]
var enter_costs : PackedFloat32Array
var travel_costs : PackedFloat32Array

assert(polygons.size() == enter_costs.size() or enter_costs.size() == 0)
assert(polygons.size() == travel_costs.size() or travel_costs.size() == 0)

navmesh_arrays[NavigationServer3D.NAVMESH_ARRAY_VERTICES] = vertices
navmesh_arrays[NavigationServer3D.NAVMESH_ARRAY_POLYGONS] = polygons
navmesh_arrays[NavigationServer3D.NAVMESH_ARRAY_ENTERCOSTS] = enter_costs
navmesh_arrays[NavigationServer3D.NAVMESH_ARRAY_TRAVELCOSTS] = travel_costs

NavigationServer3D.navmesh_update_from_arrays(navmesh_rid, navmesh_arrays)

var navmesh_instance_rid : RID = NavigationServer3D.navmesh_instance_create()

NavigationServer3D.navmesh_instance_set_navmesh(navmesh_instance_rid , navmesh_rid)
NavigationServer3D.navmesh_instance_set_transform(navmesh_instance_rid , Transform3D())

var navregion_rid : RID = NavigationServer3D.region_create()
NavigationServer3D.region_add_navmesh_instance(navregion_rid , navmesh_instance_rid)
NavigationServer3D.region_remove_navmesh_instance(navregion_rid , navmesh_instance_rid)
# Example with NavigationMesh
var navigation_mesh : NavigationMesh = NavigationMesh.new()

navigation_mesh.clear()

navigation_mesh.set_vertices(vertices)
navigation_mesh.set_polygons(polygons)
navigation_mesh.set_enter_costs(enter_costs)
navigation_mesh.set_travel_costs(travel_costs)

navigation_mesh.commit_changes()

var navmesh_rid : RID = navigation_mesh.get_rid()
var navmesh_arrays : Array = NavigationServer3D.navmesh_get_arrays(navmesh_rid)

var vertices = navmesh_arrays[NavigationMesh.ARRAY_VERTICES]
var polygons = navmesh_arrays[NavigationMesh.ARRAY_POLYGONS]
var enter_costs = navmesh_arrays[NavigationMesh.ARRAY_ENTERCOSTS]
var travel_costs = navmesh_arrays[NavigationMesh.ARRAY_TRAVELCOSTS]

If this enhancement will not be used often, can it be worked around with a few lines of script?

No, those are server and resource internals that users have no access.

Is there a reason why this should be core and not an add-on in the asset library?

Navigation is core.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants