godot
godot copied to clipboard
Add navigation layers to `AStar2D`, `AStar3D`, and `AStarGrid2D`
Adds navigation layers to AStar2D
, AStar3D
, and AStarGrid2D
. By default, all points will be on layer one and all functions that now take a layer argument will default to layer 1, so existing implementations should not be impacted.
AStar2D::add_point
and AStar3D::add_point
now have an optional argument to specify the layer bitmask when adding the point.
get_id_path
, get_point_path
for all support specifying a layer to use. Points that are not on that layer are ignored for pathfinding, as if they were disabled. This also means you can actually disable a point if you set it's layer to 0, but I kept the disabled functionality as a way to disable a point for all layers and preserve the point's layer data at the same time.
get_closest_point
for AStar2D
and AStar3D
will respect the provided layer, and only return the closest point with the matching layer.
AStarGrid2D
seems to constantly remake the points whenever you call update. I believe this will wipe out any custom layers you set as well, which may be an issue and should maybe be mentioned in the docs? I couldn't think of a way to preserve this data given the update function first clears all points. Open to suggestions on this!
Rational:
Instead of having to make duplicate AStar objects if some agents have slightly different path options, you can now use the same overall map data for 32 distinct path options. This greatly simplifies code for users. For example, in my project the map is the same once generated but some units can only travel on some tiles. Water tiles, for example, cannot be traversed by land units and vice versa. Air units can traverse all types. Previously I've had to use 3 separate AStar objects and switch which one I am using based on the unit. After adding layers, I can just specify which layers the points on are to represent land, sea, air during generation, and then for pathfinding specify which layers the agent uses and use one map instead of duplicating the entire thing.
Example:
Download: astar_test.zip
This project features two agents, a Red and Blue. The Red and Blue tiles can be traversed only by those agents respectively. The project also has use UI elements to view the layers of the point the mouse is over and showcase the get_closest_point
function respecting the layer option. It pulls the layer from the currently selected character in the option box.
By default all "open" tiles have been set to layer 2 and 3 (so the value will display 6). Gray "obstacle" tiles are set to layer 0. The red character is on layer 3 (value 4) and the blue character is on layer 2 (value 2). Towards the end, you can that I have my mouse over tile 6,7 (id 497) but the "closest point" in the UI is "496" as that tile is on a different layer from the red character.
Outstanding questions:
- I noticed some of the physics layer implementations have a distinct
mask
andmask_value
function, where the former takes a bitmask and the later takes a layer as an int 1-32. Should I mirror that and have two functions, one to change the bitmask directly and one to specify the layer? Setting layer by direct int is a bit easier, but would not support multiple layers for "shared" points, so I'm not sure if that extra function would be considered a nice utility or just bloat. - What should we do about
AStarGrid2D::update
wiping out any saved layer changes? Just add a documentation note about it? Change that function to remember all the layers for all points and somehow reapply them?
Previous questions, leaving here for community knowledge reasons
- I need to add the compat functions, but I am not sure the proper procedure when a function already has one. I added one for
get_id_path
andget_point_path
in a previous PR, and this one will be modifying those functions again. Is the correct approach to entirely remove those old compat methods and replace them with the new ones, or do I create separate compat functions and bind them again? I couldn't find a clear instruction on this. -> I was told they get additional ones, which I have now added.
Closes: https://github.com/godotengine/godot-proposals/issues/5188