-
-
Notifications
You must be signed in to change notification settings - Fork 21.6k
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
Navigation design does not align with the rest of the engine #102204
Comments
For point 4, what would be in the resource for |
True, the navigation link in its current from probably should not have a resource attached. The point still stands for the obstacle though. Personally I would like to see more complex options for links though where the entry and exit points could be generic shapes/areas to allow marking cliffs with jump links for example. |
For |
I would say it's more similar to an Area or Collider though. Given that an obstacle would usually also have some form of collision and both of those use |
Both |
The underlying issue though is that this blows up the scene files quite a bit. Especially during development when they are all stored as Text. With obstacles you will probably have quite a few that use the same shape so not being able to store them in a common resource can be quite an issue. I had to implement my own resource for this because I had scene files approaching 100mb and take way too long to load. |
That's a valid point, but I'd say very much outside the scope of a discussion about aligning the navigation code with other parts, as this is not a discrepancy, I think that idea would be best as a feature proposal on its own, or it'll drown in other topics |
Imo this breaks locality of relevance and makes things pretty convoluted, what if you want a whole bunch of different nodes to share one behavior? How would yo make them all use the same code easily without a lot of boilerplate code? You'd also have to add it to a bunch of nodes that otherwise wouldn't have any script attached Meanwhile you can make it do that by calling such a method on your node, by just making a dedicated callable for that |
Not really seeing the issue here to be honest. The precedent has already been set with how collision data is generated and nothing is stopping you from implementing some generic parsing logic and calling that from the proposed
Is not really a lot of boilerplate. It's actually even less boilerplate than the current implementation which requires you to first allocate a parser, then set the callback and finally also take care to free that parser. Also not like the current implementation doesn't already use a similar solution as well: godot/scene/3d/physics/static_body_3d.cpp Lines 153 to 154 in 9ee1873
godot/scene/3d/physics/static_body_3d.cpp Lines 161 to 162 in 9ee1873
godot/scene/3d/physics/static_body_3d.cpp Lines 145 to 146 in 9ee1873
godot/scene/3d/physics/static_body_3d.cpp Lines 137 to 138 in 9ee1873
If anything the current implementation encourages breaking separation of concerns by allowing parsing of all kinds of different nodes in a single function no matter if they use the same logic or not. Also the current implementation does not allow you to reuse any of the existing parsing logic as it is all C++ only. I already had this issue with the previous implementation where I had to copy the code for parsing convex shapes since the code for that was private inside the Additionally the current implementation has one big issue and these two functions where actually what triggered me to write this issue in the first place. If I inherit from godot/scene/3d/mesh_instance_3d.cpp Line 864 in 9ee1873
MeshInstance3D . So if I wanted to return a simplified mesh for navmesh baking I could do that but I wouldn't gain anything from that because the default parser would still be called and add the complex geometry. This is both unintuitive and inflexible.
Why? How would your custom nodes have any relevant parsing logic if they do not even have any custom properties? I mean sure you could contrive some esoteric example where your source geometry parser generates something based on the node name. But why would you do that externally and not in the nodes script? To throw your own words back at you "Imo this breaks locality" |
If we're comparing with the physics engine it does use callbacks, not virtual methods, for callbacks that is, complex behavior that requires data to be fed in and out But I can see various contexts where not calling a method on a node would make sense for the geometry parser, for example just doing something like adding extra margins or some other filtering or parsing But a callback is the most balanced position IMO, where you can choose to call a method on the node itself, or do something else, having a virtual method on the class is IMO really limiting the flexibility |
Please move to a proposal discussions. This has no qualifiers for being in the issue tracker. |
This is discussing defects with the current implementation though. Not proposing any new features, I mean I guess adding the ability to replace the
Where exactly can I register a callback with the physics system that gets called for every node it needs a collision shape for? Cause the editor functionality to create a collision shape from a mesh is using virtual functions here: godot/editor/plugins/mesh_instance_3d_editor_plugin.cpp Lines 65 to 69 in 9ee1873
I would say baking a navigation mesh is pretty similar in functionality. The only callbacks in the physics server are acting on specific instances and are not generically called for every physics object registered with the server.
Please give an example of where a global callback getting called for every node without any way of preventing that is somehow more flexible than a virtual function you can customize for all your custom node types. Same as the global method choosing to call a method on the node itself or not, the method on the node can choose to call a global method or not and additionally can choose to extend on the functionality already present or replace it entirely. |
Tested versions
4.x
System information
Issue description
The current design of the navigation system exhibits significant inconsistencies compared to the rest of the engine. These inconsistencies hinder flexibility, extensibility, and alignment with established patterns in the engine's architecture. Below are the key issues and proposed resolutions.
1.
NavigationServer
The
NavigationServer
is implemented in a way that discourages modularity and alternative implementations. The core implementation resides in a module, but it doesn't allow for easy substitution or extensibility. Unlike other servers, which permit registration of alternatives, theNavigationServerXDManager
only supports a default navigation server. Custom implementations require deactivating the default module during the build process and can not be implemented via GDExtension. This should be brought in line with other servers such as thePhysicsServer
.2.
NavigationMesh
The
NavigationMesh
API forces the navigation system to conform strictly to the recast paradigm. Custom implementations (e.g., navigation volumes, voxel octrees, or simple navigation graphs) are impractical due to the hard dependency on theNavigationMesh
. Even replacing theNavigationServer
with a custom implementation still requires inheriting from the defaultNavigationMesh
. In contrast thePhysicsServer
for example just uses a genericShape
RID
and does not rely on any specificShape
in its API.3.
NavigationRegion
In it's current form this is really just a
NavigationMeshInstance
seeing as a region can not have more than one mesh assigned in any case, based on point 2 this should just be a generic resource likeShape
that does not rely on any specific underlying implementation.4.
NavigationObstacle
andNavigationLink
These nodes deviate from the engine's resource management conventions. The rest of the engine always keeps the data in a
Resource
class and then adds it to the scene tree with an instance class that holds the resource. SeeMeshInstanceXD
andMesh
,CollisionShapeXD
andShapeXD
,PathXD
andCurveXD
etc.5.
source_geometry_parser_create
andsource_geometry_parser_set_callback
The newly implemented geometry parsing mechanism is overly complicated and diverges from established systems. Functions like
source_geometry_parser_create
andsource_geometry_parser_set_callback
require static functions and resource management and are inconsistent with the design of similar systems in the engine. This could be much simpler by adding a virtual function_parse_source_geometry
toNode2D
andNode3D
similar togodot/scene/3d/visual_instance_3d.h
Line 205 in 9ee1873
godot/scene/3d/visual_instance_3d.h
Line 65 in 9ee1873
navigation_layer
property similar togodot/scene/3d/physics/collision_object_3d.h
Line 48 in 9ee1873
_parse_source_geometry
and be done with it.Conclusion
The navigation system would greatly benefit from adopting the engine's established design principles. Refactoring these components to align with the rest of the engine will improve modularity, flexibility, and developer experience.
Steps to reproduce
Minimal reproduction project (MRP)
The text was updated successfully, but these errors were encountered: