Oxidized Navigation
Tiled Runtime Nav-mesh generation for 3D worlds in Bevy. Based on Recast's Nav-mesh generation but in Rust.
Takes in Parry3d colliders that implement the OxidizedCollider trait from entities with the NavMeshAffector component and asynchronously generates tiles of navigation meshes based on NavMeshSettings. OxidizedCollider implementations for Bevy Rapier3D and Avian 3d are included under the rapier and avian features.
Quick-start:
Nav-mesh generation:
- Choose which backend you're going to use (bevy_rapier3d, avian_3d, or custom parry3d based colliders) and enable the relevant crate features (
rapier,avian, orparry3dfeatures). - If you opted for custom parry3d colliders, implement the
OxidizedCollidertrait for your collider component that wraps aparry3d::shape::SharedShape. This is already done forbevy_rapier3dandavian_3d. - Add
OxidizedNavigationPluginas a plugin. (eg. for avianOxidizedNavigationPlugin::<Collider>::new(NavMeshSettings {...}) - Attach a
NavMeshAffectorcomponent and a collider that implements theOxidizedCollidertrait (already implemented forbevy_rapier3dandavian_3d) to any entity you want to affect the nav-mesh.
At this point nav-meshes will be automatically generated whenever the collider or GlobalTransform of any entity with a NavMeshAffector is changed.
Querying the nav-mesh / Pathfinding:
- Your system needs to take in the
NavMeshresource. - Get the underlying data from the nav-mesh using
NavMesh::get. This data is wrapped in anRwLock. - To access the data call
RwLock::read. This will block until you get read acces on the lock. If a task is already writing to the lock it may take time. - Call
query::find_pathwith theNavMeshTilesreturned from theRwLock.
Also see the examples for how to run pathfinding in an async task which may be preferable.
FAQ
I added the
OxidizedNavigationPluginto my app and now it won't compile.
You need to use OxidizedNavigationPlugin::<Collider>::new(NavMeshSettings {...}, where Collider is either a rapier or avian Collider, or your own custom collider that implements the OxidizedCollider trait. This is necessary to allow us to be generic over different Collider components.
When enabling XPBD, I get the error "You must pick a single parry3d feature."
You need to disable the default parry_016 feature as XPBD uses a different version of Parry3d.
A version of Parry3d needs to be enabled by default for the crate to be compilable & publishable.
I don't want to use the Rapier3d or XPBD3d physics engines just to generate a navmesh. How do I create my own
parry3dwrapper component?
You need to create a component that contains a parry3d SharedShape, then implement the OxidizedCollider trait. See the parry3d example for a basic example.
Can I use this with the builtin bevy shapes, or my own custom shapes?
Currently only parry3d colliders are supported, or crates using parry3d colliders. You'd have to write a function to convert your shapes/bevy shapes into parry3d colliders.
Why aren't my Xpbd/Parry3d colliders scaled properly?
You need to manually apply your transform's scale to the Xpbd/Parry3d collider's shape.
My physics crate updated and now my nav-meshes won't generate.
This is due to how dependencies are handled, Oxidized Navigation will only interact with the versions specified in Supported Versions. If you want to use other versions you can make cargo use a different version.
How do I draw the Nav-mesh for debugging?
Debug draw is available behind the debug_draw feature and using the OxidizedNavigationDebugDrawPlugin see usage in examples.
Supported versions
| Crate Version | Bevy Version | Bevy Rapier 3D Version | Bevy Xpbd 3D Version | Avian3D Version | Parry3d Version |
|---|---|---|---|---|---|
| 0.12.0 | 0.15 | 0.28 | unsupported | git-rev-52cbcec (1) | 0.17 |
| 0.11.0 | 0.14 | 0.27 | 0.5 | unsupported | 0.15/0.16 |
| 0.9.0 | 0.12 | 0.24 | 0.3 | unsupported | 0.13 |
| 0.10.0 | 0.13 | 0.25 | 0.4 | unsupported | 0.13 |
| 0.8.0 | 0.12 | 0.23 | 0.3 | unsupported | 0.13 |
| 0.7.0 | 0.11 | 0.22 | 0.2 | unsupported | 0.13 |
| 0.6.0 | 0.11 | 0.22 | unsupported | unsupported | unsupported |
| 0.5.X | 0.10.X | 0.21 | unsupported | unsupported | unsupported |
| 0.4.0 | 0.10.X | 0.21 | unsupported | unsupported | unsupported |
| 0.3.0 | 0.10.0 | 0.21 | unsupported | unsupported | unsupported |
| 0.2.0 | 0.9.X | 0.20 | unsupported | unsupported | unsupported |
| 0.1.X | 0.9.X | 0.19 | unsupported | unsupported | unsupported |
(1)
- Avian3D has yet to publish an official bevy-0.15 release. There will be a 0.12.1 release when they do
- You will need to use a
[patch.crates-io]override for now see MIGRATING - 0.12.0 - The minimum git rev sha supported is 52cbcec
- Newer git revs will possibly (probably) work but are untested with this crate, YMMV 🤷🏼
Using an unsupported Rapier, Xpbd, Avian3d or parry3d version will cause Oxidized Navigation to fail as it tries to get the wrong version of components. In this case you may be able to override which version Oxidized Navigation depends on.
Non-exhaustive TODO-list:
-
Allow creating nav-mesh from meshes (probably add an option to
NavMeshAffector). -
Rebuild all tiles when
NavMeshSettingsare changed. -
Nav-mesh "layers" using different
NavMeshSettings. -
Pathfinding ticket system (Call to pathfinding returns a ticket that one can check later, controlling async pathfinding like this allows us to limit the amount of parallel tasks & prioritize them)
-
Remove
create_nav_mesh_tile_from_poly_meshin favor of creating data in the right format from the start. -
Add local nav-mesh sub-grids that can be used for moving objects (platforms, ships, etc) without needing to regenerate it's interior every update.