#landmass
2780 messages ยท Page 3 of 3 (latest)
The AABB case I hadn't thought of. I'll need to think about how to handle that one if/when we get streaming assets
I should write that down though
Yes please!
Well we need upstream AABBs for skinned meshes in the first place haha
Fair haha
Bevy currently only uses the AABB of the non-animated mesh, resulting in dramatic culling issues
Greeble's crate just recalculates the AABBs naively AFAIK
But I heard we could also calculate the max AABB extent on animation load and use that
Bit disappointing, but itโs not been an issue for me in practice ๐
I suppose it could become an issue on web, but our asset handling is so beyond wasteful on Wasm that itโs not the real issue
(Wasm cannot return memory)
@sand jasper Andriy did not publish it yet: https://github.com/andriyDev/landmass/tree/main/crates/landmass_rerecast
Yeah I'm gonna release it for 0.17
I can confirm it works though, see https://github.com/janhohenheim/thief_sense_demo for a fairly small demo
does the ground mesh count as obstacle for the mesh3d_backend?
All meshes do
Also, it needs to be an obstacle, otherwise there would be nothing generated on it ๐
the agents are never reporting AgentState::ReachedTarget
my agents have avian colliders so their transform has a offset on Y from the ground, and my targets are on the very surface of the ground, if that matters
@mellow mirage might that be the good old "put agents at feet" thing?
Yeah that sounds right
You can play with the PointSampleDistance3d options in the AgentOptions/ArchipelagoOptions (I renamed it recently)
how necessary is updating Velocity for that calculation?
If you don't update the velocity your agent may often slow down around corners
Also their local collision avoidance between other agents won't work properly
what schedule is best to update Velocity?
it gotta be after an avian schedule right?
i put a huge value on the ArchipelagoOptions (from agent radius of 2.), it fixed a problem where the agent would report being outside of the navmesh when going up the sides of my test half-pipe, but not the problem of them yo-yoing on top of the target
both AgentTarget::Entity and AgentTarget::Point can trigger AgentState::ReachedTarget?
FWIW I personally add the agent as a child of the collider
so that the agent is on the ground
I then use a custom AgentOf relation to link them
See the repo I posted above
having the Collider as the child does not work well?
because avian already has a ColliderOf to link a Collider to the entity with RigidBody
Yes
You can also set the TargetReachedCondition to a better value. But like the agent checks its distance between the end point and the agent point after snapping it to the ground
So it shouldn't need that much tuning?
Updating in post update seems fine. You can also update it in PreUpdate just before landmass runs
the target and the agent
does the target need to have width? because that is just a point in space basicaly
both AgentTarget::Entity and AgentTarget::Point cause the agent to yo-yo on top of the target
TargetReachCondition is required for the state to change to ReachedTarget? what is the meaning of None on each of the distances?
and put the agent at the feet means exactly what? because i was getting more AgentNotInNavMesh with the feet at about 0.025 off the ground compared to when it is on the center of the agents collider at about 0.75
I have my agents flush with the ground.
How is your distance_above and distance_below
the agent is a child positioned so that it is at the same point as the ground when the agent is standing on the ground
In my case, the collider is 1.8 m high and floats 0.1 m above the ground, so I offset the agent by -(1.8 / 2 + 0.1) = -1.0 m from the collider
Can you share all of your ArchipelagoOptions?
from radius 0.5
Is that all?
Ohhhh
This is actually a bug in landmass
I am computing the distance as the distance from the agent's position, not the agent's sampled position.
Thanks for spotting this!
0.17 branch is updated with this now @sand jasper, if you'd like to test it out
i didn't have the TargetReachCondition until my last test of the day though
@sleek scarab would you take a look at this? https://github.com/andriyDev/landmass/pull/164 No pressure if you don't have time. Not sure if I'm forgetting some footguns that we've hit hahaha
@mellow mirage @sleek scarab does this mesh make sense?
Bit hard to tell due to the perspective
Mind trying with bevy_rerecast_editor?
That makes it simpler to see ๐
the green is the agent radius, right? this feels more like agent diameter, i.e. it is too small
The RC is not on crates.io, so you have to do cargo install bevy_rerecast_editor --git https://github.com:janhohenheim/rerecast
Or something like that
@sleek scarab https://crates.io/crates/bevy_rerecast_editor the link to the repo is broken
And add the bevy_remote plugins, I believe theyโre called something like RemotePlugin and HttpsRemotePlugin
Good catch, will fix later ๐
how do you move around the editor, right click only rotates the camera
hold right click and then hit WASD
should probably add that info somewhere ๐
Looks correct to me
if you want it to be more detailed, up the cell size fraction
the one used by the pathfinding in the end is the green one ๐
If you want to exclude the ramp, reduce the walkable climb
the one in the middle is excluded because it happens to have a too high slope
this is using avian backend
so yeah this all looks correct to me!
Also, if you do cargo install bevy_rerecast_editor --git https://github.com/janhohenheim/rerecast you'll get a newer release of the editor
but it will use the 0.17 remote endpoints, no?
The BRP endpoints didn't change in 0.17 AFAIK
I might be wrong though
But I think a 0.17 editor should be able to talk with a 0.16 app
actually, let me try ๐
this is for ledges, not slopes
nvm
don't use the 0.17 editor for 0.16 projects ๐
oh yeah whoops
Yep I need to expose the slope too
adding that to the UI is trivial
If you want, I can publish a 0.16 release later that includes it
The only reason I didn't add all of the params is because I didn't find a way to do it in bevy_ui without a shit ton of boilerplate ;-;
lemme know if you want any other knobs in there
@sleek scarab kek
thread 'Async Compute Task Pool (2)' panicked at /home/hukasu/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rerecast-0.1.1/src/detail_mesh.rs:294:40:
attempt to subtract with overflow
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `bevy_rerecast_core::generator::poll_tasks`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
error: Recipe `navmesh` failed on line 303 with exit code 101
lol
shouldn't these gizmos be blue to indicate that they are from the polygon mesh?
That's the landmass gizmos, right?
ah, yes, bevy_landmass::debug::Landmass3dDebugPlugin::default()
if so, blue = polygon, green = detail is my own convention for rerecast. These are the gizmos that landmass uses, and me and Andriy never put any effort into making sure the colors match between landmass and rerecast haha
but
you can mix the actual rerecast gizmos and landmass gizmos
sec
this is how I like to mix the rerecast and landmass gizmos
ffs, one day i will not click the video x instead of the video player x
hehehe
memory allocation of 396997076744 bytes failed welp
Thatโs a lot
this green gizmo is not tied to the agent radius
@sand jasper alright I have some time now
you needed the slope angle in the 0.16 ui, right?
anything else?
small annoyance on the ui, there is no way to clear a cursor from text boxes, so i end up writing values on the text boxes trying to use keys from other applications
yeah that's crap, I fixed that for 0.17
I'll see if I can backport it ๐
backported the fix
and published
try downloading the new version ๐
sorry that the 0.16 UI looks a bit shit hehe
also added the slope to the 0.17 version
@mellow mirage here's a question for you
yeah these are excellent tips. Hard to come up on the spot with anything else ๐
oh I see
but it would be neat if it was the radius 
Right now it is tied to the agent having a target or not
BTW I forgot how silly the propagation for pointer targets was. I backported the unfocus fix and had to remember that in 0.16 trigger.target() is the current propagation target and trigger.target is the original target
๐ซ
In 0.17 it's .entity and .original_event_target()
or alternatively .event_target() and .original_event_target()
much better
Yeah this doesn't render the agent's radius, just their position. This could be improved. It just draws all landmass points with the same radius
Ah you found that haha sorry
@mellow mirage if I have a landmass agent, does it also need a landmass character in order to do local avoidance?
or is it implicitly a character when it's an agent?
It looks to me like they're doing local avoidance with just the agent
but it's a bit hard to tell
Agents always use local avoidance
nice ๐
is there an utility where i can query which entities are reachable from a point?
The best you can do is Archipelago::find_path currently.
In the future, I might add a more robust reachability check which I could then expose. Right now it fails if some node types have infinite cost (making it unusable by agents)
i cant compile bevy_landmass due to an error on ord_subset
error[E0277]: the size for values of type `L` cannot be known at compilation time
--> /home/hukasu/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ord_subset-3.1.1/src/ord_subset_trait.rs:113:51
|
113 | impl<$($T:OrdSubset),+> OrdSubset for ($($T,)+) where last_type!($($T,)+): ?Sized {
| ^^^^^^^^^ doesn't have a size known at compile-time
...
128 | / tuple_impls! {
129 | | Tuple1 {
130 | | (0) -> A
... |
229 | | (11) -> L
| | - this type parameter needs to be `Sized`
230 | | }
231 | | }
| |_- in this macro invocation
|
= note: required for `(A, B, C, D, E, F, G, H, I, J, K, L)` to implement `PartialEq`
note: required by a bound in `ord_subset_trait::OrdSubset`
--> /home/hukasu/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ord_subset-3.1.1/src/ord_subset_trait.rs:12:41
|
12 | pub trait OrdSubset: PartialOrd<Self> + PartialEq<Self> {
| ^^^^^^^^^^^^^^^ required by this bound in `OrdSubset`
= note: this error originates in the macro `tuple_impls` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
113 - impl<$($T:OrdSubset),+> OrdSubset for ($($T,)+) where last_type!($($T,)+): ?Sized {
113 + impl<$($T:OrdSubset),+> OrdSubset for ($($T,)+) {
|
For more information about this error, try `rustc --explain E0277`.
error: could not compile `ord_subset` (lib) due to 12 previous errors
I know that one! You'll need a patch
for posteriority
[patch.crates-io]
ord_subset = { git = "https://github.com/virtualritz/ord_subset", rev = "c6432c67d3dcf684f37db68d711a7fca2813c29b" }
Yeah I completely removed ord_subset haha
is there any utility to just give me a position within x radius?
Not sure if this is exactly what you mean but there is the sample_point method that can get you a valid point on the navmesh
https://docs.rs/bevy_landmass/latest/bevy_landmass/struct.Archipelago.html#method.sample_point
An archipelago, holding the internal state of landmass.
it would be more like a find_path where you don't input a end_point with a maximum distance
huh yeah, I do not think I have seen anything like that.
like in skyrim they had something like that, where when a player would get close to a fox, the fox would just query any tile 50 units away from the player
ah I see, I doubt there is anything prebuilt for that, you could use sample point with very low tolerances on the distance to make sure that sampled point is very close to that desired radius to see if a point in the radius is valid.
@mellow mirage about to release rerecast for Bevy 0.17
same as the RC, just bumped versions
Awesome, I'll release landmass_rerecast tonight
done 
And now I'm done!
Thank you!
animation link is to mark something like you can jump from this point to this other point?
between islands also?
Yup exactly!
how do you make other entities always open way for another? like, this dude will fuck you up if you stay on its way
Play with their avoidance responsibility. Lower avoidance responsibility means they won't try to avoid other characters as much
@sleek scarab which settings should i change when i get invalid contour?
Uuuh good question, I donโt know by heart. I think the max contour simplification error?
i didn't play with all nobs, but increasing cell_size_fraction worked, my guess is that there is a narrow bit that gets mangled with small values
2.5, 4., 10.
avian backend
ah, good to know!
just be careful with that knob, it makes generation much more expensive ๐
@sleek scarab FYI https://github.com/andriyDev/landmass/issues/170#issuecomment-3387139115
Perhaps rerecast needs an "ignore mesh" component or something?
it has a filter you can set
The input passed to the navmesh backend system.
Additional ignores are the backend's job (at least ATM)
the mesh backend has ExcludeMeshFromNavmesh
dunno if the avian navmesh does too
Ahhh ok
happy to change it if it's annoying ๐
I don't think this is re-exported from the bevy_rerecast or something?
lol you're right
whoops
Might also be worth it to add that doc to Mesh3dBackend to point more people at it?
What is the difference between a character and an agent in bevy_landmass?
An agent does pathfinding and will avoid agents and characters. A character is basically just an obstacle - it doesn't do any pathfinding or avoidance
So the canonical example is you'd have your player be a character so that you AI agents will avoid them
Published avian_rerecast supporting Avian 0.4 and Bevy 0.17 ๐
@mellow mirage I'm working with Steam Audio right now, and they also do pathfinding, but in 3D using a grid of probes.
Interestingly they have two settings for pathfinding that I think may be interesting for landmass:
- validate paths
- search alternative paths
The first setting makes it so every connection between two probes during pathfinding is validated by a raycast. The idea is that this will catch dynamic geometry, like a moving obstacle. If the raycast fails, then the pathfinding fails.
The second setting expands on the first setting by not failing, but marking that connection between probes as invalid for the current frame. It then goes on pathfinding an alternative route.
The real-world workflow is that you annotate your colliders as Steam Audio meshes, and at bake time only use the "most open scenario", i.e. all movable obstacles are gone. Then at runtime you use the full set of Steam Audio meshes, and the pathfinding will adapt to any new meshes it encounters by navigating around them
It's a bit like the Landmass concept of local avoidance
But API-wise it works more automatically
and I have no clue how they actually handle the new obstacles internally.
I know they do A*, and that's where my understanding ends
But yeah the key insight here is the concept of "optionally use a raycast to verify every connection formed during pathfinding"
Maybe that could be useful?
path finding on the Steam Audio lib?
Yeah it does pathfinding as a cheap way to do audio propagation across space
I don't think that would help much with regular pathfinding. I would guess that audio is much more amenable to approximation, so those alternate paths probably don't "sound" as bad. Whereas if an in agent takes a weird detour it's much easier to see
I'm also guessing that those "probes" are probably distributed more uniformly, whereas the navmesh tries to be as sparse as possibly. Validating a navmesh edge with a single raycast may be more punishing that in SteamAudio's case
Punishing in terms of path quality
Maybe that's wrong though haha
Yeah theyโre a uniform grid
I'm surprised that's fast enough and doesn't chew up memory? Especially if they're doing raycasts during the search?
The pathing is done in a separate thread on a 100 ms timer
How often does the audio update then? Every 100ms?
The audio itself updates every frame, it just uses slightly outdated information
Like, you can offset the pathing to pretend it still arrived at your ear after your movement even if youโre not sure it actually did until the next 100 ms timer
There is also a direct raycast for occlusion that is run every frame
So you donโt hear a "lag" when you go behind cover
Since the pathing is meant to convey indirect audio, you donโt notice if it's a bit out of sync
The spatial information is out of sync, that is. The audio information itself, so the samples, are updated as fast as possible in their own thread
I know I asked this before, but I forgot. If an NPC is pathfinding to a player, and the player moved every frame, how often is that path recalculated?
(In landmass)
I only recalculate the path if the agent or target go off the existing path (in terms of nav mesh nodes), and or if they end up in the wrong order (the target is earlier in the path than the agent)
Otherwise, we keep the path and only update the straight line path which is very cheap
Can I tell landmass to please only do that every 100 ms?
No not yet
It also would mean the agents would effectively be stuck doing nothing for that 100ms
Can't they keep the outdated path?
Since we don't know where the agent or the target are in relation to the existing path
I don't even store where the agent is in their current path
I suppose I could...
I'm mentioning it because this is a very common thing people do in 3D games with lots of NPCs
I definitely want to be able to limit how many path finds there are per frame
Great!
I'm currently modeling my NPCs so that everything they do is on a timer that is influenced by their distance to the player
E.g. their vision cones only update every 500 ms when far from the player, but every 200 ms when near
And the one and only thing I currently cannot really model like that is landmass
At least not that I know
I suppose I could only update the agent entity's position every 100 ms. Then thatโs the time frame for all NPCs, but eh
Hehe
No rush though!
I donโt yet have any pathfinding bottlenecks ๐
Hahaha, that is a clever workaround! It does mean the local avoidance is also broken
Oh yeah true lol
Though maybe in your case you'd be ok to turn that off if given the option?
Hmmmmmm
You know what
I could have a character entity that follows the player every frame
And a separate agent entityโs position every that lags behind on a timer
That way local avoidance still works
๐งช
The agent would try to avoid itself though ๐
Oh heck
Donโt we all sometimes
Agents donโt know anything about CollisionLayers, right?
They do not
@mellow mirage I'm having some trouble 
I'm trying to update my namesh
rerecast looks correct
and the landmass gizmos also look... correct? Not sure
another angle
the agent state is Idle
but it fails to ever sample any point!
the sampler gives me OutOfRange every time
it's happening since I recreted the navmesh
Which kinda puts the blame on rerecast
but uuh I don't think I changed anything?
hmm I fiddled with the params and generated a new navmesh and that one works?
It seems either
- rerecast is generating something fucked up or
- landmass is not dealing correctly with some meshes
It breaks when I open up the navmesh editor and save a newly generated navmesh that has some different params
and that should be hot reloading the nav mesh right?
yes, and it is
but it also happens when I restart the game with the new navmesh
And there's no error logs?
nope. Weird, right?
Indeed!
You can see that something indeed arrives at the landmass side of things
Yeah hmmm that should mean we have valid stuff
hmm, maybe I should be playing around with the sampling settings?
that doesn't do the trick
ยฏ_(ใ)_/ยฏ
well I have my workaround
just a bit curious
@mellow mirage lol the schedule change required touching every test
since they need to actually run, y'know
but done now ๐
Mind taking a look at the PR?
I'll take a deeper look tonight, currently at work lol
Oh sure lol
From a quick skim it seemed fine!
no pressure
also, this should be public in Bevy
PRing that rn
An alternative to this may be to change the fixed update rate to a specific value, and then stick with the manual update strategy. I'm not excited about having a magic number here or even using Bevy's magic number. Thoughts?
Still good to make it pub though
Agreed
take a look now
That works even better!
Nudge nudge ๐
Hi sorry about that! Had a rough night, taking a look right now!
Oh no, then please take your time! No rush 
Done! Thanks for the change!!
@mellow mirage do you happen to know how expensive sampling a point is?
I'm writing some code in a hot loop and considering whether I can afford it
It's fine if not, but do you know what kind of ฮผs times I can expect for sampling on bigger navmeshes?
I haven't benchmarked it no :/
With some extra caching, it could be made faster
Like if you pass a previously cached sampled point, we could check the previous island + node first
Meh I'll stick with my impl. I literally just need it for sorting and all the other features in that lib are completely unnecessary.
Thanks though!
mainly excited that this won't break for others running cargo update on old versions anymore haha
Indeed!
@mellow mirage Is this supposed to work like this?
I was honestly expecting them (agents/characters) to take a path to avoid colliding. Is there anything I overlooked in the landmass or bevy_landmass crate?
I took your example and made it slightly more complex (like you see above).
I'm updating positions using the AgentDesiredVelocity2d.
https://gist.github.com/Ploruto/cf4d91a1b13b164c2e2209f74d7f08eb
Are you updating the Velocity component of both agents?
ahh, I suppose I don't. That makes sense. I thought landmass did that automatically.
There's an issue to make bevy_landmass automatically complain if your agent moves often without its velocity set
Still gotta get around to doing that
What's the function I would use to calculate the velocity? Sorry but I seem to be too stupid to find it in the docs.
The velocity is just the velocity of your agent. Normally your physics engine will provide this. If you don't have one, you can also just use the AgentDesiredVelocity and copy it over, but of course that won't take into account any other effects in your game
I'm currently doing:
fn update_position(mut query: Query<(&mut Transform, &AgentDesiredVelocity2d)>, time: Res<Time>) {
for (mut transform, agent_vel) in query.iter_mut() {
transform.translation.x += agent_vel.velocity().x;
transform.translation.y += agent_vel.velocity().y;
}
}
I thought you meant that AgentDesiredVelocity2d needs to be updated manually.
I seem to be completely off.
Ah not quite, there's a Velocity component too!
The Velocity component tells landmass how the agent actually moves, whereas the AgentDesiredVelocity tells you how landmass says your agent should try to move
So with my simple position update, I could simply set the velocity to equal the AgentDesiredVelocity2d.velocity(), correct?
Yup exactly!
I just realized the bevy_landmass README doesn't mention this! I need to add that!
At least the example needs to include this
I don't know if my brain is completely fried but:
fn update_position(
mut query: Query<(&mut Transform, &AgentDesiredVelocity2d, &mut Velocity2d)>,
time: Res<Time>,
) {
for (mut transform, agent_vel, mut vel) in query.iter_mut() {
transform.translation.x += agent_vel.velocity().x * time.delta_secs();
transform.translation.y += agent_vel.velocity().y * time.delta_secs();
vel.velocity = agent_vel.velocity();
}
}
This is what you where talking about, correct? It appears to behave very similarly.
In the clip I showed, I assumed that the magenta colored path is what landmass strives for.
That's what I meant yes, but also your position update is slightly wrong. You should multiply the velocity by the delta time
Hopefully that'll work haha
I'm guessing that landmass isn't reacting fast enough for how your agents are moving?
Yeah, so I've applied all the changes but they still just push each other around. Either I messed up big time or idk xD
[I've updated the gist to the latest version (just in case)]
One thing I'm noticing is that your agent is also a character! You should just remove the Character component
I did that but that doesn't seem to make it any better ๐
Just do confirm: The agents look like:
Agent2dBundle {
agent: Default::default(),
settings: AgentSettings {
radius: AGENT_RADIUS,
desired_speed: 20.0,
max_speed: 20.0,
},
archipelago_ref: ArchipelagoRef2d::new(archipelago_id),
},
AgentTarget2d::Point(POINT_2),
with no Character component (and some more components for rendering and transform).
Hmmm I'm a little dumbfounded!
And the only system that acts on them is the update_position system from above.
Do I need to activate collision avoidance with a secret feature flag or plugin perhaps? xD
oh, is that no longer a thing?
Haha you shouldn't need to, in fact there's no way to turn off collision avoidance
You normally should have one or the other (or pause the agent)
But I'm just trying to make it as simple as possible to find the problem lol
Just in case: I tried to make them both Characters only (no Agent) but that obviously didn't work either ๐
(I gtg for now, but I'll take another look later, sorry!)
Please ping me if you spot the error/bug.
Hello, say I have many melee units that target a building, is there a way to make them path so that they don't all end up in the same point but instead surround it ?
Also curious how the navigation should interact with a physics engine like avian. What is needed so that it all works together nicely
I'm not sure this has to do with landmass but you could sample points around your 'building' as targets for your units. Then also attach landmass'Agent component to your units to avoid collisions (leads to spreading).
I'd also like to know how "determinstic" landmass (bevy_landmass) behaves. Is there anything that would make it behave nondeterministic?
This is probably when I'm going to do, but since landmass handles a lot of high level navigation stuff I'd thought that it might be something that exists/will exist.
Also i'm still unsure about the physics engine part of my question
I tried running your example with higher speeds and then it seems to work
It's quite concerning that it falls apart at low speeds
At 50 speed it works reasonably well
Also, separating the desired and max speeds seems to help (though I'm not sure why). Normally this is a good idea since it allows agents to speed up to avoid a collision (not just slow down). I tried having a desired_speed of 20 and a max_speed of 100 and it works ok.
landmass doesn't currently have a way to surround points. It's something I do want, but I'm not really sure how to go about it. I think most games solve that problem from the outside by just creating a "formation" that agents try to stand in.
As for interacting with the physics engine, you basically just need to pass the physics engine's velocity into landmass and then use the desired velocity of the agent to update the force in some way.
that makes sense thanks
Yes there is randomness to break out of cases where agents are exactly on top of each other. I also use a lot of hashmaps so I'm not sure what else is non-deterministic.
You can also try playing with the time_horizon in the ArchipelagoOptions. I mainly tuned it for faster movement
Maybe I need a minimum distance as well as a time_horizon
Hello, might be a dumb question, but in the examples the archipelago is cosntructed based on an agent radius, so how would that work with agents of different radii
Usually you want to construct the ArchipelagoOptions with the max radius you're going to use
@mellow mirage you may find this interesting: https://developer.valvesoftware.com/wiki/Nav_Mesh_Editing
Turns out Source Engine lets you edit a lot of its navmesh stuff not in-editor, but in-game ๐
e.g. this one-way link to jump from the ledge down was authored in-game through console commands
I mean in landmass this is literally just spawning an AnimationLink with two points - it's totally fine to do that!
It just never occured to me that one could do that at runtime!
I was always considering authoring that in an editor
Indeed haha
but this way you just do a raycast from the camera, boom, there's your point A
I mean the fact that it seems you have to do this in teh game is a little weird
They were talking about drawing zones manually lol
That I'd expect to do in an editor for sure
yeah that's ass
S2 can generate navmeshes
so at least there that's definitely no longer needed
(in fact, it just does it for you implicitly when you compile your map)
Is there any further documentation on constructing a 3D navmesh? I'm having trouble recreating the examples into my own project.
The current state-of-the-art is using landmass_rerecast.
Please share what you're struggling with though! I wonder if the examples are stale since I messed with the order of the polygons (you may need to flip them)
fn landmass_setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
nav_meshes: ResMut<Assets<NavMesh3d>>,
asset_server: Res<AssetServer>,
) {
let archipelago = Archipelago3d::new(ArchipelagoOptions::from_agent_radius(0.35));
let archipelago_entity = commands.spawn(archipelago).id();
// Spawn the islands.
let mesh: Handle<Mesh> = asset_server.load("levels/World.glb#Mesh0/Primitive0");
let nav_mesh = nav_meshes.reserve_handle();
commands.spawn((
Island3dBundle {
archipelago_ref: ArchipelagoRef3d::new(archipelago_entity),
island: Island,
nav_mesh: NavMeshHandle(nav_mesh.clone()),
},
ConvertMesh { mesh, nav_mesh },
));
}
fn convert_mesh(
converters: Query<(Entity, &ConvertMesh)>,
meshes: Res<Assets<Mesh>>,
mut nav_meshes: ResMut<Assets<NavMesh3d>>,
mut commands: Commands,
) {
trace!("SYSTEM: convert_mesh");
for (entity, converter) in converters.iter() {
trace!("Iterating over converters");
let Some(mesh) = meshes.get(&converter.mesh) else {
trace!("Failed to get converter mesh");
continue;
};
if let Ok(nav_mesh) = bevy_mesh_to_landmass_nav_mesh(mesh) {
if let Ok(valid_nav_mesh) = nav_mesh.validate() {
nav_meshes
.insert(&converter.nav_mesh,
NavMesh3d { nav_mesh: Arc::new(valid_nav_mesh) },
)
.unwrap();
commands.entity(entity).remove::<ConvertMesh>();
}
//let valid_nav_mesh = nav_mesh.validate().unwrap();
}
//let nav_mesh = bevy_mesh_to_landmass_nav_mesh(mesh).unwrap();
}
}
Note, this is me trying to recreate parts of the playground example from bevy_landmass with my own file.
I seem to be getting errors with the validate() method, but I'm not sure why.
I can push my current repo if you want to recreate the error.
I'm just trying to get a minimal working system to iterate on.
What validation error are you getting?
Not sure, I've been trying to print the error.
let me try something; one sec
got it
Err(ConcavePolygon(0))
That might mean how you're exporting the mesh has the wrong coordinate system. That error can be printed if your coordinates are accidentally "vertical" or flipped
Try spawning just the mesh (not the gltf scene) and see if it's oriented correctly
Oh also make sure the navmesh only includes the valid walking areas, not the whole level geometry.
I should be, since the mesh is spawned in elsewhere. I'm just loading it again here for some reason to get the navmesh.
In other words
For example, if you include the bottoms of floors, that's an invalid nav mesh
In this context, Mesh0 should just be the floor itself.
Would other stuff on top of it be causing it, even though it's not loaded into the navmesh?
If it's not a part of that bevy Mesh, it won't have any effect
You can also try triangulating the navmesh before exporting. That could help?
I doubt it though
Want the output of bevy_mesh_to_landmass_nav_mesh(mesh)?
Uhh that may be a lot of data haha
Can you send a pic of bevy rendering your navmesh mesh?
No, because it crashes.
Or now, because I took the unwraps out, it doesn't at all
Here's what it looks like in Blender though
Mesh0 should be the pink ground.
Bevy does render the mesh itself though.
Yeah so the problem is your mesh is a rectangular prism. Landmass is expecting you only have the top face of that prism - so ONLY the walkable surface, not any other part of the floor
That explains that
Yeah haha, it's a pain. But that's what landmass_rerecast is for!
It will use bevy_rerecast to build the nav mesh for whatever geometry you give it
Oof.
I've been holding out on working with rerecast because I couldn't figure it out.
It is definitely a more complex beast with a lot of options haha
But I think the defaults were straightforward to setup?
I'll poke at it and come back with questions if needed.
Quick sanity check question, to make sure i'm doing this right before going forward:
Setting up bevy_rerecast simply involves this, correct?:
.add_plugins(NavmeshPlugins::default())
.add_plugins(AvianBackendPlugin::default())
That sounds right lol
Ok, don't want to get far ahead and wonder what I'm doing wrong, lmao
And you need the landmass_recast plugins
You mean these?:
.add_plugins(Landmass3dPlugin::default())
.add_plugins(Landmass3dDebugPlugin::default())
No, there's a crate called landmass_rerecast
This code from the landmass_rerecast readme:
// This island's nav mesh will be generated by `bevy_rerecast`!
commands.spawn(Island3dBundle {
island: Island,
archipelago_ref: ArchipelagoRef3d::new(archipelago),
nav_mesh: NavMeshHandle3d(
generator.generate(NavmeshSettings { agent_radius: 0.5, ..Default::default() }),
),
});
is giving me this error:
mismatched types
expected struct `NavMeshHandle<ThreeD>`
found struct `NavMeshHandle3d` (rustc E0308)
Woops sorry I got busy and missed this. Yes you need to explicitly import the landmass_rerecast::NavMeshHandle3d. Other than that it should work
Thanks. One last question and I'll leave you alone. What should I look at for using the NavMesh?
Uhhh what do you mean?
Just simply what structs/components should I look more at for creating navigating characters?
ohhh
I know there's agent
Basically just Agent
Yeah, I see that the adapted example supposedly spawns one in.
But I guess because it's not actually a part of any moving entity, it just sits there
I dunno; just trying to figure out what I need to provide, vs what's included.
Ah let me clarify: You need everything in AgentBundle, you need to set Velocity to whatever your agent's velocity is (usually you get that from your physics engine), and you need to use AgentDesiredVelocity to apply the motion to your agent.
You also need AgentTarget to tell the agent where to go
I'll do that for now, but is it possible to handle the movement myself, while relying on the navmesh for, well, navigation?
That's basically what is happening - it's up to you to actually move the agent. landmass just says "if you want to go there, this is the velocity you should move at"
Ah
I understood you backwards there
Real quick, should I be using AgentDesiredVelocity, or AgentDesiredVelocity3d?
Wait, nvm
I think
AgentDesiredVelocity3d is AgentDesiredVelocity with a particular coordinate system, so they should be interchangable!
hey, just a bit confused about the sample_point method- how do i create the inputs for it in the right way? like, for example, how would i pass in the navmesh coords of an agent aspoint?
The point of sample_point is to find the nearest navmesh coord for a given world space point, so you can just use the GlobalTransform translation of an agent as the point
If you're in 2d, you'll need to do .xy() as well
ahh i see, so no conversions or anything. thanks!
hi
Does someone know how can i make the mesh rotate towards the walking direction ?
pub fn move_agent_by_velocity(
time: Res<Time>,
mut agent_query: Query<(&mut Transform, &GlobalTransform, &Velocity3d, &Children)>,
) {
for (mut transform, global_transform, velocity, childs) in agent_query.iter_mut() {
let local_velocity = global_transform
.affine()
.inverse()
.transform_vector3(velocity.velocity);
transform.translation += local_velocity * time.delta_secs();
}
}
i wanted to update it there
but the agent just rotate indefinetely
@mellow mirage is there any bult-in settings for that ?
No, it's up to you to do updating of the character transforms
Landmass sets the agent desired velocity, it's up to you to set the regular velocity.
right
you can assign the rotation to the velocity using something like: https://docs.rs/bevy_transform/0.17.3/src/bevy_transform/components/transform.rs.html#471-480
Source of the Rust file src/components/transform.rs.
how do i get the target potint ? no the final but the next ? is it "desired" ?
AgentDesiredVelocity
There's no way to get the next target point, but the desired velocity will point in the direction the agent wants to move, which will take into account local collision avoidance.
hello again, is there a best way to get the "walking distance" of an actor from their target?
You can use find_path, which returns a bunch of points (basically), and then just sum up the distances of those points.
right thats what i was thinking, thanks!!
ERROR bevy_rerecast_core::generator: Failed to generate navmesh: Invalid contour. This sometimes happens if the contour simplification is too aggressive.
This error is a little vague, what should I be looking/poking at?
I'm guessing the bevy_rerecast generation options has a contour simplification option?
There are a handful of options it could be in NavmeshSettings.
This may be more of a question for @sleek scarab
Hi I am trying to do navigation on rerecast navmesh
i use this to set target of agent:
โจ```rs
let _target = commands.spawn(target(position, &mut meshes, &mut materials)).id();
for mut agent in agents {
*agent = AgentTarget3d::Point(position + Vec3::Y * 0.3);
}
then i print in console and i get this
โจ```
Target: Point(Vec3(-1.2441564, 0.38111955, -0.9764929)) | State Idle
```โฉ
why is agent idle but has target that he didnt reach yet
also this is how i spawn player
โจ```rs
pub fn player(
position: Vec3,
meshes: &mut Assets<Mesh>,
materials: &mut Assets<StandardMaterial>,
archipelago: &ArchipelagoRes,
) -> impl Bundle {
let mesh = meshes.add(Capsule3d::new(
AGENT_RADIUS,
AGENT_HEIGTH - 2.0 * AGENT_RADIUS,
));
let material = materials.add(Color::srgb_u8(124, 144, 255));
(
Name::new("Player"),
Player,
Transform::from_translation(position),
Agent3dBundle {
agent: Default::default(),
settings: AgentSettings {
radius: AGENT_RADIUS,
desired_speed: 7.0,
max_speed: 10.0,
},
archipelago_ref: ArchipelagoRef3d::new(archipelago.archipelago3d_ent),
},
AgentTarget3d::None,
children![(
Transform::from_xyz(0.0, AGENT_HEIGTH / 2.0, 0.0),
Mesh3d(mesh),
MeshMaterial3d(material),
Pickable::IGNORE,
)],
)
}
Hmmm that's surprising? Are you logging in the same frame that you spawn? Or do you log after at least one frame?
i just figured it. i spawned agent to fast and it was somehow baked into navmesh even though i use filters for it
now i spawn agent with delay and it is working
Huh that's still surprising, since then the agent should be reporting that it's not on the nav mesh
Strange
i have a question:
initially i spawn agent with default desired speed
now i want to update this desired speed (example walk, run)
how to do that since AgentDesiredVelocity3d is not changable
do i just leave it and only update Velocity3d, but will it work (The current velocity of the agent/character. This must be set to match whatever speed the agent/character is going.)
You can query for https://docs.rs/bevy_landmass/latest/bevy_landmass/struct.AgentSettings.html and mutate the desired_speed field
The settings for an agent. See crate::AgentBundle for required related components.
@mellow mirage you got time for a sec?
I can chat yes haha
What's up?
we're doing jam stuffs and I'm having a landmass trouble
sec
pic incoming
so I want my dudes to do a random walk
and what I do is, I take their feet pos
then take a random dir
raycast there
and where it hits, I pull a little bit back just in case
and that's the yellow circle here
how this of course doesn't work because it's not quite on the navmesh right
so I sample the position
but that almost always gives me an error
Are you messing with the PointSampleDistance options? You can make the radius really big there
I tried 0.5
thought that should certainly be enough here
You're also setting distance above and below, right?
I use from_agent_radius
so yeah
Hmmm
Oh yeah wait if you did from_agent_radius(0.5), the radius would be 0.1
I would not recommend from_agent_radius when sampling
dudes are walking!
thx!
@mellow mirage i am trying to use bevy_landmass on top of bevy_rerecast navmeshes. what is the minimum setup i need to do if all i need is the position sampling from Archipelago3d do i need to spawn IslandBundle and Agents ?
You need the island bundle but not the agents
And you need an archipelago of course
awesome will give it a try
if i have a platform that is constantly moving how can i make the pathfinder make use of it when it at a point close enough to adjacent navmesh parts to connect to?
Uhhhhh a constantly moving platform will not work well... Especially with bevy_rerecast which I think will recalculate the navmesh every frame.
If you're willing to go advanced, you can make a second archipelago whose island is "relative" to your moving platform. You can do all your pathfinding on that, and then when the platform is stationary you can change its ArchipelagoRef to point to the "main" archipelago
i believe one needs to call regenerate manually
Oh I stand corrected, for some reason I thought it was auto updating
ok so for this i would need the archipelago to be aware on what island / platform i locate it at any given time, right?
Yeah. Similarly your agents need to know what platform they are on as well
gotcha. ok
Looking for a bit more help on how to debug AgentState::NoPath
I'm generating the vertices for the navmesh based on tiles from ldtk, and the Landmass2dDebugPlugin shows everything fine, so I'm unsure why the agent can't path from the top left to bottom right tiles. I'm rendering the agent with a green circle (top left).
let mut vertices: Vec<Vec2> = default();
let mut polygons: Vec<Vec<usize>> = default();
for (tile_coord, tags) in tiles.iter_many(children) {
if !tags.is_some_and(|tags| tags.tags.iter().any(|t| t == "Pathable")) {
continue;
}
let tile_pos = IVec2::from(*tile_coord) * layer_metadata.grid_size
+ IVec2::new(-layer_metadata.grid_size / 2, layer_metadata.grid_size / 2);
polygons.push([0, 1, 2, 3].map(|i| i + vertices.len()).to_vec());
vertices.push((tile_pos + IVec2::new(0, 0) * layer_metadata.grid_size).as_vec2());
vertices.push((tile_pos + IVec2::new(0, -1) * layer_metadata.grid_size).as_vec2());
vertices.push((tile_pos + IVec2::new(1, -1) * layer_metadata.grid_size).as_vec2());
vertices.push((tile_pos + IVec2::new(1, 0) * layer_metadata.grid_size).as_vec2());
}
let nm2d = NavigationMesh2d {
vertices,
polygon_type_indices: (0..polygons.len()).map(|_| 0).collect(),
polygons,
height_mesh: None,
}
.validate()
.unwrap();
Your polygons aren't connected. Landmass uses shared vertices to determine if polygons are connected
The way you've generated your mesh, each square defines its own 4 vertices, so since none of those vertices are shared, it doesn't think those polygons are connected.
ahhh, ok, makes sense thanks
Hi, I can't find a channel for rerecast, so I'll ask here, hope thats fine.
I have a couple of questions:
rerecastallows generating a navmesh from any gltf file that gets spawned. Can I also specify a specific gtlf model, and only this should be used for nav mesh generation? Ive exported a mesh as gltf file from https://navmesh.isaacmason.com/ (and edited it in blender, so some areas wont be included in pathfinding)- If that's not possible,
bevy_mesh_to_landmass_nav_meshmentions that its implementation is naive, and a better method for generating navigation meshes should be used. Would this also apply to my case, where that mesh is made specifically for pathfinding? rerecastmentions in their README that its possibe to export a navmesh as a .bin file and import it into the game. How can I import the file in the game? Is that something that I need to implement myself?
The easiest way to generate a navigation mesh. Upload your GLTF file, tune the configuration, and download your navmesh as a GLTF.
Previously, I've just generated the nav mesh from colliders using avian integration, but now i want to exclude some areas to be not included in navmesh generation, hence why ive switched to gltf model as i can edit that in advance
@sleek scarab
Can i maybe somehow export the nav mesh that avian_rerecast generates as a file thats editable in blender, so i can remove some areas from the nav mesh, and then import that edited file in rerecast?
because the nav mesh itself seems to be of much better quality than the one the online version generates
What do you mean by "online version"? ๐
the online generator found here
https://navmesh.isaacmason.com/
both implementations rely on recast, so they should have both same results? but maybe i misunderstand some things ^^
The easiest way to generate a navigation mesh. Upload your GLTF file, tune the configuration, and download your navmesh as a GLTF.
Hmm right now I just serde it into a file I call .nav, but it could just as well be a gltf with a little bit of elbow grease
Oh hey I didnโt know that ๐
Yeah should be the exact same IF the params are the same
(I have unit tests to verify that)
Okay, I see, so then my question would be whether I can specify from which gltf model the nav mesh should be generated, for some more context see my message from above
Ah sure!
So either you tag the meshes that you want to ignore
(I forgot the name of the marker)
Or you take a look at how avian_rerecast is implemented
Itโs just a 50 line glue
You can customize that to do whatever you want ๐
okay i see, so there is some kind of name that i could include in my meshes name, so bevy_rerecast will ignore them?
No, itโs a marker component
Ah, even better!
I assume you use bevy_rerecast_editor?
Hmm, I did use it before, but at the moment I can't get it to work. Have you tested it since bevy 0.18 came out?
Yep, used it for the jam ๐
Component to opt-out a Collider or RigidBody from navmesh generation when using AvianBackendPlugin. If that backend is not used, this component has no effect.
This is the marker, but itโs in the rc
Which uses avian 0.6 rc
Yeah, I would love to make my own implementation, but I have basically 0 knowledge that would be required to make a own backend. but maybe its time to learn a bit more about this topic
Itโs suuuuuper simple ๐
Take a look at it, it should be self-explanatory
Component used to mark Mesh3des so that theyโre not sent to the editor for previewing the level.
Alternatively, this component makes the collider not go to the editor at all
you prob mean 0.6.0-dev?
Okay, I will ๐
Okay, perfect, thanks for the answers!
ahh, nice, your move and slide implementation is included there! maybe ill switch to your implementation, mine is a bit crappy haha
but im also very happy that i was able to write my own, so out of proud ill keep mine ^^
Yesss I think it turned out quite good 
That is really something to be proud of! 
Thank you!!!
Ah, I found the error that I had running bevy_rerecast_editor:
2026-02-21T11:09:10.737598Z WARN bevy_ecs::error::handler: Encountered an error in system `bevy_rerecast_editor::get_navmesh_input::poll_remote_navmesh_input`: BRP error: {"code":-32601,"message":"Method `bevy_rerecast/generate_editor_input` not found"}
Which is weird, because that would mean the method that comes from rerecast wasnt added? Also, in README, its mentioned that the remote plugins need to be added, but adding it in bevy 0.18 errors because these plugins already exist, I guess that was changed in bevy 0.18 when you add the bevy_remote feature
I get this when I click Load Scene. I also remember trying to debug this, seeing that the method only gets inserted when certain resources exist, etc, i made sure everything was setup correctly, i even had a log for when the method gets added, which i could see, but still, i got that error
Did you enable the editor_integration feature?
Do you have both the remoteplugin and theโฆ i think httpsplugin?
Ah, i was missing that feature. Ooops. Thanks!
You want me to make a PR to add a note in editor section that the feature needs to be added?
Adding bevy_remote feature seems to already add those two plugins. or i guess defaultplugins.. adding those plugins errors
Yes please ๐ I think itโs in the default features, but worth a note!
Good to know! Could write that into the readme too
okay, i will include it in pr
alright, ive made the pr, tell me if you want the notices at a different location. think it makes sense like it is
https://github.com/janhohenheim/rerecast/pull/53
Thanks a lot, I'll check when I'm back home later 
@mellow mirage I'm running into an issue where I set an agent's AgentTarget3d to a point, but I always get LandmassAgentDesiredVelocity::velocity of zero
the target I set is the result of a successful archipelago.sample_point
any idea how I might debug this?
I suppose the NPC's agent is maybe not on the navmesh for some reason 
though it surely looks correct
the box on the ground is where the target is
I'm also missing the yellow target gizmo that I usually get
Step one is always logging their state
But I think landmass debug rendering uses blue
So I think your island is just not properly registering, or the nav mesh is not being converted properly?
yeah this is my custom visualization
Idle
FYI this is code I'm porting from one crate to another, so it's very possible I'm missing something incredibly simple that I forgot to port
I'm betting your agent is missing some component that landmass needs
That shouldn't be the case when there's a target I think 
lemme check
do you see anything suspicious?
Nothing other than the comments wants to follow player lol
ah yeah I use a different targetting system in this other crate
You did add the landmass plugins right?
Both the regular ones and the rerecast ones?
should, but let me double check
yep
It would be cool to be able to ask "does this entity match a query in this system"
That feels build-able
where would you use it?
aah to see if it's the same entity that i'm setting up?
let me maybe take a look at how it looks in-game
looks correct to me
Maybe your archipelago doesn't have the right components?
then sample_point wouldn't work, no?
it's just this here

I'll be afk for a moment, but I'm really curious what I'm missing
oh, simple question: I assume AgentTarget3d::Point is a global value in the end, right?
and not relative to the Transform of the agent
Yes global
that sounds right then
I also will be afk shortly lol
before going I quickly printed the Entity IDs and yes, it's the same entity
back now
it certainly does, but it's possible some of its parents may not
then again, that should print a warning in Bevy I believe
i.e. Transform requires GlobalTransform, which I believe has a builtin validation observer
just checked. Yep, the entire hierarchy has them
@mellow mirage I'm a silly silly goose
I tweaked some constants and the sample_point function actually returns Err
whoops whoops
fixed that and now I get AgentNotOnNavMesh
definitely
the agent is on the feet
is there a knob I can tweak?
the AgentSettings::radius maybe
I think you want to change the radius of the archipelago options?
It's set to 0.25, so I think the height is like 0.05 or something smol
using this yields no improvements
I should check the landmass gizmos
okay I'm silly
I rotated something and forgot to rotate the navmesh too
haha
now it works
thanks for the help 
Hello, so my question is: How are we handling large open worlds? Is there a built in way to build the nav meshes in chunks and stitch them together?
In theory yes haha
So rerecast is a 1:1 port of recast, which has exactly that feature as you described
I just didnโt port it yet
Itโs not difficult or anything, it just never blocked me yet
I'll for sure port it eventually unless someone beats me to it, itโs just very low priority given how fast the non-tiled version is proving to be
Note; recast calls the chunks "tiles"
Sounds good. It's not urgent for me either, just something I know I'll want to do eventually.
Thank you for the answer ๐
Okay another question: Is it possible to make it so the debug visualizations for different islands are different colors so I can see where breaks are in complex terrain?
Landmass islands? Probably not. I don't think I currently expose that. I would be happy to accept a PR for that though ๐
No, it's for my custom terrain #showcase message Maybe island isn't the best term. Just the disconnected navmesh segments
also gotta figure out how do disable generation on oceans. Maybe make them separate meshes?
Also, eventually, I'd like to have alternate means of transport like Morrowinds silt-strider service. I'd need a way to work that into navigation but I think I can get that working in my custom graph layer that agents user for distant navigation
Thatโs a pretty good idea ๐
Mind opening an issue?
Should be easy to implement
When generating a nav mesh, it is common to end up with two or more distinct, separate nav mesh areas. Since nav meshes can be quite large, it's hard to notice these discontinuities at a glance...
@sleek scarab I switched my pathfinding to landmass and it's working flawlessly. I thought landmass was a crate for, like, big heightmap terrains lol
A beautiful path across my custom navmesh, discovered nearly instantly
Hehehe, one of us, one of us!
This is such a joy to see working 
Please share a video of the agents walking around once you have that!
OOOOOH AAAAAAH
@mellow mirage if @robust cosmos is fine with it, this would make for an extremely lovely video in the readme
thanks for sharing 
again, soooo cool to see rerecast working in action ๐
oooh.... I actually generated my own navmesh lol
It was easy since I'm already generating the terrain. It's almost instant
Good point!
@robust cosmos would you be ok with that?
oh fair enough lol
Yeah I don't mind
I was looking through the landmass API for building navmeshes, I currently use polyanya. I was wondering if there is an equivalent workflow in landmass? Basically I have a square map, and everything is grid based. So I just carve out squares where needed. Agent radius takes care of adding margin between the carved out obstacles and the walkable area, "smoothing" the corners of everything. Below is the entirety of my navmesh generation logic ๐
let mut triangulation =
polyanya::Triangulation::from_outer_edges(&SQUARE.map(|p| p * config_size));
triangulation.set_agent_radius(agent_radius);
triangulation.add_obstacles(
obstacles_to_use
.into_iter()
.map(|(size, pos)| SQUARE.map(|corner| corner * size + pos)),
);
let mut navmesh: polyanya::Mesh = triangulation.as_navmesh();
Landmass doesn't do that, but rerecast does
But I did do something similar for a 2d game I was working on. Just started with a big rectangle and then cut away area using geo
You can also take care of the margins by just expanding each area you cut away first
I guess, though I'd have to generate more complex shapes than a square or I'd get hard corners everywhere
oh wow geo is a beast of a crate, didn't know about it before, thanks!
I assume you used boolean ops to cut the polygons?
Indeed!
Interesting, I might try hook that up directly into landmass, I don't think I need complex stuff like recast to figure out a navmesh because I have "perfect information" about it by design
My rough impl I used haha
Oooh this is awesome, cheers! What are you doing lines 189-206, some kind of shape expansion?
create_full_nav_mesh_polygon is basically exactly what my above code does xD
I think it turns every vertex of the original rectangle into its own square based on the agent radius, which later gets convex-hulled.
That was a simple stupid way to make a margin around the colliders
Thanks @humble hatch for the guidance on character movement ๐ using a navmesh to bound the player simplified the controller implementation a lot, and it works smoothly with this collection of landmass crates which i was gonna need anyway for npcs. Just wanted to show off the nice workflow I was trying to set up where I can edit the level in blender, and immediately preview and save/commit the level's navmesh to the filesystem (and have it then hotload to the level's archipelago directly in game) - all fairly easy to set up with bevy patterns and the crates
I'm getting a ConcavePolygon(0) validation error, but I think it's wrong? It's always polygon 0, so I print it but it seems fine
println!("{:?}", nav_mesh.polygons[0]);
for v in &nav_mesh.polygons[0] {
println!(" {v}: {}", nav_mesh.vertices[*v]);
}
[2, 3, 0, 1]
2: [10, 0, 10]
3: [-10, 0, 10]
0: [-10, 0, -10]
1: [10, 0, -10]
I'm following the logic you linked earlier andriy, using geo to build the navmesh. I'm rendering the GeneratedNavMesh in green here
Hmm yeah I'm not sure why that would be wrong, it looks correct to me. You could try flipping the order of the polygons but I don't really understand why that would be necessary
Iirc the bevy 3d coordinate system should do the flipping for you automatically...
I called .reverse on all the polygons but it just moved the error further to polygon 5 lol ๐ฅฒ I've mostly copy-pasted from your gist so there might be something I'm doing wrong somewhere
here's the original one
fn navmesh_validation_test() -> Result<(), landmass::ValidationError> {
use landmass::{NavigationMesh, XYZ};
let nav_mesh = NavigationMesh::<XYZ> {
vertices: vec![
Vec3::new(-10.0, 0.0, -10.0),
Vec3::new(10.0, 0.0, -10.0),
Vec3::new(10.0, 0.0, 10.0),
Vec3::new(-10.0, 0.0, 10.0),
],
polygons: vec![vec![2, 3, 0, 1]],
polygon_type_indices: vec![0],
height_mesh: None,
};
nav_mesh.validate().map(|_| ()) // ValidationError::ConcavePolygon(0)
}
does landmass offer a way for agents to not pick the same location to navigate to? My units have collision in my game and are navigating to the same area/colliding with each other haha
No there isn't unfortunately
I don't know if there's anything we can do here without something like navmesh hole cutting, which is not practical on the landmass side. Maybe rerecast could support that but I don't think it does currently
or synchronized arrival from https://www.jdxdev.com/blog/2021/03/19/boids-for-rts/ (misspelled as Syncronised Arrival)
when a unit arrives at a destination it checks if itโs neighbours are in contact with it and zeros their velocity and sets them as arrived too
Syncronised stop is disabled if a unit isnโt within a threshold distance to the movement goal, this means that units too far away will push others forwards until they enter within this larger stopping distance. I added this so that units stop in a smaller circular radius around the movement goal, rather than a long thin line of units forming (like a line of ants coming to a stop).
I'm gonna ask here, because I see no other relevant place:
I want to build navmesh data using bevy_rerecast and then access it (wanna try to create own pathfinding). bevy_rerecast tells that I need: run bevy app and load scene -> load scene into bevy_rerecast_editor using bevy brp -> generate navmesh -> load navmesh in game
I feel like in release game version I don't need all of this bevy -> rerecast editor -> bevy loading complexity, I just want to be able to load predefined navmesh data
Is there any way to just load scene from 3D model into editor?
bevy_rerecast has features to turn off some stuff
I was also under the impression it has a loader to just load nav data from a file?
I believe bevy_rerecast not only load but also provide a way to access navmesh data, otherwise you need to read raw bytes, no?
You can use https://docs.rs/bevy_rerecast/latest/bevy_rerecast/asset_loader/struct.NavmeshLoader.html to load the nav mesh data without going through the editor at all
The AssetLoader for Navmesh assets. Loads files ending in .nav.
You can also disable all the editor stuff by disabling the editor_integration feature on bevy_rerecast
yes, this loads .nav, but I need to somehow make editor see my 3D model to actually create .nav, and the only way it seems is to connect bevy to editor using brp, which makes project configuration quite complex (optional features), but all I need is to just feed 3D model into editor, why it can't just load .gltf itself?
Ohhhh I understand now, sorry about that
That's an @sleek scarab question
Largely I think this is just because it's much easier to send the mesh itself rather than trying to get the editor to load the correct path with the asset system
which doesn't want to break its file system abstraction
You can generate a navmesh from the running scene via code
See the examples
The editor is just a neat tool to do that for you
Ideally for static scenes you create the navmesh data once, save it in a .nav file, then ship that nav file to the player to load it
Or you regenerate the navmesh every time the player starts the game if the computational cost is not too high for you
You never need the editor if you donโt want to
Oooh I see what you mean now, you want to load a gltf into the editor
Yeah the only reason that doesnโt work is that I didnโt implement it :p
Ideally I want to replace the navmesh editor with jackdaw anyways
I think jackdaw can load arbitrary gltfs
Bingo, and also to support prefab obstacles, as raw glTFs cannot reference other glTFs, so this has to be done at runtime
@digital harness does loading a gltf, generating a navmesh, then saving a navmesh work atm?
I know it should
but does it?
Great thanks for answering!! well, as I understand the workflow is:
- have bevy_rerecast_editor as optional feature (for plugins / any logic call use
#[cfg]) - run bevy app -> remote access with editor -> bake .nav -> load .nav in next run without nav editor feature
is it clean solution? Just looking for project setup that won't load it with unnecessary dependencies
Oh i havenโt tested that flow in a while
But i dont see how it wouldโve been touched with recent changes - aside from migrating to the Operator API internally
Iโm AFK tonight but can have a look in the AM
Yeah that sounds right. I personally donโt see it as overhead since I need a separate dev mode anyways for hot reloading, bevy_inspector_egui, debug gizmos, etc
So the rerecast editor stuff is just one more feature to add to the feature gate pile
If itโs just a glTF, take a look at https://github.com/jbuehler23/jackdaw
You should be able to load your glTF there and export a .nav
whoa ๐ฎ
I would also love for you to suggest any improvements to the gltf loading as well, i kinda didnโt have a need to go further with a basic load and display type deal (and some fiddling around child entities that get created in bevy iirc)
you mean I load glTF with jackdaw functionality and then load it in rerecast editor?
No, jackdaw has rerecast support
You can load a glTF in jackdaw AND generate a rerecast navmesh AND export it all in jackdaw ๐
At least you should be able to, jackdaw is a bit buggy
So let us know if thereโs any issues with that
I currently at the point where I have .nav data (I didn't use jackdaw yet, just create TriMesh from tagged scene entity), in editor it looks fine.
Next step I want to be able to just move player on this navmesh, currently I use WASD to just move player along xz axis. I don't need any pathfinding yet, just move player but now with navmesh data as spatial constraint
I believe for that to be happen player entity should have something like agent data (where it is in terms of navmesh polygons) and sample flat movement along current polygon, polygon crossing, height sampling (using detailed mesh as I understand).
Is there something in landmass or other crates I can just grab and use, or am I need to implement this myself
Landmass has a method called sample_point you can use
I'm preatty new for navmesh implementation details, so pleas excuse me for asking maybe too much noob question. @mellow mirage also thank you, player is moving on navmesh with just sampling good enough with really rare stacking
I'm trying to start to implement custom algorithm for crowd pathfinding on navmesh.
As I see all polygons in polygon mesh are placed in a way so if polygon A is a neighbor for polygon B then agent can travel straight forward from any point of A to any point of B and vice versa (without touching any other polygon or abscent of surface). But can I be sure this is a rule?
That's not strictly true given animation links (aka off mesh links)
But with only polygons, that is true
I want to avoid off mesh links as much as possible (I gonna talk very seriously with level designer about that ๐ )
I'm having trouble with pathfinding using landmass. I have a 2d grid with a player and a monster (see picture), and the monster keeps getting stuck against the walls. Its desired velocity vector points in a direction that goes exactly through the corner of the wall, not taking into account the radius I gave the monster :/ Anyone has an idea what the problem might be? I'm also attaching the code for spawning the archipelago and the monster's agent.
This is intentional sorta. The nav mesh should be the walkable area. Of course the monster has some radius, so some of that area that you've marked walkable actually isn't walkable.
You need to shrink your navmesh by the size of the monster
Ohh I see. So this won't support having entities of different sizes? Or like, I need a different archipelago for each
Sorta yeah. I'd recommend just picking the biggest size entity you have (within reason) and then using that for navigation.
Usually most characters are similar enough in size that picking the biggest to err on the size of caution works fine
If you do need substantially different sized entities, then yeah a different archipelago for each could work, and putting characters for large agents in the small archipelagos
Hopefully that makes sense haha
it does! thanks a lot! and thank you for the crate :] it was pretty simple to setup and get working
I just wish the quality was better haha. Agents that are stationary cause all sorts of problems that make me really sad about it
And a lot of the solutions I've seen seem to be too RTS focused.
yeah it's been difficult to find good resources on the subject. I was quite happy when I found that you'd solved most of my problems with landmass ๐ sorry to hear it's not as good as you'd wish
That's exactly why I wanted to fill the space! It seemed shocking that there wasn't just an out of the box solution that solved all these problems (that wasn't proprietary in other engines)