#Avian Physics
1 messages · Page 43 of 1
and batch processing should be better for perf than a dozen observers firing for each added/removed body
I could try recreating a minimal example for you to track it down
but from what you're saying it looks like you might want to delay it further until you refactor it
tell me if you'd fancy the reproducible example and I'll see what I can do
however, one more thing @vestal minnow, what time would you say is the best to insert the disabled component? I'm trying to use an observer and some avian-inserted component to delay the insertion of Disabled until Avian has setup all of its internal things
the thing is that inserting an entity with Disabled directly is borked af, however if I manually trigger the insertion with (for example) a key input then there's no problem
so I'm trying to find the sweetspot for automatic insertion 😅
Hello and thank you for avian, it's pure magic.
I'm testing avian on a simple game (with rollback), detecting collisions with observers works fine.
One thing i'm not sure how to do, is determine which parts (sides) of the colliders come into contact. In this case it's just a ball with a circular collider and some obstacle with a rectangular collider.
The collisions give you the normals of the colliding entities, I imagine you can use that for checking
Hello and thank you, i'll check the docs again.
Is it correct that "Collisions" used to be a bevy Resource, and now it's a SystemParam ?
Because i saw a project of someone using bevy_ggrs and avian, and he had some code to register "Collisions" as a resource to be rolled back.
Is it enough to just rollback CollidingEntities ?
@cinder summit ^
ContactPair contains a list of ContactManifold, and ConactManifold has a "normal" field.
total_normal_impulse() ?
What I roll back now is ContactGraph and ConstraintGraph, I also disable IslandPlugin and IslandSleepingPlugin on avian to avoid mispredictions caused by those not being deterministic if the simulation wasn't spawned in the exact same order
Nice. I don't get any desyncs.
I don't rollback Position, only my VirtualPosition.
Ok, i think i found it, ContactPoint.
Is it wrong to use Collisions from an observer ?
why would it?
How is the progress of the kinematic controller group ? Just to know since the posted links have expired
thanks
@vestal minnow thanks a bunch of implementing Default on Collider
I got worried for a second there that a certain pattern wasn't possible
...I did?
oh lol
alright, convert my praise into: please implement Default for Collider in peck
hehe
wait no
this is avian
there we go, real Joona code
why is that 0.5x0.5 
convert my plead back into praise
oh wait, did we both think it was half_length
heh
wonder how many users it would break to change
probably a leftover from when it was half lengths
This reminds me of the time when we swapped height and width for some constructors
good times
Would it be useful if we had an Empty shape variant that we can use as a default? IIRC Jolt has an EmptyShape too
It literally does nothing, it's just a placeholder basically
hmm, could be
I need it as a placeholder that I late-init in an on_add hook
so for me Empty would certainly be good enough
Good morning. Does a value of 1.0 in a collision normal vector have a special significance ?
it just means that it's a normal perfectly pointing into an axis
e.g. directly into the Z axis
Update in case anyone else has this problem:
Solved using the same solution as Quake 2:
https://github.com/id-Software/Quake-2/blob/372afde46e7defc9dd2d719a1732b8ace1fa096e/qcommon/pmove.c#L248
Discovered via https://github.com/Ploruto/kcc_prototyping/blob/main/src/move_and_slide.rs
@cinder summit When i use bevy_ggrs in synctest mode (just local players) with avian, it reports desyncs as soon as there's a collision, doesn't happen in the normal p2p mode ... strange
is avian stateless ?
Nope, though you can disable certain behaviors to have it behave much less stateful, like disabling warm starting, and disabling simulation islands and the associated island sleeping plugin
I think @vestal minnow had some ideas on how some of these features could get a stateless version eventually though 🤔
Jolt's parallel union-find algorithm to build islands from scratch each tick, plus some non-incremental greedy graph coloring for the constraint graph
the lack of warm starting would be quite bad for stability, but Unity DOTS physics has some cursed heuristics that it uses to improve stability without contact caching, which is something we could try
@vestal minnow can I get ur attention for a bit about the PR I put up yesterday?
Objective
Whenever a Collider is disabled and moved away from a position, the collisions that it was triggering will come back to being active as soon as the Disabled component gets removed again, ...
I've noticed some more weird behavior after the fix (and I've explained it in the PR already)
and I've been thinking that the "correct" solution for this would be to just have an observer on colliders On<Add, Disabled> that removes the collision
instead of changing the current function like I did in my PR
what do you think?
in theory you're already accounting for it here, but something isn't working :/
In which bevy schedule do avian collision event observers run in ? When you use .observe() with CollisionEventsEnabled.
PSA: hot-swapping a Collider at runtime works fine! It recalculates the ColliderAabb as expected 🙂
damm
Wait, why is this surprising? 🤔
Joona and me chatted about it and we both guessed that it should work
Since they get triggered by avian, they'll happen in whichever schedule you've set it to run, which by default is FixedPostUpdate iirc
but didn't actually know for sure
What ... I mean I've seen all the code for it and knew it works 
well I didn't 😛
Thank you, very interesting. But shouldn't the handling of the collisions happen in the GgrsSchedule ?
I'm seeing this weird behaviour: when running the game on desktop (1v1), i never get any desyncs on collisions. On wasm, i get desyncs every time there's a collision with the ball.
And the ball collision handling is done with an .observe(), that's why i'm wondering if the problem isn't because i'm mutating the ball velocity outside of the ggrs schedule. All my systems run before PhysicsSet::Prepare.
I think all of your physics should happen inside of the schedule you'd replay during rollbacks, if that's not FixedMain, then you probably want to set avian to run in a different schedule
Ok. Are there any public projects of games using bevy_ggrs + avian ? Only found the "bevy_ggrs_avian_example" repo.
No clue, I don't personally use bevy_ggrs, I do set avian to run in a different schedule in both my game and the bevy_rewind example however: https://github.com/NiseVoid/bevy_rewind/blob/main/examples/toy_cars/avian.rs#L13
Yes i run avian in the RollbackUpdate schedule. RollbackUpdate is a schedule from the bevy_roll_safe crate.
So if you do: .add_plugins(PhysicsPlugins::new(RollbackUpdate)) .. then your observers will run in RollbackUpdate ?
Yep. though if it's in the update one you'll have to order many things to run before physics, which is why it's usually in the PostUpdate versions
I use .before(PhysicsSet::Prepare)
Thank you very much for the infos @cinder summit
@vestal minnow is there any difference between controlling a kinematic body by settings its transform vs by setting its velocity?
i.e., does Avian do anything "fancy" if I am a good citizen and use the velocity instead of teleporting a kinematic body?
(not counting interpolation)
Velocity is important so that collisions consider relative velocity correctly. If the velocity of the kinematic body is zero, any other bodies that bumps into it will see it as a stationary object, which will lead to an incorrect contact impulse
There may also be differences in how well e.g. speculative collisions work
alright, then I'll set the velocity where possible 🙂 thanks!
Velocity is also important since it applies the movement over several substeps
However with collide and slide you may need to do something different, since you essentially have a known target position that you want to move to (the output of the algo), and the collide and slide algorithm itself is not integrated with substepping
yeah it works wayyyy better if I just set the position :/
that's also what the KCC prototype does
when I instead set the velocity, I get a lot of penetration
which means I'm setting the velocity wrong ofc
but there is a certain neatness in just saying "okay, for this velocity you calculated, please just advance as far as you can before penetrating"
I believe Rapier does just set the transform, not sure what engines typically do here
All simulations have state. If this is for rollback, what you need is the ability to copy all state that can’t be reconstructed. My physics has warm start and other state, but it can all be copied.
"stateless" as in "cacheless", Unity's ECS physics also markets itself as "stateless"
That doesn’t make a lot of sense. How is the last position not considered state, but previous contact forces considered state?
“Cache” implies it can be recalculated, but is stored to improve performance, but these can’t be recalculated.
just checked Godot, they set the velocity
I mean the previous contact forces are kind of a problem when networking, if those are necessary you kind of can't just connect to a simulation midway anymore, since those depend on the one in the frame before, which depended on the frame before that, etc etc
Mainly the point is just that the simulation can be driven by the current state (positions, velocities, shapes, masses), and you don't need to store any previous state like warm starting impulses and you don't need to rollback constraint graphs and whatnot
but its stateless
Same for any other state. You could send them over the network.
You could do that, but that would cost a decent chunk of bandwidth, so if you're networking over the internet you really don't want to do that
Less state can be better, but there’s always a trade off.
Yea, the tradeoffs exist, but usually you can implement better options than just "disable this feature entirely because it's impractical for networking"
Currently avian doesn't really give you options though, you either get the features, or don't get the features 
State only needs sent on initial synchronization i.e. joining an in-progress game. After that only inputs need be sent.
idk how nise did client prediction with avian not being state less
seens pain
btw you made avian 3x faster, is this faster than rapier now? @vestal minnow
I disable most of the state, except the parts that only cause minor mispredictions that eventually dissolve into floating point errors
Fun thing is that rapier gets improved too, allthough at a slower rate (in part because less active development, in part because the more complete your physics engine, the harder every improvement is)
and they're also working on other things like their GPU physics
damm
fr?
what you think you could improve to make it as fast as rapier jondolf?
see their wgmath (wgsl) or nexus (slang) repos for rigid body physics, or slosh for MPM simulation
very WIP though
wgmath (wgrapier, wgparry, etc.) is probably the more developed one, but still missing a lot feature-wise
your one is cpu right?
yes, like almost every game physics engine
i think the only exception is phsycis x
from nvidia
PhysX
but PhysX have no determinism
nah, PhysX is mostly on the CPU
at one point they were going heavy on GPU physics but then they backtracked
"Yes, NVIDIA PhysX can run on a GPU to accelerate physics calculations for games and other applications. It is designed to use the processing power of NVIDIA GeForce GPUs (8-series and later) for effects like destruction, fluids, and other dynamic simulations."
My understanding is that PhysX started out as a way to do physics on PPUs (old dedicated "physics processing units"), and later transitioned to GPU physics using CUDA. From what I've heard, they've kinda phased out GPU simulation for rigid bodies (though I think it does support it as an option), but does run fluid sim and soft body sim and other stuff like that on the GPU
Not 100% sure on what the state of their rigid body GPU sim is though
Also, GPU physics via PhysX is limited to Nvidia GPUs
SIMD constraint solver + BVH broad phase with incremental updates
plus we could adopt some optimisations that rapier also added recently, like a cheaper friction model for 3D that just applies a single tangential Coulomb friction constraint and a twist constraint for each contact manifold, rather than applying Coulomb friction to each contact point separately
I believe Bepu also uses this simplified friction model
It’s hard to optimize a physics library without a concrete application. There’s too many different directions for optimization, all with trade offs.
In my experience, flexibility is often more important than performance, as long as minimum thresholds are met - it’s more binary; there’s some things you can do, and some you can’t. It doesn’t matter much if you make the things you can do faster, unless that makes something else possible, like walls modeled as individual bricks instead of slabs. The rule of thumb is that these sorts of changes require 10x improvements.
Although these can build up over time. I guess my point is that a small (2x) difference in performance shouldn’t be a big deal unless there are no other differences.
i am just asking cause one of requeriments to avian be added on bevy is being as fast as rapier
Is it? Being "as fast as rapier" seems like a pointless requirement. Avian has some major limitations atm, but once we fix those it should be good enough for a majority of all game uses
IIRC that's something that Joona self-imposed 😛
Well yes, but I don't think Jondolf's intent was "it needs to be faster than rapier 2 years from now"
Like we already outperform rapier from when avian released now, I think. But Jondolf said that was a goal later than that, and there are some major flaws rapier didn't have but avian did
Like how making many many static colliders destroys performance even though they won't collide with eachother
heh I remember
(Easy enough to fix with a BVH)
I say like slapping a BVH into avian is easy when my PR is still open
-# Send help
I remember when collider transform propagation used to go through all hierarchies even if there were no colliders, and people with deep hierarchies like skinned meshes got single digits FPS
good old days
🙏🙏🙏
I should probably get my PR into a state where someone that actually knows parry can throw the last bit in and we can merge it 🤔
many many static colliders
how many is many many?
Most people that reported issues had over 10k
It's mostly because it scales exponentially
It exponentially scales a few trivial checks just to early out against all other static colliders
hmm, in the broadphase?
Yep!
Having a BVH and only searching collisions for entities that could collide, would massively speed this case up, while providing a slightly smaller speedup for many dynamic-dynamic entities
Aaah that will improve matters significantly! I'm always surprised how well sweep and prune performs, seems like it shouldn't be quick.
The scaling of a BVH is much more efficient than what we do either way, but it might be slower on really small purely dynamic body worlds
so fluid sims?
I mean I'd make a fluid sim seperately
Also fluid sims don't have small numbers of entities usually!
my game turns into a fluid sim when there's too much debris tbh, I don't think it's an uncommon case
ok I'm not sure if this is a known issue, but I have a disabled entity with a disabled collider as a child. When cloning that entity the positioning gets all messed up
commands
.spawn((Disabled, Transform::from_xyz(0.0, 10.0, 0.0))
.with_child((Disabled, Transform::default(), Collider::sphere(0.5)))
if I clone this, it results in the child being position at global 0,0,0
when I don't insert the collider and then clone it, the child ends up at global 0, 10, 0
yeah that's kind of a self-imposed requirement I guess 😛 but Avian is often slower than Rapier, and Rapier is slower than Box2D (which is kinda my holy grail of game physics), so it would be neat to be in the same ballpark at least in terms of scalability
ignoring raw performance numbers, especially our broad phase is kind of abysmal and simply does not scale well for large scenes even if they're completely static, which I would not want for "official" physics
but yeah, once we fix those few remaining bottlenecks and ideally add SIMD, we should be pretty good on the performance front
I think I could get the BVH stuff finished in a week or two, but that'd be a week or two of not working on Peck 
I'd like to stay focused on Peck until I've made the repo public, mainly I just need to fix up my 2D EPA, clean up some APIs and docs, and add convex polygons and polyhedra (and probably compound shapes)
I would then consider it "usable", though stuff like trimeshes are missing atm
finishing the BVH stuff would probably be my next priority though, besides helping Jan with KCC work where needed
i mean so far i saw its
it was on the list they sent here
who is "they"
i dont remember, hey jondolf do you play make avian stateless on future? cause on the way its rn it sucks for rollback right?
I will aim to support using less state, but not "stateless" by default since that inherently tends to be much slower and less stable
i see
Fast and stable by default but optionally cross platform deterministic and stateless seems like the right approach tbh
But yes I want to support networking scenarios better, whatever the details of that end up being
cross platform deterministic is a thing already i guess
Is there a way to retrieve the size of a collider after the component has been inserted ? Say you add a Collider::rectangle(), can you then get the physical size of the collider from a query ?
Here's my attempt at multiplayer pong with ggrs + avian: https://pongstr.codeberg.page/ I have no desyncs issues on desktop but with wasm it's bad.
can downcast the shape
hmmm seems rigid bodies don't like being disabled using bevy's Disabled component
have you tried using https://docs.rs/avian3d/latest/avian3d/dynamics/rigid_body/struct.RigidBodyDisabled.html ?
A marker component that indicates that a rigid body is disabled and should not participate in the simulation. Disables velocity, forces, contact response, and attached joints.
yeah I have
the issue is I still need the bevy disable Component
which is what I guess is causing some issues
specifically, if I spawn an entity with a RigidBody and Disabled, then clone it and insert a transform, that transform's translation gets overwritten to be at 0, 0, 0
(rotation and scale stay at the values I inserted)
I think I caught a weird interaction dont know if it should be considered a bug
If you add a RigidBody to an element that already had a rigid body it is transform gets a little cuckoo
An entity with multiples bodies ? 🤔
could be in my case I was just readding static body
because me has no brain juice
thread 'main' (71702) panicked at /home/sirmadeira/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/avian3d-0.4.1/src/dynamics/solver/islands/mod.rs:650:9: assertion failed: island.contact_count > 0
Has anyone else came across with this assertion error?
does anyone know of an example on how know when things collide. im using avian3d and want to have some sound effects when things collide.
Look into the observer API for collisions 🙂
Look at the tainted coders tutorial: https://taintedcoders.com/bevy/physics/avian at the very end there's an example on how to setup an observer.
Avian is a physics plugin for Bevy. It is the successor to Bevy XPBD. Both were created by Joona Aalto (Jondolf) who is on a mission to bring an ECS native physics engine to Bevy.
Hi,
Shouldn't Position and any user-facing components like Rotation, LinearVelocity, etc. only get overwritten if the new value is actually different from the previous one?
For example here: https://github.com/avianphysics/avian/blob/bf498f387977e318ff7be176c33472f1b5963c7a/src/dynamics/solver/solver_body/plugin.rs#L275
Do something like this instead:
let old_world_com = *rot * com.0;
let new_rot = (solver_body.delta_rotation * *rot).fast_renormalize();
if *rot != new_rot {
*rot = new_rot;
}
let new_world_com = *rot * com.0;
let new_pos = pos.0 + solver_body.delta_position + old_world_com - new_world_com;
if pos.0 != new_pos {
pos.0 = new_pos;
}
// Write back velocities only if changed
if lin_vel.0 != solver_body.linear_velocity {
lin_vel.0 = solver_body.linear_velocity;
}
if ang_vel.0 != solver_body.angular_velocity {
ang_vel.0 = solver_body.angular_velocity;
}
This would keep the Bevy change detection accurate.
i think its because avian is statefull
not stateless
Isn't it impossible ? Or you're saying to RB as child ?
I am saying the tranform of the entity acts weirdly, specially if it is a child
I guess I will just insert Position which seems to work
When you despawn an entity which has a Collider, is it immediately effective or can there still be collision events on the next frame even though the entity is about to be destroyed ?
@vestal minnow do you have thoughts on this? https://github.com/avianphysics/avian/issues/887
I don't understand why I can't get the Position of a child Collider to get updated with the parent
Responded briefly
I've been focusing mostly on Peck and Jan's KCC work, so apologies if I'm a bit slow at responding to things 😅
It should be effective pretty much immediately, it won't detect any new collisions
I think you can get CollisionEnd events though if it was touching other colliders when it was despawned
Thank you!
hiiii all! im having an issue where i have two static cuboid colliders right next to each other (to panels in a level im building), where when i roll my dynamic sphere across the seam between the two, there often a little hitch/jump, which seems to be caused by the sphere encountering the edge of the second cuboid, even though it's at exactly the same height as the first cuboid. This seems to be called a phantom collision, and i was wondering if there were any easy ways to prevent this
is there a utility method for collecting a bunch of colliders and combining them into a single voxel grid shape?
do trimeshes solve the problem as well?
iirc trimeshes have a specific countermeasure
there's also a voxels collider iirc? may have weird characteristics
no worries; i think i figured out what's going on
@vestal minnow it's been a while, i haven't really been working on my game much but i've come back to it, and i've still got that problem where disabled hitboxes fall when they're not supposed to, and also trigger the no mass or inertia warning
are you disabling the rigidbody or the collider
the collider
a rigidbody with no enabled colliders has no mass and no impediment to gravity
try telling it to sleep maybe
btw is it a good approach for a sword to enable and disable the collider and sprite when not being swung? for a terraria style swing
how do you do that?
insert the Sleeping marker component
feels like more of a kinematic + sensor situation
i remember seeing several Disabled-related bugfixes, possible that's related
what was the previous and/or intended behavior
the sword would become visible, and retain its position relative to its parent
turn off gravity or make it kinematic then
though overriding its Position with its Transform+Parent does sound like a reasonable handling of the situation
any clue why im getting really unstable behavior at first with these revolute joints?
relevant spawner code:
let wheel_entity = {
cmd.spawn((
RigidBody::Dynamic,
Collider::cylinder(wheel_radius, wheel_thickness),
Mass(10.0),
Friction::new(0.9).with_combine_rule(CoefficientCombine::Max),
CollisionLayers {
memberships: InteractionLayer::Car.into(),
filters: InteractionLayer::Default.into(),
},
Transform::from_rotation(Quat::from_rotation_z(
std::f32::consts::FRAC_PI_2,
)),
))
.id()
};
cmd.spawn((RevoluteJoint::new(target, wheel_entity)
.with_local_basis1(Quat::from_rotation_y(std::f32::consts::FRAC_PI_2))
.with_local_basis2(Quat::from_rotation_x(std::f32::consts::FRAC_PI_2))
.with_local_anchor1(Vec3::new(
(half_width + wheel_thickness) * x_sign,
0.0,
half_depth * z_sign,
))
.with_local_anchor2(Vec3::ZERO)
.with_hinge_axis(Vec3::Z),));
it seems kinda random, sometimes it spawns in without issue
Hi folks! I'm facing an issue and I'm unsure if it comes from the library or some issue with how bevy deals with custom Disabled components.
Let me break down the issue:
- I'm registering a custom
Disabledcomponent that I add/remove on aStatechange for entities matching a certainQueryFilter. - These entities have a
Collider(at least most of them). - I'm spawning other entities that also have a
Collider, andCollidingEntitiescomponent. - I run a system that will process any collisions with these entities by iterating its
CollidingEntitiesand doing stuff (like, for example, damaging the other entities). - Everything works normally until I add and remove this custom
Disabledcomponent. After that,CollidingEntitiesin my damaging entities always contains 0 entities.
Is this a known issue or is this a typical problem with these custom disabled components that the bevy docs warns about? Thanks a lot in advance!
I think its an avian bug?
A playtester was playing and I wasn't looking so I have no idea what caused this
ah okay in case anyone is wondering, i ended up disabling the joint and running the sim, and saw that the transform was not matching up for where the joint expected it, i assume leading to some crazy impulse forces to solve. After using transforms to place things correctly it stablized
Is the joint solve order in Avian fully deterministic?
thread 'main' panicked at /usr/local/rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:1995:13:
swap_remove index (is 0) should be < len (is 0)
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace
Encountered a panic in system avian2d::collision::narrow_phase::update_narrow_phase<avian2d::collision::collider::parry::Collider, ()>!
Encountered a panic in system avian2d::schedule::run_physics_schedule!
Encountered a panic in system bevy_roll_safe::schedule::run_schedules!
Encountered a panic in system <bevy_ggrs::GgrsPlugin<bevy_ggrs::GgrsConfig<u8, matchbox_protocol::PeerId>> as bevy_app::plugin::Plugin>::build::{{closure}}!
I've seen this panic a few times now, just wanted to share it.
Also getting some panics with "Contact pair not found in graph: ContactId(0)".
Considering ggrs is involved here ... Do the ContactGraph and ConstraintGraph get rolled back?
Hi. I've just disabled rollback of ConstraintGraph and the panic doesn't happen anymore.
I was trying to understand the role of ConstraintGraph
ContactGraph can't be rolled back as far as i'm aware
Iirc those two are linked in a way. If things are contacting this creates constraints to solve, and other things like joints also create constraints, thus if you roll back one you need to roll back both
Not rolling back either also sort of works but I think that can cause determinism issues
Ok, interesting.
@vestal minnow I'm done triaging Avian 
There's a whole bunch of issues like "hierarchies of colliders do something unexpected" and there's not really a label for that
specifically for the ECS-ness of stuff
Like how things behave in Children hierarchies, how it interacts with Disabled, things about required components...
Maybe an extra label would be good
Then there's a whole bunch of issues that are "I have ghost collisions"
not sure what to do with those?
Is it really just for cubes? What should I use if my world is procedural, but more "smooth"
Trimeshes or convex decomposition is usually what you'd do there
That said, I didn't have great luck with that personally in the past, which is part of why my SDF collisions exist now
Thank you! 💚 super appreciated
Yeah I guess maybe A-Transform for transform problems, but we don't really have specifically a hierarchy label
Hmm, not sure... There's not too much we can do about ghost collisions, beyond providing shapes that don't suffer from them (which we already have for meshes and voxels), and maybe adding something like Jolt's "enhanced internal edge removal" (#612)
We might just want to create some centralized issue that we link to from all the scattered issues, and close those ones
And also have a good section on ghost collisions in docs
Yep I think it would be good to close those 5 or so issues and link to a single issue
Not yet because it uses Query iteration order, which isn't guaranteed in Bevy. It will most likely be reworked though to not use queries for the core solver, since we need that for graph coloring and SIMD optimizations anyway. So it should hopefully get fixed in the future
The joint solve order should only cause problems for joint chains
Ex: if you have two bodies connected by a joint, and those bodies don't have any other joints, it should be fully deterministic even if joints exist elsewhere in the world
Other than that, I'm not really aware of determinism problems in Avian, other than how networking can complicate things
I believe that should only happen with the dev profile and not in release builds luckily. But yeah, looks like an Avian bug, that should ideally be normalized there
ah the reason I was asking was because I was interested in doing an animation system like Embarks where they use reinforcement learning + physics to drive their characters. I was thinking if I had that animation system + multiplayer then that determinism would be useful. Thanks for the answer!
How should I approach making the movement system(something simple, like just flying including collision). I've added trimesh collisions to my chunks, and a sphere collider to my character. How should I now move the character in a avian way?
accelerate it
up to you whether to pay attention to mass or existing velocity
If you want a dynamic rigid body, just add a force
if you want a kinematic rigid body, you have good timing: https://github.com/avianphysics/avian/pull/894
I've added LinearVelocity component, and set velocity with:
for (mut player_transform, _player, mut linear_velocity) in player_query.iter_mut() {
//player_transform.translation = player_transform.translation + temp_translation;
linear_velocity.0 = normalized_direction * 200.;
}
But the character didn't move
Collider::sphere(5.),
RigidBody::Dynamic,
LinearVelocity::default(),
These are the avian components I have on a given character
from the example that PR adds
is that in FixedUpdate?
Yes
then it should work imo 
Is having other components, like Transform::from_translation(Vec3::new(32., 32., 32.)), could impact how avian works?
does it wake the body
entitycommands.remove::<Sleeping>(), yk
happens automatically with the forces querydata
Still nothing
for (entity, mut player_transform, _player, mut linear_velocity) in player_query.iter_mut() {
//player_transform.translation = player_transform.translation + temp_translation;
commands.entity(entity).remove::<Sleeping>();
linear_velocity.0 = normalized_direction * 200.;
}
and normalized_direction isn't zero?
Nope, printed it a while ago just to make sure
can you try applying a force instead? with Forces
no
Still nothing:
mut player_query: Query<(Entity, &mut Transform, &MovementComponent, Forces)>,
for (entity, mut player_transform, _player, mut forces) in player_query.iter_mut() {
//player_transform.translation = player_transform.translation + temp_translation;
commands.entity(entity).remove::<Sleeping>();
let mut velocity = forces.linear_velocity_mut();
*velocity = normal_dir * 200.;
//linear_velocity.0 = normal_dir * 200.;
}
...lol
A trait for applying forces, impulses, and accelerations to a dynamic rigid body.
Still nothing
Hmm... I think I know why
Does Forces need to be explicitly added into entity?
If I add Forces to query it no querries 0 items
no
should be automatic for any rigidbody
Then I think for some reason its not being added
This is how I spawn the player:
let player_entity = commands.spawn((
Player {
velocity : Vec3::ZERO,
gravity : 9.8,
speed : 20.0,
},
Transform::from_translation(Vec3::new(32., 32., 32.)),
Visibility::default(),
MovementMonitor::new(Vec3::new(32., 32., 32.)),
MovementComponent { },
Collider::sphere(5.),
RigidBody::Dynamic,
LinearVelocity::default(),
LocalEntity,
)).id();
shouldn't need LinearVelocity either
Should it be ForcesItem instead of just Forces?
what if you remove whatever Player::{velocity, gravity} is for
nothing
is the repo public somewhere
Unfortunately not
But give me a sec, I will prepare a public one
Ok, I found the issue
Finally
Ofc. it was something very stupid
Missing PhysicsPlugins::default()
Ok, collisions work
But, how can I disable them? I've noticed that with lot of chunks the colliders add up to lag condireably
happens
ColliderDisabled, or make sure they're all static
Or? They are all static, but I wonder if just the sheer amount of vertices is not just impacting the performance, bcs. after adding ColliderDisabled component it doesn't change anything in terms of performance.
Should I add collider on the fly when player enters new chunk, or am I doing something wrong?
Can you say a little more about your SDF collisions? Are they integrated with Avian, or are they completely different systems? Does it integrate good with dynamic terrain, that can be e.g. digged?
Bet it’s lighting. Disable all shadows and try again to confirm
Avian allows one to define custom collider types. Using that I defined my own collider type for avian to use. In theory I could have support for digging, though I currently only implement signed distance functions, rather than the field that would allow for comtinuous destructive modifications of the terrain
@vestal minnow was working on portals yesterday and noticed that if i try to teleport in an observer it just never teleports, but if i stick it in a System it works perfectly
Now that I know that the camera jitter issue is related to updating transforms between physics steps, i can intuit that this is probably the same thing, but it does raise the question.
If i DO need to make arbitrary modifications to the transform of a physics object, what is the correct system timing to do this in?
on the docs it says to do it in PostUpdate but before the transform propogations, but in my case just running the system in Update fixed everything so im not sure if the PostUpdate rule is more so like "A known safe timing" or if its actually genuinely needed and i just got lucky.
I think that might be an old reccommendation. Avian used to run inPostUpdate by default, but that's FixedPostUpdate now, which runs before Update
What event is your observer responding to?
Do you want the teleport to be interpolated or not?
for portals, probably not, right?
If you teleport in FixedUpdate, it will work, but it will also interpolate, which is not what you want here
I'm not sure which schedule is best for what you want 
Maybe you could use FixedUpdate and yeet the interpolation components manually on those ticks?
This feels like the correct approach since portals are part of the simulation, not a purely visual thing
yep agreed
You'll probably want to query for https://docs.rs/bevy_transform_interpolation/latest/bevy_transform_interpolation/struct.TranslationEasingState.html
Stores the start and end states used for interpolating the translation of an entity. The change in translation is smoothed from start to end in between FixedUpdate runs.
I think that one is not re-exported by Avian, so you'll have to add a dependency on bevy_transform_interpolation
Which, to be clear, you already have anyways transitively
maybe just setting start to None in your teleportation tick could work
i mean it was working fine in a regular update with interpolation, so maybe just chuck it in a post update is the go?
less so looking to fix a problem since its already solved and more so looking for "Whats best practice here" and to understand how i solved it (since really i just threw something at the wall and it stuck
)
I assume your observer was something like a collision event?
That sounds like the wrong update loop though. Why would you want to tie teleportation to your monitor's refresh rate (assuming VSync)?
exactly the case yeah 
Maybe take a look at https://bevy.org/examples/movement/physics-in-fixed-timestep/ 🙂
I'd imagine all you need to fix those is buffer the change till after physics, or maybe change Position and Rotation directly instead of Transform
But ofc if you have interpolation that can be its own problem to solve
thats probably how it actually got fixed, because i didnt move the collision into a system, i had it emit a teleport event that i read in an update.
So it wouldve had a built in 1 frame lag between the collision and the teleport 
The event would probably get picked up by the Update later in that frame, but it could cause issues if your FPS dropped en you ran a couple of FixedUpdate loops in one frame
Ideally the change would get processed in FixedPostUpdate after physics ran, or try that Position/Rotation thing so the physics immediately respond to it 🤔
FixedPostUpdate sounds fine actually.
if it runs after the physics systems id be able to read the collision event in a system instead of an observer and do the transform with 0 frame delay right?
Yep
aight yeah ill just do that then.
does feel a bit weird moving gameplay systems that touch transforms directly into a PostUpdate schedule, since yk, postupdate atleast by the definition should be for stuff that responds to updates, like cleanup or engine stuff ykyk.
But it is what it is 
NotShadowCaster,
NotShadowReceiver
I've added these to my chunk's entity, but its looks like shadowing is still there
It needs to be on the entities that hold Mesh3d
Yes, it is
Also, if you're dealing with a large stretch of voxel terrain, you're probably gonna want to do some LoDs, only have colliders on chunks that are nearby, etc
If you update them often you also get problems like how trimesh colliders are slow (but immediate), while convex decomp is fast but needs some time to process, you can use this to your advantage by swapping new chunks out with trimeshes, then processing them in the background and putting the more efficient collider when done
Similarly when loading new chunks
Also, everything performs better with less veritices, so running a simplification pass on your meshes might be worth it too
Huh, weird 
By simplification pass you mean some authomatic config that is built in with bevy, or custom made?
I think there were a couple of third-party plugins for it at least
@vestal minnow do RigidBodys not get Position and Rotation if their colliders are children? 
oh wait Colliders are also not getting those either in my test
I guess I set the test up wrong hmm
Ooooh I see, I forgot
.insert_resource(TimeUpdateStrategy::ManualDuration(
Time::<Fixed>::default().timestep(),
))
Hello, I do not found an equivalent of CollidingEntities that also match when a collider if fully inside the second, does one exist or does this ability need to be implemented by hand with the collision triggers (On<CollisionStart> & On<CollisionEnd>) ?
It behaves as you expect if you don't use trimeshes
trimeshes are always "hollow", hence why you don't get a collision when one thing is fully inside another
but try e.g. a convex decomposition and CollidingEntities should report that 🙂
Oh I didn't check the type of meshes, I will try that, thank you 🙂
Gravity is a reasource, not a component O.o?
GravityScale is the component
for per-entity gravity, you can use ConstantLinearAcceleration, just make sure to disable global gravity or use GravityScale::ZERO
Yes, but it reduced the lag
But only if character didn't touch anything. After the touch the lag is gargantuous
does move-and-slide have a lot more overhead than the conveyor belt setup if I'm doing kinda the same thing?
What’s the conveyor belt setup?
Move-and-slide is intended for kinematic bodies, and not integrated with the actual simulation loop, I'm not sure how you'd use it for this
Perf-wise, it does some shape casts and computes contact manifolds, while with CollisionHooks you're not really doing anything extra beyond your conveyor belt logic
ah, cool. Yeah, I was curious but I think the collision hooks might work better for what I'm doing (using dynamic bodies)
@vestal minnow what are the semantics of changing Transform in PreUpdate?
or not semantics, but rather effects on interpolation
I think it disables interpolation for that frame and respects the new transform, which is what I want
But I find that it weirdly enough doesn't change the position when running on Web 
Very possible this is a user error by me, but just checking in case you know anything about that
I believe that should be correct
but I don't remember if I've tested exactly that setup
i'm currently experiencing this crash and i'd like to debug it but have no idea what might cause it
thread 'Compute Task Pool (8)' panicked at C:\Users\zwaze\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\avian3d-0.4.1\src\dynamics\solver\plugin.rs:398:51:
index out of bounds: the len is 1 but the index is 1
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `avian3d::dynamics::solver::plugin::prepare_contact_constraints`!
Encountered a panic in system `avian3d::schedule::run_physics_schedule`!
Encountered a panic in system `bevy_app::main_schedule::FixedMain::run_fixed_main`!
Encountered a panic in system `lightyear_prediction::rollback::run_rollback`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
any idea?
i use ligthyear and have PhysicsInterpolationPlugin, PhysicsTransformPlugin and the IslandPlugin disabled for it
Well it is a badly checked wrap, wher3 it expects a collision but it doea not exist
Guess you could just handle it?
the panic comes from avian directly
i'm just wondering what might cause it, like am i missing a component? its definitely lightyear that causes it as only the client crashes but the host is fine. so i'm trying to figure out what is missing
are the ContactGraph and ConstraintGraph being rolled back differently
Hi guys I have a little confusion here
struct Player;
#[derive(Component)]
struct PressurePlate;
fn setup_pressure_plates(mut commands: Commands) {
commands.spawn((
PressurePlate,
Collider::cuboid(1.0, 0.1, 1.0),
Sensor,
// Enable collision events for this collider.
CollisionEventsEnabled,
))
// Observer for responding to collisions starting with the pressure plate.
.observe(|trigger: Trigger<OnCollisionStart>, player_query: Query<&Player>| {
// The trigger target is the entity that the observer is targeting.
let pressure_plate = trigger.target();
// The `collider` stored in the event is the entity that the target entity collided with.
// There is also a `body` field for the rigid body that the collider is attached to.
let other_entity = trigger.collider;
// Check if the entity colliding with the pressure plate is a player.
if player_query.contains(other_entity) {
println!("Player {other_entity} stepped on pressure plate {pressure_plate}");
}
});
}```
in this code: player_query return a query of Player component, but in the if statment player_query .contains take a entity?
so what contains do exactly?
contains checks if an entity matches a query, rather than actually fetching the data for the query
I'm trying to setup Avian to run server side. Right now my server side code just runs with bevy MinimalPlugins and StatePlugins. Avian crashes as there are resources, etc missing which I imagine get setup when you use the DefaultPlugins in bevy. I was wondering if anyone could point me to a resource, or let me know what the minimum Plugins they needed to use to get Avian working on the server side. Thank you.
I think it might depend on the features you have enabled on avian. Avian with milimal plugins works for me iirc
I'm initializing avian with PhysicsPlugin::default(). In my code I'm only trying to add a Collider and RigidBody
My guess is it would be complaining about things like meshes or asset events not existing because things like processing of colliders from meshes are enabled by default 🤔
Encountered an error in system avian3d::collision::collider::cache::clear_unused_colliders: Parameter MessageReader<AssetEvent<Mesh>>::messages failed validation: Message not initialized
If this is an expected state, wrap the parameter in Option<T> and handle None when it happens, or wrap the parameter in If<T> to skip the system when it happens.
Yes, you're correct
Gonna want to set the features for avian to the minimum amount in your Cargo.toml I guess
Something like this:
avian3d = { version = "0.4", default-features = false, features = ["3d", "f32", "parry-f32", "default-collider", "xpbd_joints"] }
Ok, I'll give that a try. Thank you!
I'm playing with the tnua character controller with avian2d, using tiled maps. I'm using a RayCaster to detect entities within a certain distance, which works. I add objects in the map with the tiled editor.
It seems that for each tile, object, .. in the tiled map, there isn't 1 but 2 entities, the tile entity and another one. I'm using bevy_ecs_tiled. The RayCaster query hits an entity but not the one i'm looking for.
fn detect_portals(
portals: Query<Entity, With<Portal>>,
mut rays: Query<(&mut RayCaster, &mut RayHits)>,
mut gizmos: Gizmos
) {
for (ray, hits) in &mut rays {
let origin = ray.global_origin().f32();
let direction = ray.global_direction().f32();
for hit in hits.iter() {
gizmos.line_2d(origin, origin + direction * hit.distance as f32, GREEN);
if portals.contains(hit.entity) {
info!("We're close to a portal: {:?}", hit.entity);
}
}
}
}
Is the RayCaster on the same entity as the character's collider? If it is, then it should ignore it by default, but otherwise you might be hitting the player's own collider
Either way I'd try to figure out what the "other" unwanted hit entity actually is
It could be that tnua is also adding its own sensor collider or something that you're hitting, I don't remember if it uses colliders or just spatial queries
Yes, the RayCaster is on the same entity as the character's collider, and it's not hitting the player's collider. The RayCaster looks for any entity with a Transform, a RigidBody ? Will try to figure out if the issue isn't related to the very recent 0.10.0 release of bevy_ecs_tiled.
It will look for any Collider in the scene along the path of the ray
I've found a solution. Insert a collider on the entity when the map is loaded. Can now do raycasting on things defined in the tiled map. Thank you!
Is there a built-in way to write something like "acknowledge collisions with layers a and b, unless the collider has collision layer c"?
i don't think the current system can collide with some layers l but not l|c
it's "any filter of a overlaps with b AND any filter of b overlaps with a"
Hey, so there is this wireframe-blink-on-contact thing and I am not sure if this is normal and how I would disable it...been searching for an hour but somehow to blind to find any mention/config about it... :/
at some point you're removing Sleeping but not resetting the SleepTimer so it keeps sleeping for one tick every time it elapses
sleeping bodies have dimmer wireframes
oh nice, I did not think about frame stepping a recording, thx :p
hmmh I'm not doing anything with Sleeping or SleepTimer at all, something else has to manipulate it
what's the character controller
ohh
fn movement_damping(mut query: Query<(&MovementDampingFactor, &mut LinearVelocity)>) {
for (damping_factor, mut linear_velocity) in &mut query {
linear_velocity.x *= damping_factor.0;
linear_velocity.z *= damping_factor.0;
}
}
This is basically copypasta from the dynamic_character_3d example, it causes this apparently
thank you a ton :)
o7
Ghost collisions are so annoying 😭
indeed, we should at some point write down a section in the FAQ dedicated to them
Is there a way to get the area of a parry3d shape ? m2 or others or i have to implement it myself on the shapes ?
You can get the volume if that's what you mean, but surface area doesn't have a built-in helper except for maybe a couple of shapes
To get the volume, you'd just compute the mass given a density of 1, because then volume = mass / density = mass / 1.0 = mass
For a Collider:
let volume = collider.mass(1.0);
For a Parry SharedShape:
let volume = shape.mass_properties(1.0).mass();
Good evening. Another question about tiled maps, avian2d and tnua. I use tnua to control my character. I've just added moving platforms. I can stand on the platform but the character doesn't move with the platform, it stays in the same position while the platform moves. Definitely related to the fact that tnua is a floating character controller isn't it ? Anyone familiar with tnua here ?
The platform's RigidBody is Kinematic
When the character is in crouch position, the character's collider and the platform's collider intersect.
maybe related to Friction ..
Ok i've found some documentation on this: "Moving platforms can be implemented by updating the Position or Transform of a kinematic or static body. For platforms that carry dynamic bodies, ensure that collision response is handled so that passengers move with the platform."
Just need to implement the second part with a system then.
That's weird - Tnua should be able to handle that. The moving platform in the Avian 2D demo is a kinematic rigid body, and the character moves along with it without having to crouch.
Is your code uploaded anywhere public?
check that the platform is moved using velocity
Hi and thank you. Code not uploaded anywhere yet.
LinearVelocity ? I haven't added a velocity component for now.
Will use LinearVelocity to see if it makes a difference.
Doesn't a kinematic rigid body that get moved by altering its position also automatically get its velocity updated? Or is that only in Rapier?
no idea, but if they're using tnua that might be the issue
In the tnua repository, in the 2d platformer demo, there's a MovingPlatformPlugin.
Wow!
With LinearVelocity, it works !
@sweet sundial Much respect, thank you.
np
otherwise you're basically teleporting the platform
Rapier has separate RigidBody::KinematicVelocityBased (move with velocity) and RigidBody::KinematicPositionBased (move with position) for this, but we don't have a position-based version yet
You can easily do it manually though by just setting velocity to (target_pos - pos) / dt
I wish for detecting collisions between specific entities you could do On<CollisionStart, insert entity here> instead of checking if a query contains them
hmm, that would mean triggering that event for every collision start even if you don't care, right?
Couldn't tell you myself 😔
there is https://docs.rs/avian3d/latest/avian3d/collision/collider/struct.CollidingEntities.html which keeps track of entities that are currently colliding with a given entity.
A component for reading which entities are colliding with a collider entity. Must be added manually for desired colliders.
did you already saw newtow dynamics @vestal minnow ?
Newton or specifically Newton Dynamics
https://github.com/newton-physics/newton
https://github.com/MADEAPPS/newton-dynamics/
I know they exist but haven't looked into them too much
Newton Dynamics
you should take a look for some idea, its pretty good, 100% deterministic between plataforms and its somehow not stateless
stateless or stateful
Avian and Rapier also support cross-platform determinism and are stateful
wait, but a time ago here we said its not possible to do roolback with it
rollback determinism is different from cross-platform determinism
Box2D is also cross-platform deterministic but not rollback deterministic
You can do rollback with both Avian and Rapier, it's just not trivial to get it working nicely and with Avian you need to disable some things
like simulation islands and maybe warm starting
and roll back resources like the contact graph and constraint graph
you know, how about just have a way to force island simulation and warm starting when you want?
cause after all its just values
The problem is mainly the persistent state. Islands are persisted across frames, and if the data is not correct or up to date, your program can crash, and it's hard/expensive to roll back all that data properly and keep everything in sync across clients
i see, wise jondolf
We'd ideally want to rebuild islands from scratch each frame with something like Jolt's parallel union-find algorithm, so you don't need to cache any of that state or send it over the network
jondolf, iam excited to see your work
which is slower in performance, but plays nicer with networking
how about warm?
like i wanted to know wich States right now are problem for roolback, just Island and Warm?
warm starting (=initialize the contact solver with the previous frame's impulses) is the second problem yeah, I feel like you should be able to just roll back that data but IIRC it didn't work for some people, so I'm not sure
you can disable it if you need to, at the cost of having worse stability for stacking scenarios (like a stack of blocks)
yeah i see you have some trouble with stacking scenarios xd
Newton Dynamics also fixed it, idk how, but it have no problem with shake, well i wont take lot of your time iam being annoying xd, gl bro, hope avian get implemented into bevy officialy soon @vestal minnow
Can I find somewhere complete documentation on collisions? I want to know what options I have available
collision events? collision hooks? collision graph? or just https://docs.rs/avian3d/latest/avian3d/collision/contact_types/struct.Collisions.html
A SystemParam for accessing and querying collision data.
Ways to create collisions. I know there is an automatic way to do this with CoACD, but I think I would prefer something manual, like extracting collision from premade low poly mesh in blender
you mean colliders?
Yes
you could go with https://docs.rs/avian3d/latest/avian3d/collision/collider/struct.Collider.html#method.trimesh_from_mesh , though it's hollow
A collider used for detecting collisions and generating contacts.
or for something much more advanced you could impl AnyCollider yourself
What do you mean "hollow"? If I have e.g. cube taken straight out of blender will it affect anything?
iirc the bevy-blender toolkit has the ability to define components on objects, so you could use the reflectable collider constructors for primitive shapes like that
A component that will automatically generate a Collider at runtime using Collider::try_from_constructor. Enabling the collider-from-mesh feature activates support for computing the shape dynamically from the mesh attached to the same entity.
don't know about the toolkit though
anyone have a problem where a falling collider (like a character falling post-jump) "intersect" the ground colliders by a pixel for like a few frames or so?
it's such a subtle issue physics-wise but it really affects my character control, e.g. all horizontal velocities are reset to 0, and it can't jump again instantly because its y velocity from the jump impulse gets immediately overridden
what controller do you use? that sounds more extreme than would normally happen with just physics
my custom-made one...but at this point i should just use existing ones in the bevy ecosystem
i'm not too keen on adding even more dependencies but it is what it is
the red one prints every frame if i hold down the jump button mid-air
the yellow one prints when it initiates the jump
now in the case where i press the jump button and hold it till the character lands, i'd expect it to jump.
which it "does", because that jump! gets printed
except at that frame the character collider is intersecting with the ground collider, so the velocity gets cancelled out
what cancels that velocity, though? ramp countermeasure or something?
i really don't know
you can see that when she lands, for a moment her collider is 1 pixel inside the ground
could maybe try turning up speculative collisions
-# ... i wonder if integer coordinate avian is possible
speculative margin is already at MAX tho?
adding SweptCcd fixes the collision though, ...but the velocity is still reset somehow
... hey, isn't the down momentum at the end of a jump exactly equal to that at the start with reversed direction?
you might be perfectly cancelling your fall
can try logging the velocity right before and after adding the impulse
i applied linear_velocity_mut() directly though
sure, one sec
wait that makes sense
i might be adding the velocity when it was still falling
...well changing it from += to = didn't change anything, so i'm not sure
better to check it now before trying to find things elsewhere that might touch velocity at that moment
okay yeah lmao
this did work; i realized i changed this one line to account for jump buffer without actually adding the jump buffer logic yet
not to keen on the = part though, that might mess things up if i wanna add some things like moving elevators
can branch on the sign of the existing velocity, or vel = vel.max(0.0) + dv;
i do a lot of "if it's going the wrong direction, fix that; otherwise just add"
i see, thanks for the suggestion
what about elevators moving downward though? she would jump way higher than she should
ehhh it's probably fine, that's what most players would probably expect
could make the reference the relative velocity of the object she's grounded on
ahh like Query<&LinearVelocity>ing the ground entity?
arghhhh Forces mutably borrows LinearVelocity so i can't make the query
can just query its Forces then :p
the Forces query is already par_iter_mut()-ed d:
oh no no wait i could just store the velocity on the grounded check instead
par_iter on a player's component sounds a bit unoptimal
all my enemy entities will share the same controller component
with mocked action values
so my AI components in the future could just tell the entity where to move and not worry about how they move
fair enough
Hello! I probably misunderstand something, but how many times does this move the character controller? E.g. if there are 4 points, each 1 meter deep, the character controller will be pushed 4 meters instead of 1 meter, isn't it? Perhaps I just don't understand contact manifolds correctly (couldn't find a proper image of it) or something else.
does Dominance affect joints? or the better question, is there a way to make joints completely avoid applying forces to the first body? i'm trying to make a nice-looking hair with distance joints and they always end up messing my player's movements
oh whoa it actually does!
can you explain what you did? I was trying to do something similar to have objects hanging off a vehicle that swing around but don't affect the vehicle's physics
add Dominance(-1) to the hanging object-- however, i scrapped that solution for a manual verlet integration because the joints were so unstable
unstable how?
and verlet integration?
unstable how?
i should've recorded it but oftentimes the joint entity would stretch really crazy and actually cause a panic due to invalid operations
and verlet integration?
https://github.com/mattatz/unity-verlet-simulator
you made a version of this that works in Bevy?
nope, i'm just a high schooler struggling with high-level physics 👍
rn i'm just asking chatgpt for a general algorithm and write my own rust version to my Hair component
lol the next Jondolf
you're way too kind
could be useful if you manage to get something working. I made a game with joints that were used to attach limbs that swung around and it worked pretty well but I do remember struggling a bit with some instability at first and then when I tried doing it on the vehicles it was unstable and also affected the vehicle so I set it aside. Wonder if something changed.. I'll post something here if I get time to try again and make some progress
When you use a RayCaster (with Dir2::X, horizontal) with a circle Collider, is it normal if the ray isn't horizontal but points down a bit ?
As the character moves, the circle collider seems to "roll", and the ray starts to point towards the ground.
Doesn't happen with a rectangular collider, definitely linked to the collider's shape, makes sense.
you can add LockedAxes::ROTATION_LOCKED
@wet niche thanks for the pointer to modify_contacts. What a powerful feature. I've been having a great time implementing destruction physics. Finally crashing has severe consequences!
Thanks !!
How can i apply an impulse on spawn to rigidbody at specific point on rigid body ?
Hello. I'm trying to use new MoveAndSlide algorithm to implement a character controller. I've copied the example code and tried to add gravitation. But now it simply slides along the ground even though I've added the Dir::Y plane to config. Below is the code and video demonstration of what happens. What should I change to make it not slide and stand still when it's grounded?
// in `run_move_and_slide` same as the system in the examples
&MoveAndSlideConfig {
planes: vec![Dir3::Y],
..default()
},
// system to apply gravity
fn apply_gravity(time: Res<Time<Fixed>>, mut controllers: Query<&mut LinearVelocity>) {
let delta_time = time.timestep().as_secs_f32();
for mut linear_velocity in &mut controllers {
linear_velocity.0 += 9.8 * delta_time;
}
}
// regestrations
.add_systems(
FixedUpdate,
(player_movement, apply_gravity, run_move_and_slide).chain(),
)
That system is applying a gravity of Vec3::new(9.8 * delta_time, 9.8 * delta_time, 9.8 * delta_time) to the linear velocity
you want to just apply it to the y component
I'm also not sure why you're applying a positive (=upwards) gravity unless your y-coordinates are flipped 🤔
ah yeah um yeah
i'm stupid
Do colliders no longer scale according to their transform in 0.4?
my asymmetrically scaled sphere's still working
Yeah it should work
By the way, for those not on the Avian Character Controller Working Group server, there was a kind of mini-revolution and it was rebranded to a more general Avian Dev server 😄
https://discord.gg/xJaYNZvd
The general Avian community and user questions will remain here on the Bevy server and in this #1124043933886976171 thread, and upstream physics discussions will still be held in #physics-dev
So not much has really changed, this is just a kind of smaller sub-community for discussing the development of Avian and related crates (like Peck, or Jan's bevy_ahoy KCC) and collaborating there, or for discussing any other interesting physicsy things
A bonus is that you get the Avian feather as an emoji by being on the server 😛
Is this code wrong ?
#[derive(EntityEvent)]
pub struct TeleportEvent {
pub entity: Entity,
pub destination: Vec3,
}
fn on_teleport(
event: On<TeleportEvent>,
mut transforms: Query<&mut Transform>,
) {
if let Ok(mut transform) = transforms.get_mut(event.entity) {
transform.translation = event.destination.clone();
}
}
I trigger teleport events when an entity collides with a portal, "destination" being the coordinates of the place the portal sends to. The event is triggered, the transform is changed, and the entity isn't moved.
when in the schedule are you sending these events
I send the event from a collision observer.
The entity isn't moved, and keeps bumping on the portal's collider.
I'm not changing this entity's transform anywhere else in the code
try updating Position instead
Hmm is Position part of avian ?
yes
Ah so avian uses Position internally
depending on when the observers are triggered, the position+rotation/transform sync systems might ignore one or the other
It's working. Can't thank you enough.
So mutating a Transform with avian entities is wrong.
works fine with scheduled systems
no, i don't know when that event is sent, but it's probably possible to find out, so i'm looking through the plugins
edit: https://docs.rs/avian3d/latest/avian3d/collision/narrow_phase/struct.CollisionEventSystems.html
When creating collider:
let mesh3d = Mesh3d(meshes.add(Cuboid::new(1000.0, 10.0, 1000.0)));
let mesh = match meshes.get(&mesh3d) {
None => {
return;
}
Some(item) => {
item
}
};
let collider = Collider::trimesh_from_mesh(&mesh).unwrap();
commands.entity(entity).insert((
mesh3d,
MeshMaterial3d(materials.add(Color::srgb(0.5, 0.5, 0.5))),
TestTag,
Block {
display_name: "Test platform".to_string(),
id: 0
},
collider
));
Should I store it somewhere in order to not have to recreate it over and over?
i assume the first line isn't part of the code
you can use a HashMap<AssetId, Collider>
that's worthwhile because Collider is an Arc<dyn Shape>
Is it appropriate to use a momentary circle Collider to represent the explosion of a bomb 💣 ? If the player is in the middle of the explosion and the colliders don't intersect, would that generate a collision ?
if it's not a polyline
most colliders are solid
if you just want whether something would collide with a circle at a location at a precise moment, use a spacial query
or a Sensor on a collider
Nice, thank you.
Hello. Does anyone have an example of integrating the one_way_platform example (https://github.com/avianphysics/avian/blob/main/crates/avian2d/examples/one_way_platform_2d.rs) with proper detection if the entity is on the ground? I am trying to write a system to add Grounded component to the player entity using a ShapeCaster, but it gets complicated when the player is colliding with a one way platform. If they are above the platform, they should be Grounded, but if they are just inside of the platform (ie. not all the way through it on their jump), Grounded should not be added
for anyone also wonder how to do this, I managed to make the ShapeCaster from Collider::segment - so I just made it a horizontal line, with origin at the bottom of the player's collider. Before I was trying to use a ShapeCaster from the player's rectangular Collider, which means it registered hits inside the player, instead of only below the player
Ye, first line is just for the test.
So saving is a good way. thanks
assuming you want multiple colliders from the same mesh at least
can probably set something up to read asset drop events and remove relevant colliders from the map, or just use weak arcs in the map
for optimization
If you want to have two or more RayCaster on an entity, it's best to create child entities which hold a RayCaster, and declare a relationship ? or is there a better approach.
that's probably fine, but in some situations (ie, only need the raycast every so often) spacial queries are better
I'm making a cat platformer game, and the mice detect danger ahead with a forward raycaster, but i'm thinking of adding another one in the opposite direction 🙂
So yeah i'm constantly querying the raycaster in a system
o no
It started happening when I activated the debug plugin (debug collider gizmos and all)
This usually means that stuff has become NaN. Avian doesn't have enough debug asserts to catch these, so the crash usually happens when updating AABBs even though the first NaN appeared somewhere else.
I tracked one of them down in my project, and it ended up being a bug in collision manifold generation, causing my character controller to make a LinearVelocity negative infinity, causing positions to be NaN, causing AABBs to be NaN
huh
It would probably be a good idea for avian to have a debug_assert!(x.is_finite()) every time a component is read or written to the ECS, otherwise it takes so long to figure out where it happens
But no clue why it would happen just because of a debug plugin. Do you have a deterministic way to reproduce it?
Literally just enabling the debug plugin
I did manage to make the debug plugin not crash the app if I dont walk into certain room of the dungeon in my game...?
No idea why tbh
I spent 5 minutes looking at doing that, but it would add so much boilerplate. An alternative is to do as the computed variables (e.g. ComputedMass) and enforce non-NaN/Inf by making the field private and having constructors with debug_assert. That would be a breaking change and a slight hit to ergonomics, but probably what I would suggest.
On another note- I noticed that activating the parent activates the children colliders but not vice-versa. Am I doing something wrong? Is there away to make the children detect the collision?
anyone else running into these errors trying to compile avian?
the trait bound
AngularInertiaTensor: From<glam_matrix_extras::SymmetricMat3>is not satisfied
ok, I just checked out main and did a cargo update and it seems to be working 🤷♂️
@vestal minnow
Hello!
- I am currently using the main branch and the
move_and_slidefunction. The character controller slides down the slopes, is it gonna be fixed? - How can I change max slope angle?
- Is steps climbing gonna be implemented?
- Any ETA on the stable version?
- Is there gonna be complete character controller component?
- We haven't updated the KCC examples in the repo yet, so they still don't use
move_and_slidecurrently. But the plan is to rework them, and also add several new character controller examples (ex: 2D top down, 3D first person...) - The old KCC examples handle slope collision behavior in the
kinematic_controller_collisionssystem, which you'd replace withmove_and_slide, but it doesn't have slope handling built-in. You need to check if the character is grounded (= hitting the ground with a normal whose angle to the up direction is below the max slope angle), and if yes, have some logic to prevent sliding down and possibly also snap the character to the ground if you want to stick to slopes. - Most likely yes
- I believe Bevy is making a 0.18 release candidate in about a week, so I'll probably do a 0.5-rc release for Avian around that time too. It'll have the move-and-slide stuff. A proper 0.5 release will come later, when Bevy 0.18 is fully released
- Yes, the plan is to have a more or less fully featured KCC, with optional slope handling, ground snapping, stair stepping, all that fun stuff. I don't have any specific ETA for this, but I have an early minimal draft for an API already (link), and will try to get the basics working soon-ish
If this is 3D, I can heavily recommend bevy_ahoy by @visual sparrow for a KCC
It uses Avian's move_and_slide and other related things, and is being actively developed with a ton of really cool stuff
- I was talking about this.
Yeah that's just a floating character that you can move around to test sliding against geometry, so yes it's meant to slide down slopes and whatnot, there's no ground handling there
Ok so after hours of debugging I know exactly what's happening but not what to do to fix it.
The small collider is created as a child of a bigger collider. Then, I detach it from the parent (the only thing I do is remove theChildOf component) and reattach it later on.
As long as it has the ChildOf, it detects collisions. When independent, though, it does not.
Why? What can I do to fix it? (even if it's a hack, this collider is crucial for the enemy's main mechanic)
( @vestal minnow )
Not sure if this is the right place to ask but I've been working on a simple platformer game with bevy-tnua, avian2d, and bevy_ecs_tiled:
https://github.com/Rigidity/avian-tnua-platformer-wip
And I keep running into issues with the player colliding with the edge of the floor like it's a wall, for a moment. I fixed all the clipping issues, so now it just disrupts the velocity of the player.
The red rectangle collider doesn't have this issue, but the auto generated map collider(s) by bevy_ecs_tiled do - and as you can see they're combined correctly to avoid ghost collisions (this only happens on the true corners of the map)
Here's a video of it happening
@visual sparrow
Hello! How do I connect bevy_ahoy?
bevy_ahoy = "0.0.1"```
When I write it like this, `kcc.rs` doesn't compile, throws me a dozen of errors.
oh right.
I forgot
gimme a sec 😄
what errors?
oh wait
you need a patch
add this:
[patch.crates-io]
avian3d = { git = "https://github.com/avianphysics/avian" }
does that help?
Now there are only 2 similar errors:
error[E0599]: no method named `depenetrate_all` found for reference `&avian3d::prelude::MoveAndSlide<'_, '_>` in the current scope
can you do cargo update -p avian3d?
or wait
huh
why do you get that 
Oooooh I know why
Yeah don't use the crates.io version 😄
depend on https://github.com/janhohenheim/bevy_ahoy directly
i.e.
bevy_ahoy = { git = "https://github.com/janhohenheim/bevy_ahoy" }
@crisp hazel I think this should cover your problem too
👀 I'll try it tomorrow
It worked, but I still have a problem with actions! macro. If I have use bevy_enhanced_input::prelude::*; in the file, it says there is a conflict, if I don't have it, it doesn't recognize it.
My Cargo.toml looks like this:
...
[dependencies]
avian3d = "0.4.1"
bevy = { version = "0.17.3", features = ["dynamic_linking"] }
bevy_ahoy = "0.0.1"
bevy_enhanced_input = "0.20.0"
bevy_skein = "0.4.0"
[patch.crates-io]
avian3d = { git = "https://github.com/avianphysics/avian" }
bevy_ahoy = { git = "https://github.com/janhohenheim/bevy_ahoy" }
...```
Well, now I have:
error[E0277]: the trait bound `bevy_ahoy::prelude::Movement: InputAction` is not satisfied
Even if I copy that macro directly from bevy_ahoy GitHub page.
try now 🙂
cargo update -p bevy_ahoy
sorry for the trouble, it's all very WIP haha
Also writing a platformer with tnua, avian2d and bevy_ecs_tiled. I also have the same issue but only with rectangle objects. Will look at your code ...
It has stopped complaining! 👍
I understand, no worries! 👌
Take a look at minimal.rs for usage, we don’t have better docs yet 😬
I'll write those once we have mantling and water implemented
Yeah, I am looking exactly there.
Nice! Would you mind giving us feedback when you've set it up? 🙂
I hope the handling feels as lovely to you as it does to us 
Nothing wrong with your code. I use a different collider shape for the player. But i also see problems with the colliders generated from the tiled map.
I guess I'll have to look under the hood.. was thinking it could be using trimeshes and winding vertices in the wrong order
but I also don't see two triangles for each rectangle when using the debug plugin, so idk
Would be interesting to see if there's the same problem with ldtk maps.
I wonder how nobody would notice this though
Have you tried with a rounded rectangle collider ?
It works really well! Although, I've noticed a couple of things.
- Dynamic objects fly violently when the character controller approaches them.
- If you run left and jump, and then press right midair, velocity negates completely. It feels wrong.
- When the character controller moves up a slope and stops, it slowly moves up (and vice versa). Apparently,
CharacterControllerCameraOf.enable_smoothingenables or disables it. What are disadvantages if I turn it off? (I haven't noticed any so far.) - What is the difference between
speedandmax_speed? - If you hold forward and jump, and then look right or left, you will continue jumping towards the original direction, but if you rotate horizontally more than 90°, you will be jumping sideways. It's a bit hard to describe in words, better just to see it once.
- What are “tac” and “crane”?
- I think if the character controller crouches midair, it should bend its legs, so the camera doesn't drop down. It think it's like that in Half-Life... 🤔
- If the character controller runs into a steep slope, it shortly tries to climb it sometimes. Probably not a huge problem though...
- Are there any plans for switching between walk/sprint modes? (Although, I guess, it should be possible to just change max speed with a button.)
I haven't checked out all the CharacterController's fields yet because I'm falling asleep.
checking out the example for the chain_3d. it uses the SphericalJoint. which is cool because they joint objects in the chain rotate with the movement, but its very springy. I tried the DistanceJoint and that you can fix the joint distance but the joints dont seam to rotate with the movement. is there a way to get the Spherical to not be springy and stretchy in distance?
thank you very much for typing this up!
- that's just the density of the objects being low 🙂 You can set their density higher and will see that they don't fly anymore
- That's a feature! It's called counter-strafing
- The disadvantages are that things like stair stepping and crouching will teleport the camera, which can be disorienting. I'll tweak the smoothing at some point to this behavior you noticed is better behaved

- Yeah I need to improve the naming on the configuration fields haha.
speedis how much speed you reach when you hold W on the ground,max_speedis the maximum you can get through movement techniques like airstrafing before the game clamps you - That's also a feature, it's how air control works in Quake-derived KCCs 😄
- They're terms from parkour. In this KCC, "tac" means
- Run and jump so that you jump slightly into a wall. The angle should be about 10 -30 degrees inte the wall (where 0 would be parallel to the wall)
- press space again when you're touching the wall
- if you do it right, you will kick off from the wall and gain vertical and horizontal speed. It's our imo more fun version of a wallrun 😉
"crane" is a move that pulls you up a low ledge without having to full-on grab the ledge and slowly climb it. You jump to an obstacle that is just a bit too high, then press space again when touching it to get up the rest of the way - agreed!
- Is that the residual momentum, or an actual climb? If it's the residual momentum, that's expected. i.e. your speed won't go to zero instantly but be "unloaded" on the steep slope
- I was thinking it's trivial enough to change the
speedyourself (not themax_speed), so it's not builtin rn. But we could add it. I personally much prefer games that where you are instead always sprinting and can optionally slow down with shift, so I also want to try to nudge the users slightly in that direction (it's an opinionated KCC).
cc @summer acorn
i disagree with 7, for a couple reasons. center of mass should be preserved, this is how physics works. when you tuck your legs in that pulls your torso and head down. secondly, the pull down is good visual feedback that you indeed crouched imo
i do agree with 3, im going to have smoothing disabled for my projects
im glad its a setting
Oh yep you're right. I believe we said it should tuck in the head and the legs so that the CoM stays the same, right?
yup
Is there a way to define the PhysicsSchedule to make systems ambigious in order by default?
If I don't specify their order explicitly the app won't run so I have to make meaningless system sets
Can't you put all your systems in just PostCollisionCheckSystems::First?
why do you want it to be ambiguous anyways?
inter-system parallelism is usually not something that gives you performance
I wish
I don't mind tbh, it just won't run because it wants order specification
Not a performance thing, I just want the app to run haha
hold on let me show you what happens if I put two systems on the same system-sub-set
@visual sparrow it compiles successfully, but then
Hehe I see
- Is there any setting for the character controller like “force” with which it pushes objects or how it applies to objects? 🤔 And does only density of other objects control the CC's speed reduction?
- Can there be an option to disable it and just gradually change the directional instead? I've just checked in HL2, it's “kinda” like this too, but it feels smoother there. But maybe it's just small acceleration/deceleration? It definitely doesn't get cut off though, like you hit an invisible wall.
- Can crouching be made gradual and not instant? E.g. gradually scale the collider's height (maybe even with easing). I recall I made this in Unity ages ago, worked just fine. But, speaking of smoothing, I really hate wobbly cameras in games.
- It feels really weird, could you make an option to have an expected behavior? I.e. each new jump follows the intended movement direction (with preserving some velocity, but not 100% of it). If I look north and start jumping towards it, and then I look west while holding
WandSpace, I'd expect to start jumping west (eventually), not to continue jumping north forever. And if I start jumping north and then suddenly turn 180° south, I definitely shouldn't be jumping towards east or west (with some of the momentum permanently cut off). It just feels like I have no control of the character.
- @summer acorn I just checked both Half-Life 1 and 2, and the camera in the first one indeed tucks down, but in Half-Life 2 it doesn't, no feedback there whatsoever, the camera doesn't change vertical position at all. So we can tell with confidence that the devs actually fixed it. And it feels just right, no feedback is really needed. In real life, center of mass is somehere around the chest for males, lower for females, but torso is the core, and arms and legs are just “free attachments”, so to speak (i.e their mass is negligible). Human body isn't a uniform cylinder. If you jump and wave your arms, your eyesight height doesn't change. Same if you bend your legs midair. I actually encourage you to try it out. I tried, nothing changes. And even if you want to tuck your head (no idea why you would), it's 3 cm tops. Anyway, to please everyone, there could be a setting for how much one wants to tuck the camera during a midair crouch.
- Yeah, I think it's residual.
- I know what you mean, but it depends on a game too, or rather it's type. In some slow-paced exploration games you'd want slow speed by default with a possibility to run sometimes. And some games may have more than 2 modes, e.g. walk, jog and run. But again, I think it can be done just by changing speed and acceleration/deceleration (for smooth transitions between modes).
- it's physics based: increasing the mass (or indirectly the density) of the KCC will make it more forceful. The speed reduction is a byproduct of trying to not intersect with the other objects, so the more they get thrown, the less your speed is decreased.
- It's based on the flavor used in CS:Source. I can look into the code difference to HL2 at some point, sure 🙂 It's also possible there is some bug or another causing it. Will need to investigate!
- The smoothing is only vertical FYI. No mouse smoothing, no smoothing when you walk. It's only up and down. The crouch can certainly be made gradual, yes, though the code would be a liiiittle bit tricky to write due to Parry's API. The smoothing on stairs would also not be needed at all if we could use capsules, but there's a Parry limitation regarding reported normals that keeps us from using them :/
- Probably not, no. Changing the air acceleration has big repercussions on the feeling and supported movement tech, and implementing two entirely different air accelerations is a lot of testing overhead, as all features must feel nice with both. You actually have a surprising amount of air control, you just need to know how via air strafing. That said, I know that the airstrafing is not yet quite perfect, so this may improve a bit in the future.
Update: can confirm that 3) and 5) are both accurate to the Counter Strike controller
I forgot to mention, but the air control depends on you pressing A/D while jumping. The momentum is also never permanently cut off: you can airstrafe up to max_speed while jumping
I don't have CS: Source, is it different from HL2?
A bit. It's mostly the same, but the code has plenty #ifdef HL2 ... #endif blocks to change the behavior in key places
a prominent one is how in HL2, jumping forward speeds you up, while in CS:S, you keep your speed
(funnily enough HL2:EP1 and HL2:EP2 again also have sliiiiightly different behavior than HL2)
I actually encourage you to try it out
i do parkour irl, the thing ive been saying to jan is to keep the CoM in the same place when you tuck or untuck from a crouch. the center of the collider is just the approximation that was easiest, but i agree that a more accurate adjustable value would be better
I am not sure we are talking about the same thing. I am talking about holding W and Space and nothing else, and moving the mouse around without releasing those 2 buttons. If you rotate 180° without releasing them, you won't jump the opposite direction ever, you will be just jumping in place, so it's “permanently” cut off (until you release Space and start over).
You also didn't reply to my [other message](#1124043933886976171 message).
I assume you mean this?
I don't have anything to add to the other points, that's why I didn't reply to that. 7) is for vero, 8) is working as intended, 9) I agree with 🙂
- Was for both, but OK.
Oh yeah I mean I have no opinion on that 😄
I'll defer to vero
@faint kite is this the behavior you describe?
just so we talk about the same thing
Perhaps, I misunderstood, centre of mass wasn't my concern at all (the body's rotation is locked anyway, so I don't see how it affects anything). Firstly, I was talking about the camera going down if you crouch mid-air, which is not realistic for real life, and as for games, we have HL2 as an example. There are probably more games too, but I consider HL2 as a standard for many things. Secondly, if you mean to cut both top and bottom of the collider, it's not correct, neither for real life, nor for a game (HL2 once again is an example). When you jump, your torso is the core, you may bend your limbs whatever you like, the torso doesn't change altitude because of that, even if you regroup mid-air (even if you swing your limbs violently, you can affect your position only this much). You may lean a bit, but that's already a rotation. So the correct approach is to cut only the bottom part of the collider, so to speak. The main idea of crouching mid-air (besides regrouping and preserving momentum) both irl and in Half-Life games is to reach higher places that you can't reach without crouching. Anyway, as I said, there could be a settings for that.
https://youtu.be/tn0lqMuGguw?si=8jFAxQ9p0v88QY5i&t=8
The standing vertical jump is an important measure of an athlete's explosive power and a critical test in the NFL Combine. So who jumps the highest? And what's the limit? WIRED's Robbie Gonzalez jumps in to examine the physics and physicality of maximum leaping ability.
Still haven’t subscribed to WIRED on YouTube? ►► http://wrd.cm/15fP7B...
When you jump, your center of mass follows a more or less fixed trajectory. Im pretty sure moving your legs up does change your center of mass relative to your torso (your center of mass moves up slightly). This has the effect of moving your torso downward slightly, relative to its previous trajectory. Right?
This is just basic conservation, a body in free fall cant pull a mass towards itself without also being pulled towards the mass.
yeah the difference is humans cannot move their legs instantly like a videogame character
i think tucking towards the center makes more sense than tucking towards the top
and i dont think the point of crouching while jumping is to get to higher places
the point is to fit in tighter spots
although it also lets you get higher places
because your feet are less in the way
an average person's legs account for about ~30% of their body mass (and about half that is in the upper legs and won't move much), so it's not like it will have a huge effect but it will be noticeable.
if you were on a space station and you tucked your legs, your eyes would move down
not a whole lot, but not unnoticable
the upper legs do move quite a bit when crouching btw
the arms do too
assuming that this is the behavior you describe, here's how this is done in Quake-derived KCCs. The first jump I do, I only press space + W. You can see I move perpendicular to the original direction, which is quirky, I agree, but not really something fixable with this acceleration style.
The second jump, I press space + W and then hold A or D while moving the mouse. As you can see, you can have very nice air control that way 🙂
I'll add to this that even if we wanted to only tuck in the legs, I'd still move the eyes a bit down to give the player better feedback on what their keypress did
yeah
i do think having the CoM in a more accurate position is a good idea
the eyes are not it though
back of the envelop, i'd expect eyes to move down by maybe about 10-15% of the leg height.
how do you get that number? 🙂
the mass ratio between legs and head?
Yes, did you only hold W and didn't press A/D? If so, it's just counter-intuitive. Is it like this in Quake 3?! Either way, it doesn't make any sense. Why am I going north and after rotating to south I am moving east instead (not even initial north direction that would have some logic at least)? If I want to go left, I will press A, don't I? More to that, if you rotate mouse enough times, you will either move towards random direction (not even the initial one) or lose momentum completely and will be jumping in place. Even more to that, if I release W and press A or D, it will do nothing, so yes, I have no control over the CC in this situation, it just jumps in a random direction like a lunatic. Idk, maybe it's a normal thing for certain games, but it is definitely something niche. And if I think it's not normal, I am pretty sure there will be players who will think the same. Sorry, but, unlike the rest of the CC, this part is really unpleasant. 😔
Yeah it's like this in basically all Source games (that don't shoot you completely down by applying a ton of friction on land)
You can go the Team Fortress way and increase the friction by a lot and apply it before the jump
that means that every jump is processed completely independently / has no momentum
Centre of mass will go up, yes, but torso moving is insignificant, as seen in the video above. Torso is 55% of the mass and legs are only 18%. Legs are thin and long compared to torso.
But you can put centre of mass even on the bottom, the CC doesn't rotate, so it doesn't matter.
Yeah, Quake 3 behaves the same way. They do have commented out code for alternative air acceleration though
whats your source for this btw
specifically those numbers
Google.
and it's speculated that the engine that CoD uses uses that code
As they note, this fixes certain things, but makes the KCC feel rather bland in the process
I never said tucking upwards, wdym?
It is literally said in the game.
they mean that it makes more sense to shrink the collider from top and bottom than only from the bottom
never mind I am too sick to do math today
aight I was just curious 😄
That too, it depends.
also, get well soon 
Exactly.
Again, you can see in the video above it's not noticeable. I actually encourage you (when you get well) to jump and crouch mid-air and see how your eyesight height changes. Mine doesn't, if you wonder.
And if you jump first?
Are you comparing jumping on Earth and tucking in space?
Actually, since a body is already moving upwards, tucking legs won't move it down, but rather will remove some velocity (vector math, all that).
Move where? Wdym?
Could you make a settings for how much camera moves?
Probably
I'll need to see how I implement the jump crouch at all haha
all I know is that the current one is shit
- Does bevy_ahoy has some mass settings? Because docs for Avian say that
Masscomponent doesn't affect kinematic bodies (which makes sense). Or does bevy_ahoy use the CC'sMasscomponent for calculations? 🤔
yeah you just use the regular Avian components
the docs are lying btw lol
kinematic bodies still get a mass
What do you mean by “acceleration style”?
The first jump: from the player's point of view, it is something that should be achievable (and actually must be performed) by pressing A, not W.
The second jump: the problem is pressing A/D doesn't work in my case as it does in your video. It barely affects the direction. Maybe it's my settings though... I didn't change many yet, but I did change speed (it's much lower).
You must hold W+A or W+D
e.g. if you want to turn right, you move the mouse right and hold W+D
by "acceleration style" I mean how the KCC decides to convert the three vectors
- current look direction
- current velocity
- current input vector
into a new velocity 🙂
changing the air_speed reduces how well you can air control
It doesn't look like a lot of code, is it possible for you to add this as a second option? 🤔 (Although I don't know what is the other option feels like, obviously...)
I can try 🙂
but first I need to finish the climbing implementation
Thanks!
Sure, no hurry. I will also try to play with settings and see if I can improve something in my case.
I'd advocate to just make 2 separate values: how much you cut it from the bottom and how much from the top. Because the bottom value is much bigger than the top value, if one even wants to trim the top at all.
Yes, I did exactly that.
then I'm not sure what went wrong, sorry 
Interesting. Initially I thought you were pressing A while turning right and vice versa (kinda like when you jump around some pivot or object), because it looks like that. Perhaps, I am just going crazy... Well, this way it kinda works, but is still weird, although that might be because of low speed in my case. What I still don't get is why, if I start jumping forward, and then press A/D while jumping, regardless of whether W is pressed or not, I don't start jumping 45° or 90° eventually, but just jump forward forever. Because if I press W and A/D, I will walk in a 45° direction, same if I jump just once, but not if I hold Space. Perhaps, it's a feature for Quake and some slice of games, but not something one would expect by default. 🤔
And again, it only works if you slowly move the mouse around and in the “right” direction (like in the video).
Otherwise you just jump in a random direction or lose speed completely.
Maybe it has something to do with times when people used keyboard to rotate instead of mouse... 🤔
I am now curious if it would be possible to just expose that stuff so users could implement their own acceleration styles... 🤔
imo it makes more sense to put the look and input directions together and just react to the resulting movement intent vector
You can override the state however you want 😄
For most moves, yes! But there are some exceptions. For example, if you want to climb up a ledge right in front of you, it's nice if you can hold space and don't need to press W
i've got "hold space to climb any wall you're touching"
If I understand you right, I agree.
I kinda like "hold space to climb the wall you're facing" since that allows you to select the right ledge in edge cases 🙂
just hold a direction then
it's for some reason not what my intuition expects
if there's a ledge I'm looking at and I'm holding space, I feel like I should be able to climb it
but obviously this is personal preference
intuition depends on the games you're used to
@hallow mulch this fixed the issue for me, something about TiledPhysicsAvianBackend::Polyline (the default) is broken but Triangulation works
Though it might have its own issues, not sure lol
Got my hopes up...
Nice !
Avian seems to miscalculate collisions on corners
How did you get the idea of changing the backend and use Triangulation, browsing the docs ? Don't see any example using Triangulation.
looked through the source code and saw the enum, then found where I could define it
ghost collisions happen when it seems like it might hit an edge if the other edge wasn't there
but if it's just a single polygon, and all 3 of polyline, triangles, and line strip have issues on the corners, idk what I'm supposed to do to fix that
Trying Triangulation now ...
works fine with convex non-compound shapes
there's a 'voxels' shape, iirc even in 2d
and meshes (incl. 2d trimesh) have anti-internal-collision measures
Oh that's weird it splits colliders into sets of triangles
I guess that's the problem - bevy_ecs_tiled is generating separate colliders rather than an actual trimesh
I would heavily recommend using a voxel collider for tilemaps, though I'm guessing bevy_ecs_tiled doesn't have built-in support for it yet
it won't have ghost collisions, unlike Parry's polyline or using a compound of rectangles
I think the problem is Tiled allows you to use various kinds of polygons as colliders for tiles, and so it has to support arbitrary shapes and combine them on a best effort basis to prevent ghost collisions in between tiles (it does the combining pretty well, but the colliders it generates still have issues on corners)
yeah you'll get those with 2D meshes or polylines since Parry doesn't fix internal edges for those, and even if it did, you'd get ghost collisions at boundaries where different colliders meet even if the surface looks flat
I tried having Cursor fix the issue in bevy_ecs_tiled and it switched it to convex_decomposition - everything seems to work now, but this could also just be slop that will break in 5 minutes for all I know lol
with a voxel collider you won't get ghost collisions since it's specialized to handle them properly
Dealing with ghost collisions is a challenging problem in game physics. The basic idea comes from motion across a flat surface. You may have several shapes joined together to make a flat surface, like a triangle mesh in 3D or a chain of edges in 2D. Convex shapes can hit the internal connections and have their motion blocked. This is undesirable...
you could also set the SpeculativeMargin of the character to zero to reduce the risk of ghost collisions, you might just overlap things a bit easier when moving at high speeds since you won't have CCD
What if you wanted a different collider for some of the tiles though? Like, a half step or ramp
yeah for that you'd need a different shape, which introduces the problem again :/
it would be nice if Parry had Box2D's chain shape (described in that article), which would fix the problem that polylines currently have
maybe I'll add it to Peck
Why is raycaster a component?
use avian3d::prelude::*;
use bevy::prelude::*;
fn setup(mut commands: Commands) {
// Spawn a ray caster at the center with the rays travelling right
commands.spawn(RayCaster::new(Vec3::ZERO, Dir3::X));
// ...spawn colliders and other things
}
fn print_hits(query: Query<(&RayCaster, &RayHits)>) {
for (ray, hits) in &query {
// For the faster iterator that isn't sorted, use `.iter()`
for hit in hits.iter_sorted() {
println!(
"Hit entity {} at {} with normal {}",
hit.entity,
ray.origin + *ray.direction * hit.distance,
hit.normal,
);
}
}
}
Do I have to update location and direction of the ReyCaster component every time I want to perform a reycast, or is there some function I missed that should be used for a reycast instead?
A system parameter for performing spatial queries.
It works, thanks!
yay! Please send some feedback after you tried it out 🙂
is there a way of creating a collider with it's origin offset? like say i want a cylinder but not centered
only by stuffing it into a Compound
is that significantly worse than a simple shape for calculations? i mean i doubt it can be that bad tho
the general recommendation is putting the collider on a child entity with its own transform, but a Compound works too if you want to keep it on a single entity
a compound collider stores a BVH acceleration structure, since they're mostly intended for, well, compound shapes
which is completely redundant if you just store one or a few shapes
but it still shouldn't be too bad in terms of overhead
negligible difference though i assume
compound shape just works and feels a bit nicer to use than child entities
I have 2 rigid dynamic bodies and i want one of them to not affected by physics, i can't use kinematic because i'm using tnua controller which requires a dynamic body, other entity i'm talking about will be a scene prop like a ball or cube
There's a Dominance component for treating dynamic bodies like they had infinite mass when interacting with lower dominance bodies
thank you
seems like this is ignored for JointDamping though?
hmm yeah it probably applies damping to both bodies currently 🤔
i was trynna make my character hair use rope segments based on revolute joints, and you could imagine the horrors in my face when my sprite started rotating even though it had both Dominance(i8::MAX) and LockedAxes::ROTATION_LOCKED
doesn't happen without JointDamping, but that makes the hair unbelievably light which looks silly
how about making an entity to not collide other entity without using collision layers ?
A trait for user-defined hooks that can filter and modify contacts.
i need in 3d
this one is too complex :D
A trait for user-defined hooks that can filter and modify contacts.
I have a weird bug
let mut entity = commands.spawn((
Name::new("Game Scene"),
Transform::from_xyz(0.0, 0.0, 0.0).with_scale(vec3(5.0,5.0,5.0)),
RigidBody::Static,
SceneRoot(scene),
ColliderConstructorHierarchy::new(ColliderConstructor::ConvexHullFromMesh),
));
when i use this some of the meshes rotates
in the scene
more specifically the mountain starts to rotate
How can I get hit point location?
distance * direction + origin
need direction and origin from wherever you cast the ray
I must have some sort of mistake. For some reason, entites are being spawn behind the collider:
for hit in hits.iter_sorted() {
let translation = hit.distance * camera_transform.forward() + camera_transform.translation();
Where:
camera_query: Query<(&GlobalTransform, &mut Camera3d, &RayCaster, &RayHits), With<LocalEntity>>,
let (camera_transform, camera, ray_caster, hits) = camera_query.single()?;
Or maybe I have something wrong with the collider creation? Is there a way to visualize the collider?
pub fn test_platform(
In(entity): In<Entity>,
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>
) {
let mesh3d = Mesh3d(meshes.add(Cuboid::new(1000.0, 10.0, 1000.0)));
let mesh = match meshes.get(&mesh3d) {
None => {
return;
}
Some(item) => {
item
}
};
let collider = Collider::trimesh_from_mesh(&mesh).unwrap();
commands.entity(entity).insert((
mesh3d,
MeshMaterial3d(materials.add(Color::srgb(0.5, 0.5, 0.5))),
TestTag,
Block {
display_name: "Test platform".to_string(),
id: 0
},
collider
));
}
there's a physics debug plugin
Collider seems to be ok
So, I made sure that it actually hits the collider plane collider, etc.
Is this possible that RayHitData.distance is bugged?
When I e.g. ray cast stright down, it actually gives me bigger distance, than when I do it under angle
The results are like Y > X
can try visualizing the raycast, either via raycaster's debug viz or just an independent gizmo
How can I visualize it via raycaster debug natively? Gizmo shows exactly what I described
use an entity with a transform and raycaster component
Finally works
This keeps happening to me. I took a look at the avian code but couldn't figure out which constructor could possibly be used for the shape casters that also uses new_unchecked
avian3d::dynamics::rigid_body::mass_properties: Dynamic rigid body 2652v4 has no mass or inertia. This can cause NaN values. Consider adding a `MassPropertiesBundle` or a `Collider` with mass.
how can i fix this
make sure it has at least one enabled collider or add a manual Mass
okay
i added mass or density and a collider and everything worked but i was getting that warning on evrything so i added a MassPropertiesBundle like
MassPropertiesBundle::from_shape(&Capsule3d::new(0.6,1.3), 1.0),
to everything and all the warnings went away
im not sure why i need a massproperties bundle and a collider that have the same shape...
like if i have
RigidBody::Dynamic,
Collider::capsule(0.6, 1.3),
ColliderDensity(1.5), //default is 1.0
it seams to work but gives that warning when i do
RigidBody::Dynamic,
MassPropertiesBundle::from_shape(&Capsule3d::new(0.6,1.3), 1.0),
Collider::capsule(0.6, 1.3),
ColliderDensity(1.5),
it works fine. no warnings.
that sounds more like MassPropertyPlugin isn't added or the scheduling's weird
MassPropertyPlugin ? havnt used that...
it's the one that manages mass properties, it's in PhysicsPlugins, but it's also the one that emits that warning
.add_plugins(PhysicsPlugins::default())
which is why i went back and crossed it out
using the example of the chain_3d with the sphericalJoint. i cant seam to get ti to be non-stertchy. its always springy and stretchy... i got the distanceJoint to work for keeping a distance but the rotation on that joint is not as cool as the sphereicalJoint.
is there a way to get the spehericalJoint to be non springysquishy?
Heyy, I've been very confused with LinearVelocity today. Is there some documentation somewhere on how this is implemented?
Why does the initial Transform.translation of a RigidBody influence the direction in which the LinearVelocity is applied?
The following is the example that made me cry about whatever is happening:
if let Some((pos, _)) = named.iter().find(|(_, name)| name.as_str() == "hand_ik.R") {
let direction = -camera.translation.with_y(0.).normalize();
let transform = Transform::from_translation(pos.translation());
dbg!(transform, direction * 10.);
commands
.spawn((
Mesh3d(meshes.add(Sphere::new(0.1))),
MeshMaterial3d(materials.add(ArcaneMaterial::new())),
transform,
Collider::sphere(0.1),
RigidBody::Dynamic,
GravityScale(0.),
LinearVelocity(direction * 10.),
));
}
The linear velocity of a rigid body, typically in meters per second.
Here the sphere moves to the right normally, but when the starting Transform changes (the hand of the character moves) it then moves forward.
The dbg output for one sphere that goes to the right and one that moves forward is:
[game/src/player/attack.rs:40:9] transform = Transform {
translation: Vec3(
3.1421115,
1.5768347,
8.041592,
),
rotation: Quat(
0.0,
0.0,
0.0,
1.0,
),
scale: Vec3(
1.0,
1.0,
1.0,
),
}
[game/src/player/attack.rs:40:9] direction * 10. = Vec3(
3.208275,
-0.0,
-9.471377,
)
[game/src/player/attack.rs:40:9] transform = Transform {
translation: Vec3(
3.0986729,
1.7161975,
8.229811,
),
rotation: Quat(
0.0,
0.0,
0.0,
1.0,
),
scale: Vec3(
1.0,
1.0,
1.0,
),
}
[game/src/player/attack.rs:40:9] direction * 10. = Vec3(
3.208275,
-0.0,
-9.471377,
)
might just be colliding with the player immediately, or with each other
can rule that out by listening to collisions or just setting the RigidBody Kinematic
Oh my goodness... thank you so much ... all that time I have wasted again through literal stupidity xD
the documentation says that tunneling is more likely with small objects but how small is "small"? If I have an object that tunnels through a wall.. if I scale up both the object and the wall so they're larger but proportionally the same would I still get the same tunneling problem?
small relative to wall thickness and velocity
ccd & speculative collisions should prevent it for non-absurd velocities though
small enough with high enough velocity that it moves through the wall within a single step that takes delta_secs
with speculative collision or swept CCD this shouldn't be a problem
however you can still have objects pass through walls if other objects are pushing them hard enough, due to contact softness
I can't figure out how I can wait for colliders to finish generating, a la how you can wait for assets to load. Is it possible at all?
check AssetServer wait_for_asset (async), i believe there is also (a rather boilerplate) example for it
oh does it count as an asset?
(cannot check atm, just responded to this part "a la how you can wait for assets to load")
Fair enough, thank you. I haven't been able to find the example, if someone else has a link that would be lovely
I think in the current version the only way is to check to see if the Collider is on the entity (assuming you're using like, ColliderConstructor or similar).
however the next version has this PR in it which hands you some observers: https://github.com/avianphysics/avian/pull/830
cool! thank you. If the collider is only attached once it is ready, then that's perfect, I can use that 🙂
That PR was in 0.4 already 🙂
https://joonaa.dev/blog/09/avian-0-4#collider-constructor-ready-events
https://docs.rs/avian3d/latest/avian3d/collision/collider/struct.ColliderConstructorHierarchyReady.html
Triggered when a ColliderConstructorHierarchy finished inserting all its Colliders.
hwhoops
I'm loading gltf assets in an avian3d project. I use ColliderConstructorHierarchy like it's done in the collider_constructors example. It completely kills my CPU 🙂
Using a convex decomposition?
Yes, ConvexDecompositionFromMesh
The asset loads, and then it goes wild and i have to kill the process
it's a pretty large model but not that much
(a house)
Yeah convex decomposition is extremely slow, in most game engines like Godot you do the decomposition in the editor, not at runtime. We're kinda limited here since Bevy's asset preprocessing situation isn't great
Although I haven't looked at exactly what Bevy supports or how hard it'd be, maybe we could implement preprocessing with some work
I'd love to work on that.
I believe some people have implemented it manually by running convex decomposition and then serializing the produced collider using serde, saving it to a file, and when running the game, you deserialize and create the collider(s) that way
Nice.
Looking at ConvexDecompositionFromMeshWithConfig ...
"Parameters controlling the VHACD convex decomposition."
Using ConvexHullFromMesh is also wayyy faster if you don't need concave colliders for the meshes in your scene
Will try that.
Ok, it's slightly better
Can see the colliders
I'm spawning like 20 houses, it's painfully slow.
Is this with the dev profile or in --release mode or with at least some build optimizations
dev profile with no optimizations is very, very slow, especially for stuff like this IME
It's a custom profile.
I'll try in release mode.
There's just so many colliders generated for the platform ..
mm 6.8k vertices for the model, potentially with 20 houses is quite a lot, though not like a crazy amount
but enough to most likely be slow to generate colliders at runtime
But it's awfully slow even after all the houses and the colliders have been processed.
The debug plugin is activated, maybe that doesn't help ..
I'll use simpler models, really cool that avian supports this.
With this model for example: https://sketchfab.com/3d-models/wooden-house-3f654e80801543e0990f25df6b590b19 it's day and night, no problems at all, really fast.
Aha, so I should prefer putting a hierarchy on the top object instead of inserting colliders directly on the mesh?
I'm guessing it'd be possible to do the preprocessing in a macro? Though then the collider would be in the binary itself
Anything I could do to stop these from crashing the app?
NaN coordinates, weird rotations, or invalid shapes is the only causes I can think of ... All of which would crash elsewhere anyway 🤔
But I have so many colliders 🥹
Usually this happens because a LinearVelocity ends up as NaN, which then propagates to Position and then to the colliders. The debugging process is sprinkling debug_assert!(vel.is_finite()) in both your own code and avian until you find the culprit.
A neat trick is to use the track_location feature on bevy, which can tell you where the last write to a component happened. That allows you to do a debug system where you can query for NaNs and figure out who wrote it there
@sand smelt interesting
Although I never reduce velocity or assign to it manually, only add to it
So I don't understand how that could be possible
Oh but sometime the value I add is devided which could be division by zero!
Thanks a lot!
hiya. anything special todo when despawning and entity that hs colliders and such on it? im getting a collider crash when despawning some entitties..
cargo/git/checkouts/avian-5a22c167119f3550/567b9f5/crates/avian3d/../../src/collision/collider/mod.rs:512:9:
assertion failed: b.min.cmple(b.max).all()
How can I Check if my collider is grounded?
Ping me please
my method is to loop on all contacts and ignore the ones with normals above some deviation from 'up'
...
@plush mulch
interestingly, the return type from Collisions::collisions_with and its inner types all seem perfectly capable of impl'ing Copy, which would prevent a .collect() in that code
Is this for a kinematic character controller in particular?
@maiden charm I'm curious which parts have the most overhead for your project, if you run with the PhysicsDiagnosticsPlugin and PhysicsDiagnosticsUiPlugin (requires the diagnostic_ui feature) 🙂
If there's a looot of colliders but not too many active collisions then I would suspect that the broad phase and maybe spatial query pipeline updates are the most costly currently
(IIRC that was the case for me)
Yeah that should get fixed with the broad phase rework which I'm trying to finally get done now
After that, having a ton of sleeping dynamic rigid bodies should be fairly cheap, right?
Yeah, both static bodies and sleeping dynamic bodies would have almost zero runtime cost
Then I recommend looking into the new MoveAndSlide API, specifically cast_move, as shown here
I recommend doing a cast_move into Vec3::NEG_Y * some_small_distance (e.g. 0.05)
if that hits, you're grounded