#Avian Physics
1 messages Β· Page 32 of 1
commands
.entity(entity)
.insert((RigidBody::Static, NoTransformEasing))
.with_child((
Collider::ellipse(25.0, 25.0),
Transform::from_xyz(-50.0, 0.0, 0.0),
));
(spawn collider as child)
oh yeah derp, i forgot sprites don't have origins
Hello, how do I get the global coordinates of an existing Collider's vertices?
This collider.shape_scaled().as_convex_polyhedron().unwrap().points() returns always the same numbers regardless of its position in space.
Thanks
Those points are in local space, so you'll probably need to transform them by the rotation and translation of the collider. It's a bit ugly, but something like this I think
let points = collider
.shape_scaled()
.as_convex_polyhedron()
.unwrap()
.points()
.iter()
.map(|p| transform.to_isometry().transform_point(Vec3::from(*p)))
.collect::<Vec<_>>();
where transform is the GlobalTransform
(we convert the transform to an isometry because we don't want to apply scale, since shape_scaled already includes scale)
Work stealing will help speed up transform propagation & any highly divide-and-conquer algorithm.
Trying to get no_std Avian running, this is fun
Firstly we'll need to copy bevy_math's ops module for f64 (I suggested having this first-party in the original PRs...)
Secondly I think we might be blocked on Nalgebra of all things 
Did someone counter propose
avian f64? π€
I need to double-check, but I'm pretty sure it's forcing an std version of Glam with all the type conversion features like convert-glam029
Which means we need to either fix this upstream if possible, or implement our own conversions
Even more reasons to work on bevy_peck
I was going to say "But at least we can no_std with SDF collisions", but that needs bevy_asset which requires std for std::io and std::path 
I wouldn't yeet it until we have proper big_space support at least, but we should imo reduce the use of f64 a lot even if the feature is enabled
Right now it changes basically everything to f64 but it's only really relevant for specific things
(Also the issue about removing f64 maybe isn't the most popular judging purely by reactions :P)
https://github.com/Jondolf/avian/issues/439
With big_space support or alike I'm honestly not even sure what it would be good for anymore
I guess maybe insane amounts of substeps, but then avian isn't really made for scientific uses and I'm not sure why games would do that to their FPS π€
I think large and small masses might be problematic with f32 atm
Okay it seems like Parry is actually insanely reliant on std right now, for some reason
Almost half of the shapes are gated behind std
hhh I guess I'll see if I can properly no_stdfy Parry
(fyi @surreal rune)
Parry is the main blocker right now, otherwise I should have no_std Avian working
what's the second most popular collider crate?
Hmm, that's interesting, I might have a look and see why. Might be as simple as they accidentally used std::Vec::Vec and didn't bother to swap over
But that's still very cool that Avian's own no_std support came so quickly. I reckon a lot of the Bevy ecosystem could be ported (bar assets and rendering of course)
Probably collision, but it's fairly minimal and I haven't used it
Or my crate Peck #showcase message but the repo is even public yet π
There aren't really any other major collision detection crates that I'm aware of, apart from Parry
There's NCollide but that's just Parry's predecessor
I'll just start removing std feature gates, see what breaks, and try to fix them :P
There's like over 240 occurrences of feature = "std"
That's exactly how I do it haha
What is this in Parry 
#[cfg(all(feature = "alloc", not(feature = "alloc")))]
#[cfg_attr(test, macro_use)]
extern crate alloc;
Lol what
Also it does this π€
#[cfg(not(feature = "alloc"))]
extern crate core as std;
I can't tell if I like this
Yeah I hate that. IMO it was a mistake for Rust to re-export core in std
yeah
Problem is they're slowly moving things out of std and into core and they can't break backwards compatibility.
But yeah, libraries should just use core there's no harm
there's a clippy lint for it
Yep I know them well. Still mad their --fix doesn't work (if you group imports it will just fail and rollback)
when using ExternalImpulse is my understanding correct that the entity that gets this component .inserted to will be "bumped" ?
Does anyone have any advice on how to reduce compile times when using avian? A modestly complex bevy project without physics takes 1-3 seconds to do incremental debug compilation but my project that uses avian, even if I remove basically every other dependency and strip my own code down to almost noting, is over 1 minute. I know that Jondolf has said that replacing parry may eventually help but is there anything folks are doing currently?
Cranelift helps some but not a huge amount.
Are you using dynamic linking? I def do not have 1 minute iterative compile times with avian.
I am.
welp thats all i got sorry
Thanks. It's a good suggestion but not the specific problem I have unless I've broken it somehow but that doesn't seem to be true.
are you using rust analyzer?
I am but I don't believe it's invalidating my build, if that's your suggestion. Only my actual package seems to be building. When I do --timings it only shows my package.
I found a dependency that was bringing in a second version of bevy. Thought I'd already removed that. We'll see if that was the issue.
Yeah, I think that was my problem. That seems to have brought me back down to 4ish seconds, which is fine.
Though why that would add nearly a minute to the compile time is confusing to me. But clearly has nothing to do with avain.
might be that one of them didn't have dylib
But if dynlib is set for bevy in the main Cargo.toml it'll be set for all dependencies that use bevy as well, right? Unless you're a dunce like me and end up with multiple versions.
@surreal rune I think I might've gotten no_std Avian and Parry working! For Avian it's on the no-std branch
The patches required to make it work:
- Parry:
no-std - Nalgebra:
glam-no-default-features
For Nalgebra did you use Glam 0.30.1 with the new nostd-libm feature?
Nope, bevy_math uses Glam 0.29
Ahh ok. I'm hoping to get that feature backported to 0.29.3 next week!
Just to cover us until we can update to 0.30 at least
Cool, that'd be nice
I see 0.16 having some teething issues as we work out exactly how to make the experience the best and get dependencies on board, but it is happening...slowly haha
Don't forget the incredibly popular sdf_peck used in exactly 1 unfinished game
Parry no_std PR here @surreal rune @grizzled depot
https://github.com/dimforge/parry/pull/330
I know this sounds weird but a function similar to look at with rigidbodies, that works via angular velocity. Would be pretty cool
just curious, but what is this: spade?/std. Some kind of cargo feature or just a weird name?
I meant the ? thing, never seen it before
It's just a way to conditionally enable std for spade if spade is enabled
If you did spade/std, it'd unconditionally enable spade itself too
Ooh, that's useful
Just a quick question, is this the correct way of calculting an ang_vel. Given a certain yaw? Also anyone knows how to get rid of tab spaces in discord code
if let Some(yaw) = action.axis_data(&PlayerInputs::RotateTo) {
let new_rotation = Quat::from_rotation_y(yaw.value);
let delta_rotation = new_rotation * rotation.conjugate();
let desired_ang_vel = delta_rotation.to_scaled_axis() / time.delta_secs();
info!(?desired_ang_vel);
ang_vel.0 = desired_ang_vel;
}```
This is more of a rust question than an avian question, but I'm implementing it for a Avian-big space plugin so I'll ask it here
Is there a nice way to "inherit" the SyncPlugin and only overwrite the bits that I need to get integration with big space working?
Or do I need to make a complete duplicate of SyncPlugin into a unique struct/impl and implement both the things that need to be changed to integrate with big space and the bits that don't?
Not a massive pain either way, just thought I'd ask first
Are LockedAxes something that can be used to keep a player-controlled spaceship stabilized on the horizon whenever pitch/yaw are applied?
dynamically applying them?
It should be possible to add them dynamically, but what do you mean by keep him stabilized ?
You want your spaceship to be unaffected or to have a stabilization like a PID system ?
I mean, if Avian is performing the rotation (based on angular impulse for example), can it satisfy these requirement during rotation:
- no gimbal lock
- full smooth 360Β° rotation along X and Y (no invisible walls or weird instabilities at singularities/poles)
- no rolling around Z, meaning keep the object level on the horizon (XZ plane)
...which is something needed for swimming or flight sims
so basically you're asking if it's local or global lock? i'm assuming it's global, but i never actually tested π€
Bevy (and avian) uses Quats to represent rotation, which doesnβt have any of these issues. All of these are much more related to Euler angles than physics.
The last one is, in as far as itβs a constraint. I imagine that should be pretty easy.
It is actually quite easy to do that with quaternions just apply an angvel given by the difference between the two quat.
And from what I saw no problems with collision
Uh I guess yes and no. Mouse input comes in as pitch and yaw, and all these rotational problems pop up then
create a small quaternion representing the change to pitch and yaw, then compose it with the pose quaternion to update the rotation.
Will try, thanks
So yeah, that approach doesn't work, it's the most primitive one and I tried it early in my attempts to make it work. It will accumulate roll around Z.
I was wondering if Avian somehow solves all that, since it implements rotations too, maybe I'm trying to reinvent the wheel.
how are you making the delta rotation exactly?
let q_pitch = DQuat::from_axis_angle(DVec3::X, input.pitch * dt);
let q_yaw = DQuat::from_axis_angle(DVec3::Y, input.yaw * dt);
let q_roll = DQuat::from_axis_angle(DVec3::Z, input.roll * dt);
let q_combined = q_pitch * q_yaw * q_roll;
ship_ct.transform.rotation *= q_combined.as_quat();
input.roll is always zero
yaw should be before pitch, i think
unless quat multiplication is actually commutative
The Z-roll accumulates either way
could also do transform.look_to(Vec3::NEG_Z * transform.rotation * yaw * pitch, <up>)
Vec3 cannot be multiplied by a Quat. Did you mean Vec3::NEG_Z.rotate(transform.rotation) ? Or something else
it can. Just use quat method mul_vec()
Are you trying to make an airplane controller? If so here is my approach on how to rot via yaw, perhaps you can apply the same to your pitch and roll logic.
if let Some(yaw) = action.axis_data(&PlayerInputs::RotateTo) {
// Handles rotation
let new_rotation = Quat::from_rotation_y(yaw.value);
let delta_rotation = new_rotation * rotation.conjugate();
let desired_ang_vel = delta_rotation.to_scaled_axis() / time.delta_secs();
ang_vel.0 = desired_ang_vel;```
yea rotation accumulation is cursed, try storing total pitch/yaw/roll in res/comp instead
you'll probably need to do it to clamp pitch/roll anyway
if I'm doing things correctly, the game shouldn't slow down if the framerate drops, right?
I think so indeed ; but Iβm not sure how in avian youβd end up in a slowing simulation ? (Other than a simulation taking more time than a frame and snowballing to take longer and longer)
Has anyone made progress on kinematic character controllers beyond just what my draft PR has?
I'm likely not going to be active in game related stuff quite a while (irl job + other responsibilities) so I'd rather someone else take over that task
does tnua not work?
is it possible / good idea, to rotate the collider here to simulate the fox going down the slope ?
yeah, normally each moving part has a separate collider to match the model
Nice, and I can parent them to the bones I guess
But how to make them work in avian? Is there any example showing something similar?
Mine is based on the dynamic character example
i don't think so, but it should be similar to other engines, at least for legs you can look up how IK works
Tnx, Iβll do some research
maybe you'll even end up going full procedural like this guy https://youtu.be/z_fmMD-Gazw?t=81
The first part of a fake tutorial series on making procedural monsters or a devlog maybe. Who knows? give me feedback plz.
Ohh would be amazing π€©
@cinder summit idk if you've seen this before
https://youtu.be/T2oUOWNNnx4?t=256
showing that it's not pretty slow would actually make a really good video
Making monsters look more organic by killing polygons and updating procedural animations. Critter Crosser indie Devlog #5
Smart 3d guy that helped me: https://www.youtube.com/@TheSnidr
Wow really satisfying, must've been a lot of work
even with all the visual bugs I'm like "wow that looks awesome"
hello, is anyone else using avian in the candidate branch? ive been having issues trying to despawn entities with physics components
Are you using the latest main? I fixed a despawn panic issue 2 days ago
i believe so
What's the error/panic/issue you're seeing?
ok just a moment i lost the message now and i am stuck in compile hell :/
I've been using it but I think the only time my code despawns may be when StateScoped kills things, which is the crash Jondolf fixed.
Is there a half cylinder shape ? I want to shapecast a sword attack
Tnua is not a kinematic character controller
Hi and thanks for the great plugin! I have a problem with a 2D static body and its friction. I'm trying to build a sort of a slowly rotating planet that objects react to. So I have a pretty big circle collider that slowly rotates. All fine and good, objects fall to its surface. But as this sprite rotates, the objects stay put, as if there was no friction. I've added the Friction to both the object and the planet.
Make sure you're not rotating the circle by manually changing its transform, and instead use velocity. If you change the transform directly, it's basically equivalent to teleportation, and the objects on the circle's surface don't observe any movement from orientation A to B
Wow, thanks for the super fast reply!! Kiitos!
Ei mitÀÀ, happy to help π
Oh and btw velocity won't actually work if the circle is a static body (since it's... static) but you can make it a kinematic body in this case
Worked like a charm, thanks!
@vestal minnow I have the changes needed to move to rc.2 if you want them. I'm not going to do a PR because I assume that looking at it will take you longer than making the changes yourself (it's like three trivial things for avian2d) but I can if it's helpful.
Testing out the main branch with bevy 16's rc1 release. Seeing some odd behavior with two dynamic ridged bodies with CCD turned on:
The elevator physics components look like:
commands.entity(mesh_entity).insert((
ColliderConstructor::TrimeshFromMesh,
avian3d::prelude::RigidBody::Dynamic,
avian3d::dynamics::ccd::SweptCcd::LINEAR,
));
And the cube:
commands.spawn((
avian3d::prelude::RigidBody::Dynamic,
avian3d::prelude::Collider::cuboid(1.0, 1.0, 1.0),
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))),
bevy::prelude::Transform::from_translation(position).with_scale(Vec3::splat(64.0)),
avian3d::dynamics::ccd::SweptCcd::LINEAR,
));
I think one issue is that I'm updating the transform not the velocity? 
could be wrong, but I'm pretty sure if you want to update the position of a body, it needs to be kinematic, not dynamic
I tried kinematic as well with the same results.
afaik when you change translation you're teleporting it even with swept ccd
and on top of that, non-convex trimesh is especially bad on anything that moves
@vestal minnow have you looked into a parry/Collider agnostic spatial query pipeline? I'm currently faced with having to rewrite all my spatial query stuff, and it makes me wonder if it would be possible to upstream something π€
I've thought about it, but haven't started on a proper design. It'd probably be something like this?
// Convenience alias to keep the current API
#[cfg(any(feature = "parry-f32", feature = "parry-f64"))]
pub type SpatialQuery = SpatialQuerySystemParam<DefaultSpatialQueryPipeline>;
// Generic SystemParam for spatial queries
#[derive(SystemParam)]
pub struct SpatialQuerySystemParam<'w, 's, Pipeline: SpatialQueryPipeline> {
pipeline: ResMut<'w, Pipeline>
}
// Trait for spatial query pipelines
pub trait SpatialQueryPipeline: Resource {
// ...all the spatial query methods
}
Updating the pipeline would probably be handled from the outside for each pipeline since it might not generalize properly, not sure
(I need to go offline for a few hours now)
Found a bug:
https://github.com/Jondolf/avian/issues/679
Any ideas on how I can dampen up a dynamic rigidbody that constantly rotates and shifts it is linear velocities?
there're angular and linear damping components
Seems like main currently won't compile for new projects (or the examples) against bevy 0.16.0-rc2?
Updated Avian and my other crates now, so it should be fixed on main in ~20 min once CI passes
https://github.com/Jondolf/avian/pull/680
We really should try making CI faster somehow π the tests take ages to compile
Damn, that was fast
haha, I was like "I know how to do that"
I feel like I've tried caching at some point π€ idk where that is though so maybe not
It's the only real way to speed up CI except for using custom runners. It can be tweaked quite a bit (e.g. different architectures or RUSTFLAG shouldn't share cache), but I think these are simple enough that it will just work
Seems like Bevy just uses actions/cache@v4, is there a reason to prefer Swatinem/rust-cache@v2?
https://github.com/bevyengine/bevy/blob/main/.github/workflows/ci.yml
GitHub docs also show actions/cache@v4 (since it's official ig)
https://docs.github.com/en/actions/use-cases-and-examples/building-and-testing/building-and-testing-rust#caching-dependencies
For this purpose they do exactly the same thing, you just don't have to remember the paths for Rust. Bevy probably wants to limit their exposure to third party actions just for stability reasons
I can use that one instead
Hmm bevy also sometimes has multiple target folders, so they need to tweak it anyway
eh you can keep the rust-cache one too, it seems pretty popular so it should be fine
either one is fine for me as long as it works π
Then I'll just keep it. But why doesn't main compile for me π€
probably this ^ hasn't been merged yet
oh right, semver
started 27 28 29 30 31 32 33 34 35 36 minutes ago...
edit: god damn how many times do I need to update this
Windows is also just ridiculously slow, I thought the "rust compilation is way too slow" was a bit of a meme until I tried it on windows
okay it merged, I updated your CI PR
Gonna be just as slow now, but hopefully faster for next PR
yeah
When using TranslationInterpolation/Extrapolation with Avian, does it work if we only modified LinearVelocity within FixedUpdate? Or should we instead be modifying transform directly? I've seen it discussed that modifying transform directly would cause collisions to stop working because it is essentially teleporting.
Transform interpolation/extrapolation should work with both modifying velocity or the transform directly in FixedUpdate. But interpolation is purely visual, it doesn't affect behavior within FixedUpdate
Yeah that part makes sense, just cant seem to get rid of screen tearing/jittery movement no matter how I configure it but ill keep tinkering with it, thanks!
Changing the transform directly can be fine in some cases, but it is like teleporting and therefore isn't considered by physics in the same way. This means that:
- the whole movement is applied at once instead of over several smaller substeps
- it can be easier to get more overlap as you're "teleporting" into other objects
- friction and restitution won't take the movement into account (since there is no new relative velocity)
- Continuous Collision Detection (CCD) may not consider the movement properly
Make sure you're not mutating the transform directly in Update or elsewhere outside FixedUpdate since that will currently break interpolation stuff
I assume you just mean the Transforms of the RigidBody entities specifically? What about if we mutate it once for say, changing location upon entering a new level?
This applies to all entities whose transforms are interpolated. Mutating Transform in Update like that works, and is perfectly fine for occasional stuff like moving to a new level, but it disables interpolation for the remainder of that fixed timestep, which could lead to very noticeable jitter if you're doing it every frame
Okay yup that makes sense, thanks again!
What's the new correct way to do child colliders? They get ColliderOf but should they also be ChildOf the RigidBody?
(neither seems to work for me but with different failures so I'm trying to work out what's wrong)
It should be the same as before, children of rigid bodies should automatically get ColliderOf pointing to the parent rigid body. But theoretically it should also be possible to have a non-child collider point to any rigid body too I think
Oh... hmm. I don't think that's what I'm seeing but I've probably broken it myself.
I need more tests for child colliders though, it's very possible there are bugs
The thing I'm having trouble with is a rather convoluted tool that adds colliders and rigidbodies to gltf models so it's also likely that I have bugs.
Specifically, I'm not necessarily creating the rigidbody component and the collider components in the same tick. Would that could a problem with your systems setting things up?
The examples in the repo like collider_constructors and dynamic_character_3d use child colliders loaded for glTF scenes, and work normally
Hmm something that actually might not work is if you add Collider first and RigidBody after π€ Is that happening in your case?
I should be able to fix that though if that's the case
I think I always do RigidBody first... let me make sure that's true.
Yeah, should always do bodies first and then colliders in the next tick
Hm, seems like that's broken yeah nvm my test scene itself was broken lol
Or... no. I think there's a case where I can go the other way.
Which makes sense, I think. Because it's clearly working sometimes and not others, which would make sense if stuff was just happening out of order for some models.
Ok, now I'm pretty sure I'm only making colliders if the body has already been made and I still see problems. Some colliders behave as expected but others seem to end up at a global translation of (0,0). They're in the scene and in the correct offset relative to their parent, if the parent was at (0,0) but it's not. And I don't think they are translating or rotating in sync with the body.
Yeah, they are not moving.
I have cases where the same body has multiple child colliders and some work but others don't. And... well actually this other case isn't a child collider. The collider is on the same entity as the body but it is also not working, in the same way.
Ok, I need to go back and rewrite some of this code. I'm not confident it's doing what I think it is so there's a very high probability that this is all my bug. I have to go do something else now but I'll let you know if it turns out to all be a false alarm.
I think there's definitely something wrong on the Avian side currently, I'm also getting some weird results
I guess this is what a release candidate is for.
LOL im so dumb my YSort was modifying Z values every frame on transforms in the Update schedule. I wish bevy had proper 2DTransforms.. One more odd issue: Is it normal for colliders to flicker occasionally and lag-behind when moving their rigid body via LinearVelocity? It is a little hard to see in this video but I figured the collider transform prop would be unnoticeable.
I made a PR that seems to fix the issues I was seeing, curious if it also fixes your problem
https://github.com/Jondolf/avian/pull/682
The flickers where the gizmos are darker are the bodies trying to start sleeping when they stay still for a while, but in this case they're always woken up (because transforms or velocities or something are being updated)
Are you using child colliders?
Yes each of the 3 colliders are children (bevy 0.15) , 2 sensors and one for physical collisions
The lagging behind might be because collider positions are only updated before physics, and so after physics, when debug rendering happens, the positions may be outdated
But for the actual physics simulation they should be up-to-date
I could probably fix this though
yeah i havent noticed any gameplay ramifications so that would make sense, was mostly a curiosity. Thanks for all the support!
Yeah, based on a quick check that fixes almost all the issues I'm having. Thanks so much! I've still got some lingering bugs but those probably are in my code.
Brought Windows tests down from 36 min to 18 min π
still not great of course, but a significant improvement
Yeah 2Γ is worth celebrating haha
Hey, I'm observing a weird issue in my game:
I have two entities, a sensor and a subject (with a collider). When the subject is a root entity (no parent), my sensor detects it fine (via CollidingEntities). All is ok.
If I attach the subject to the sensor's entity hierarchy, the subject is no longer in CollidingEntities. This is expected since now the collider is part of the same hierarchy as the sensor collider. All is ok.
But then if I detach the subject from the sensor hierarchy (i.e. remove_parent), suddenly my sensor doesn't detect the subject anymore (i.e. CollidingEntities is empty, even though the sensor is clearly colliding with the subject based on debug render). Is this a bug, or am I missing something?
With some debugging, I'm noticing that when the subject is detached from the sensor, the subject has ColliderParent component. If I remove this component manually, suddenly my sensor detects the subject again
Is there something I need to do to update physics hierarchy after detaching an entity...?
So I think I found the root cause. My subject doesn't have a RigidBody. But if I add a RigidBody things get strange when I attach the subject to the sensor (since now they're nested Rigid Bodies).
I've managed to solve it so far by manually inserting/removing the Rigid Body when the subject is detached/attached, and that seems to work.
Let me know if there is an easier way! π
I think as long as we provide the relevant context we can probably make filling the pipeline generalizable ... The bvh just needs to have AABBs, entities and layers for each each "primitive" ... Looking at obvhs I'm not entirely sure if it has everything necessary for efficient traversal, there is ray traversal and aabb traversal so you can probably implement all features but I doubt the traversal order would always be optimal π€
Oh and speaking of context, I realized mass properties don't get context ... I'm not currently sure how I would handle calculating mass properties for SDFs anyway so I'm not too concerned atm, but that's probably something that needs to be addressed (also worth considering that mass properties might just grab processed data from other resources, so it might not need the same Context either)
Back on the topic of the spatial query stuff ... It's also worth considering how components like RayCaster and the like handle the different BVHs, especially when it's possible to have multiple collider types in a world
If you can figure out a way to (uniformly) sample enough random points inside the SDF, it should be simple to estimate the angular inertia and center of mass
Yea that's kinda what I'm thinking too. I can essentially just estimate it by treating it as voxels + potentially some extra accuracy by moving towards where a surface is, though that has some limitation with bound colliders, though I'm not sure if I can even support those yet
I imagine this would be handled by just having a generic SpatialQueryPlugin (or similar) for each pipeline / collider type, and they all add their own results to the RayCaster hits. Just need to make sure you don't exceed the specified max_hits
Yea I guess that could work ... I wonder how we would decide which hits to keep though π
ShapeCaster should be easier though, it takes a shape so it needs generics anyway
Hi, is there an event for detecting collisions? I want to detect collision between the player and enemies, and give a special "dizzy" tag to the enemy when it is it by the player.
Here is finally the beast of a PR, massively reworking contact pair management and adding a contact graph
https://github.com/Jondolf/avian/pull/683
I sure am happy I don't need to go through the Bevy review processes for these right now π
I'll have the optimizations for contact constraint generation in a follow-up
I use the CollisionStarted and CollisionEnded events, you can find more details in the sensor example here: https://github.com/Jondolf/avian/blob/072ec52b6175c52392101ebad24a98aa0fd3bf4c/crates/avian2d/examples/sensor.rs#L234
Also works in 3D (which is where I'm using it)
Wow that is a lot of code change
Yup there's CollisionStarted and CollisionEnded like mentioned above. You can also use the CollidingEntities component to get all the entities colliding with the entity that has the component.
If you need actual contact data, or want to just check "are these two entities colliding", you can use the Collisions resource directly
A resource that stores all collision pairs.
Methods such as AnyCollider::contact_manifolds_with_context now take &mut Vec<ContactManifold> instead of returning a new vector every time.
π
Sounds like a free speedup to my SDF collisions
Yeah you can probably persist manifolds properly, I can't do that fully yet since I need the translation layer between Parry's ContactManifold and Avian's ContactManifold :P
CollidingEntities has just made my gravity system a little bit cleaner, thanks for that!
Literally the first line in my contact_manifolds_with_context impl:
let mut manifolds = Manifolds::<ContactManifold>::default();
```(`Manifolds` is just a newtype wrapper on `Vec<T>` where `T` is `From<Contact>` (an internal type that looks like `ContactManifold`))
Then I just pass mutable references to that around
question how do i get a collision normal? In my character controller if I continously apply a force into a wall, it glues to it. I guess i need to rebacle with a contact normal or something like that
Ah just read the docs, friction is a global thing
How would people feel about renaming
ContactstoContactPairCollisionstoContactGraph
The first one I'm fairly confident about, since the current name Contacts is pretty ambiguous (all contacts? contacts between two entities? contacts in a specific manifold?) and the code and methods already refer to "contact pairs" a lot. Rapier also uses ContactPair
Though just Contact could also make sense, and then we just say that a contact consists of one or more ContactManifolds π€ I think Box2D also uses b2Contact
Collisions is a bit weird since the new version also stores non-touching contacts, and only AABBs need to overlap. The term "Collision" sounds more like there's an active hit happening. Having "Contact" in the name would make things more consistent and clear imo, so ContactGraph (a graph structure storing contacts) would make sense
It is arguably more "intimidating" for users, but I would also consider it to be a more advanced API anyway, so it could be considered a good thing. I'm a bit conflicted there
The only interaction I've ever had with that resource is registering it for rollback ... Renaming it to ContactGraph would make that no more or less confusing π€
- for #1, no idea about #2
I do like the consistency of "ContactGraph stores ContactPairs, which store ContactManifolds, which store ContactPoints"
As opposed to 0.2 and earlier where it's "Collisions stores Contacts (for each pair), which store ContactManifolds, which store ContactData"
contactpair definitely makes sense to reduce confusion for people coming from other engines where contacts are per object
Especially when a ContactPair might not even be touching
I almost feel like we want a low-level ContactGraph resource, and some helper system parameter to abstract over the details like the fact that the graph also contains non-touching contact pairs
is this the contact-graph branch work?
Like maybe we have ContactGraph as a resource, and change Collisions from a resource to a system parameter that lets you fetch and iterate touching contacts, but doesn't let you modify or remove them (users should handle modification with collision hooks in 99% of cases)
Yup
I think I like this idea. We can make the semantics that "contacts" may or may not be touching, but the term "collision" always refers to touching contacts, which is already the case for CollisionStarted, CollisionEnded, and CollidingEntities
is this similar to the branch optimization-wise? π
This is that branch
but it doesn't have the contact constraint generation optimizations or solver body stuff, I have those on different branches
lol sorry, right
the solver body stuff would give the biggest immediate performance win, but I'm not sure how to make it neatly work with our XPBD joints, so I need to either hack some temporary workaround together or just... finish reworking our joints π
The latter sounds good
so you wish to delay good performance by another six months /s
BTW @vestal minnow, would you be open to a PR to make the spatial query stuff generic over colliders? And if yes, should that be obvhs powered or keep using Qbvh for now? Making that code generic and making an impl for non-parry colliders seems pretty doable ... It's gonna be a big PR though
Like damn the spatial query code in avian is big compared to the tiny file I had in my old spatial query stuff π
I would be open to that yeah, and using OBVHS would be great assuming it can be made to work for all of the different types of queries, and performance is roughly the same or better
I will probably need to rework some of it for the broad phase rework though, for that the plan is to have at least two BVHs (one for dynamic and kinematic bodies, one for static and sleeping bodies), and it would be shared between the broad phase and spatial queries
Colliders would be added/removed from the BVHs via the insertion/removal stuff Griffin has been implementing, and it'd probably rebuild the dynamic body tree in parallel with the narrow phase or some other part of the simulation (I think that's what Box2D does) to keep the tree quality good
Is the broadphase currently per-AnyCollider or universal?
It's the same for all collider types currently, just uses ColliderAabb
But the AABBs themselves are updated per-AnyCollider
By the ColliderBackendPlugin
(brb)
Hmmm ... I guess we have two approaches we could take there:
- Make the broadphase per-collider, so the BVHs can be per-collider
- Make the BVH generic by only putting AABBs in them and a
ComponentIdor the like of theAnyColliderimpl
Downside of 2 is that 2 collider components on 1 entity doesn't work. Downside of 1 is some extra overhead when multiple collider types are registered
Imo we don't need to support two different collider types on one entity, if people need that for whatever reason then they can use child colliders or something
idk when you would be using several different collider backends at the same time anyway
maybe if you had both 2D and 3D, but each dimension would probably have its own broad phase
Yea dimensions would definitely be split ... But I can imagine there might be people that want say SDF collisions, but also stackable boxes (which would be slow arbitrary SDF-SDF collisions over in SDF land)
But yea idk about putting them on the same entity ... Maybe if you have stackable boxes you'd need the player to have both collider types so you can still collide with the boxes ...
But child colliders would also be fine in that fairly niche case
They might be on different collision layers and whatever anyway
yeah
either trade-off is fine for me, whatever works best for the general case
having multiple collider backends at once feels like such a niche case that I wouldn't worry too much about it being perfectly supported for now, as long as it's technically possible
Okay, simple physics problem that I am stupid too solve. Lets say, I have Vec3 (0,1,0) at a step slope that I always have the information of (normal via shape cast) in this case the slope is 45 degrees, at tick 0. For what factor must I multiply to ensure that when I climb that slope, my y distance doesnt shift meaning in tick 1 I should be at (1,1,0)?
Case scenario: As the video shows, I want to avoid this Y axis jiggling from my floating character, when climbing slopes. Caused due to the distance change from the shape cast from tick 0, to tick 1
Whats your timeline on this btw?
I have some of it roughly implemented, but it probably won't be ready for 0.16 at least
hopefully early-ish in the 0.17 cycle
What is the best way to sync position of a dragged object to mouse position with physics?
I did a workaround setting translation to mouse position and then simulating forcefields around the objects.. which works, but I'm kinda implementing physics from scratch again then? especially when I want to have joints next..
2D or 3D?
2d
I have this old GrabberPlugin thing using joints for bevy_xpbd (Avian's predecessor before it was renamed), it should work but might have some small compilation errors that need to be fixed
https://gist.github.com/Jondolf/166ca879fa2994ba42b5e08a8807885c
ah so have a joint dragging it to the mouse position.. that's smart
I thought about setting the velocity so it would land at mouse pos in the next frame (which is not accurate) and then zeroing velocity.. this seems a lot better :D
I have this in the kinematic character controller examples, something similar might work?
// Points in the normal's direction in the XZ plane.
let normal_direction_xz =
normal.reject_from_normalized(Vector::Y).normalize_or_zero();
// The movement speed along the direction above.
let linear_velocity_xz = linear_velocity.dot(normal_direction_xz);
// Snap the Y speed based on the speed at which the character is moving
// up or down the slope, and how steep the slope is.
//
// A 2D visualization of the slope, the contact normal, and the velocity components:
//
// β±
// normal β±
// * β±
// β * β± velocity_x
// β * - - - - - -
// β * | velocity_y
// β * |
// *βββββββββββββββββββ*
let max_y_speed = -linear_velocity_xz * slope_angle.tan();
linear_velocity.y = linear_velocity.y.max(max_y_speed);
I guess in my head I just wanted to set the position and then afterwards tell the physics system, hey btw. it had this velocity, please calculate collisions
Updated the contact graph PR to rename Collisions to ContactGraph, but also added a Collisions system parameter as a simple wrapper to only provide touching contacts
I'll rename Contacts to ContactPair in a follow-up though
this is fine
how have I technically been working on this contact graph stuff for 3 months
might be one of my bigger PRs in a while
I have my players represented as 2D circles that are moved by a custom character controller. The inputs for these players are applied on the same tick which causes collision detection problems because the SpatialQueryPipeline doesn't have the latest position from the previous player who moved. Calling the update method for the SpatialQueryPipeline is really difficult to do because of system query conflicts while looping through the movement for each player. I'm using Avian2D just because it was convenient. If I don't need dynamic physics for the player movement, would it make more sense to roll my own collisions for the movement with bevy's built-in AABBs instead? It seems like Parry's API is the real limiting factor here.
@vestal minnow ty, that does work :)!! and with high enough lineardamping everything else doesn't just fly off :p I guess tweaking the parameters is a bit more tricky/needed then the less physics based way. can I just increase the speed of collisions resolution?
Is there any reason why an entity (a child entity) that has a dynamic rigid body component would not have its LinearVelocity updated? The velocity components are there (I do like required components, and those are required for rigidbody), but the values are all Vec3::ZERO. I feel like I'm missing something fundamental, like, "the velocities are relative to their parent entity" and I need to manually compute vels by checking GlobalTransform and PreviousGlobalTransform, but that seems like I'm just missing something.
the parent entity with a dynamic RB has the expected velocities when queried in systems.
Make sure the dynamic body has some Mass, a body without mass is treated kinda like a static body. If it has a collider though, it should automatically have some mass computed for it
Nesting rigid bodies in a hierarchy is also kind of weird and might not behave fully like you'd expect, so I wouldn't recommend it in general
The SolverConfig resource has some properties for configuring contact behavior, but I'm not sure if that's what you mean
Configuration parameters for the constraint solver that handles things like contacts and joints.
@vestal minnow two questions relating to the spatial query work:
- Do you know if there's any overhead to converting between
IsometryNdorPosition+Rotationto parry's isometries? - What the hell are
QueryPipelineAsCompositeShapeand friends? π
- Probably nothing significant, the internal representations should be basically the same
- Uhhh I copied it from Rapier, I think it's just a type that implements
TypedSimdCompositeShape, which makes Parry'sQbvhvisitors work. It basically treats the world's colliders as if they were all a part of a composite shape accelerated by a BVH, and every "part" or "subshape" is a collider
2 sounds kinda hacky, but I guess if we're doing obvhs we can just
that anyway π€
yeah feel free to 
Wait .... OBVHS ... doesn't do 2D? 
It doesn't, yeah. Ideally we'd add 2D support to OBVHS, but for now it could be fine to just always use 3D AABBs even in 2D
Ah right that hack exists π
I guess it shouldn't matter much either way unless we implement 2xVec2 SIMD, though I doubt many 2D games would even need that
Fair, I really only want it for querying though
Hmm when does external forces get converted into linear velocity?
I've been building a vehicle controller and was trying to use shapecasts, but doing so resulted in instability where there was a ton of jitter in the actual forces, and the vehicle body was affected. Switching to raycasts fixed the jitter, but I wonder if anyone has experience with this and if there's One Weird Trick. Note that changing the substep count had no real effect on it.
i had that issue due to ghost collisions, fix_internal_edges might help but i never ended up trying after switching to raycast
@vestal minnow heya, long time no see π
I'm updating my plugins right now and I'm wondering whether avian_interpolation still needs to exist. My main issue with your solution was the fact that it used to run after Update, which is no longer the case, right?
The other thing was that bevy_transform_interpolation caches more data as it does not know about Avian's components, but that's a minor difference. One could also easily improve that in your plugin by providing a backend feature or something like that.
oh hmm. I was using a sphere as the casted shape, which was projecting onto a cuboid, so I'm not sure if there's issues with trimeshes...
for what it's worth, I use raycasts for the wheels in my game. Shapes seemed like much more overhead just to avoid a little wheel clipping or whatever. Really depends on your goals though
Yeah, it's a pretty marginal difference; I know I'm not going to recreate beamng or anything and that's not the point, I'm just trying to make something that's interesting to do and fun to play with π
I had started with colliders and joints, so I've been sliding down the fidelity scale and I guess I'm landing at raycasts
Hiii, it's great seeing you around Bevy again π hope the thesis has been going well!
#5 indeed changed it to run in RunFixedMainLoopSystem::AfterFixedMainLoop (what a name) instead of after Update, so that shouldn't be an issue anymore
I think the biggest issue I've seen people have with bevy_transform_interpolation is that mutably accessing Transform outside of the fixed timestep, such as in Update, disables interpolation for the remainder of that timestep, and causes visible stutter. This is especially a problem in 2D where you might have a Z-sorting algorithm that changes Z coordinates every frame, breaking interpolation completely
There's a few ways we could potentially fix this:
- Ignore changes to
Transformoutside the fixed timestep, snapping to the interpolated value. I thinkavian_interpolationdoes this? It might break compatibility with some ecosystem crates that expect to modify transforms inUpdatethough, and doesn't really fix e.g. the Z-sorting problem since it wouldn't even allow you to change the visual Z coordinate to begin with. - Continue interpolation even after the
Transformis modified in e.g.Update, but change the "end state" of the interpolation to match the new transform. Doing this smoothly might be tricky since the trajectory of the body might change. Sometimes you also don't want movement to be interpolated, for example inbig_spacewhen changing transform grid cells. - For the 2D Z-sorting case specifically: Upstream
Transform2dto Bevy π or support only interpolating specific translation axes (might be costly)
I think something similar to 2 could be interesting to experiment with, alongside some command or something to let you actually teleport entities in cases where that's desirable. Similar to how Godot has reset_physics_interpolation
Not 100% sure how I'd best implement it though
Hmm maybe this would work for 2
Original interpolation is between start1 and end1. Then the desired end transform changes to end2. We want to keep interpolating from the same visual position, so the interpolation is now between start2 and end2
might need to do some shenanigans to put the start2 further back, since the interpolation value t wouldn't be 0.0 mid-frame
sooo it'd be like this I think π€
where the solid line is the actual path the object would take, and time t is the moment the end transform is changed
start1 is fixed step 1, end1 is fixed step 2, end2 is fixed step 3?
start1 is right before fixed update (the "old position"), end1 is right after fixed update (the "new position"), end2 is if something changes the transform before the start of the next fixed update (like some system in Update)
Right now I think the behavior in bevy_transform_interpolatipon is that if Transform changes to end2 inside Update, it will stay there without any interpolation until the next fixed timestep. So if you are in any way accessing Transform mutably outside FixedUpdate, the interpolation breaks, and you get stutter back.
This new idea would still keep end2 as the end position to reach by the time of the next fixed timestep, but it would continue interpolation from the current/old visual position to not just suddenly teleport the object
I think it should in theory fix the Z-sorting case and other scenarios where you get stutter from modifying transforms outside the fixed timestep
Do you know what the blockers are on getting Transfrom2D into bevy?
nth is working on a thread pool
But no realistically I think we just need to hammer out some details of how we'll handle transform hierarchies and mixing different types of transforms in an efficient and flexible enough way. And someone needs to actually implement it
some people also want to rework Transform not to have non-uniform scale since it causes some problems and can't really express some forms of scaling correctly, and to have an optionalDeform component or similar that also supports shear and skew and whatever other transformations you might want
(but it'd be purely visual afaik)
There were also talks of splitting rotation/translation too iirc
But yeah I can see how splitting things introduces more questions than answers overall
what are the other scenarios though, in every case i can think of it's better to modify rb velocity or position instead of translation... idk about animation though π€
Any scenario where some code touches transforms outside the fixed timestep. This could be some animation, or a third party crate that doesn't use fixed update for whatever reason
But yes in the vast majority of cases you should be using velocity or just changing transforms inside fixed update
also remember bevy_transform_interpolation isn't just for Avian and physics, it's for any entity with a transform
thanks 
great! You can blame me for that name, I just couldn't come up with anything better in my PR haha
Yep, I just ignore it.
The Z-Index thing didn't bother me personally since I only do 3D, but I see the issue
What's that drawing software, it looks gorgeous π
Have you ever checked the overhead the extra components add to complex scenes?
It's excalidraw, specifically the excalidraw plugin for Obsidian :P
I'm a liiiiiiitle bit worried since I have quite a few physics objects that need to be interpolated. I might be overly cautious here.
I haven't, I should probably make some simple scene with like a few hundred thousand (non-physics) objects moving around, and compare perf with and without interpolation
Yeah, that's the only part that is currently keeping me from archiving my plugin
I feel like it should pretty easily handle thousands of objects since it's just lerp and slerp in a parallel loop, and the systems for translation and rotation can also run in parallel
I'm more worried about the RAM tbh
fair
lol
Do you know a good way to measure this btw? Just... check task manager?
That's at least what my caveman brain would have done π¦§
Hmm I'm getting ~401 Mb without interpolation, ~440 Mb with interpolation. This is 100,000 entities with the full Transform interpolated
Note that with only translation interpolated, I'm getting ~411 Mb
When you say "without interpolation", no interpolation components get created at all for the entities, right?
If so, 40 Mb of RAM seems pretty reasonable π
Yup
Lovely! I'll retire my plugin then π
@vestal minnow I'm removing my interpolation plugin from the Bevy assets page. I noticed https://github.com/Jondolf/bevy_transform_interpolation is not on there. Is it fine if I add it?
Of course! Tbh I had forgotten that's a thing I should do
If you make a PR I'll leave an approval there
Cool! I'll add it under "Helpers", I suppose
Since "Physics" is explicitly not the only target
right?
Yeah I suppose Helpers might be closest of the current categories
though looking at the projects there it seems kinda like a dump pile of "uhhh where do I put this" lol
yeah definitely π
https://github.com/bevyengine/bevy-assets/pull/509
what's the best way to make a physics jump less fixedrate dependent and more deterministic while keeping the "accelerates continuously if you hold jump while touching a wall" behavior of a stateless Collisions check?
Merged the PR for the contact graph + pair management rework! Please let me know if y'all see any new bugs, it's a fairly big change to the collision detection internals
Next I think I will:
- Rename
ContactstoContactPair - Try vero's GJK+EPA implementation and compare its performance to the one in Peck/Parry
- Optimize contact constraint generation by moving it into the parallel contact update loop
@vestal minnow I'm updating avian_pickup and am getting these new conflicts:
Error when initializing schedule PhysicsSchedule: Systems with conflicting access have indeterminate run order.
3 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these:
-- set_velocities (in sets First, HandleVerb, Hold, SetVelocities) and update_previous_velocity (in set First)
conflict on: ["avian3d::dynamics::rigid_body::LinearVelocity", "avian3d::dynamics::rigid_body::AngularVelocity"]
-- update_previous_velocity (in set First) and drop (in sets Drop, First, HandleVerb)
conflict on: ["avian3d::dynamics::rigid_body::LinearVelocity", "avian3d::dynamics::rigid_body::AngularVelocity"]
-- update_previous_velocity (in set First) and throw (in sets First, HandleVerb, Throw)
conflict on: ["avian3d::dynamics::rigid_body::LinearVelocity", "avian3d::dynamics::rigid_body::AngularVelocity"]
Do you have some hints as to what could be going on?
set_velocities is my own system, I assume update_previous_velocity is coming from Avian?
I'm running my stuff .in_set(PhysicsStepSet::First). Is that a bad idea?
Hold up, PhysicsStepSet::First is empty by default according to the docs, so why is the error telling me that theres an update_previous_velocity in First? 
(this is avian v0.2.1)
Mm, update_previous_velocity comes from PhysicsInterpolationPlugin... I think PhysicsStepSet::First used to be properly empty, but over time some random prep systems have made their way there
I think that's actually the only system in PhysicsStepSet::First, we should just move it probably
Yeah that'd be great. I'll just put my systems .before(PhysicsStepSet::First) in the meantime, as I cannot order relative to that private function
just migrated to the 0.16 RC and i'm getting this panic:
thread 'main' panicked at /home/ty/.cargo/git/checkouts/avian-5a22c167119f3550/2ab588d/crates/avian3d/../../src/data_structures/graph.rs:231:27:
`UnGraph::add_edge`: node indices out of bounds
Encountered a panic in system `avian3d::collision::broad_phase::collect_collision_pairs<()>`!
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 `bevy_time::fixed::run_fixed_main_schedule`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
reckon this is an avian issue or bevy? full backtrace is too long to paste but can include in gh issue
Avian issue, related to the new contact graph stuff that I just merged... I'm curious how that's happening though, I haven't managed to reproduce that specific crash in any of my test scenes
I just made a fix to a somewhat related issue though, maybe you could try the fix-bit-vec-init branch to see if it magically fixes things? :P
https://github.com/Jondolf/avian/pull/686
Objective
The narrow phase is currently initializing the thread-local contact status bit vectors with a block count of zero. This means that for the first tick, contact status changes might not be ...
sure i'll try
nah, same result. the only silly thing i can think of that i'm doing that maybe you haven't tested is w/ RigidBodyDisabled and ColliderDisabled and manually setting translations while those components are set
so very likely i'm teleporting an object such that it overlaps with another collider and then removing those components
i intend to stop doing something as dumb as that eventually
Okay I managed to reproduce this, the only case where I'm getting it is indeed if I first add RigidBodyDisabled/ColliderDisabled and then later remove them
well gee whiz
I'll try to figure out what's going wrong there π€
oh god I'll also need to consider entity disabling for 0.16 won't I
Yes, I actually wanted to get some sort of support into 0.16 to make it automatically handled but that wasn't popular
there's four different ways to remove an entity from physics π despawn, remove physics components, add RigidBodyDisabled/ColliderDisabled, disable entity
mm right we have this problem I had also forgotten about π€ the contact graph stores a custom EntityDataIndex structure that maps entity IDs to node indices, but it allocates space for every entity up to the largest stored entity index... this works fine if the IDs are just collider IDs, but we're using Entity IDs directly, so if you had e.g. 999,999 non-physics entities and just one collider entity at the end, it'd allocate a million elements
(here there's only one collider, but it's entity 39v1, so it allocates 39-ish elements)
we'd need to maintain separate ColliderIds to fix this properly, or rework things to map entities to node IDs in some other way
is there a way to temporary pause the physics? I'm trying to make a pause screen
thank you it worked
is there a way to make a distancejoint bouncy?
you can use with_compliance to make it softer (the default is 0, which is infinitely stiff)
ah I changed that to make it comply to the constraints faster or slower..
I was imagining slow compliance to the min distance and then bouncing back a bit
which would mean two distinct variables
This should get fixed by #688
Objective
When a collider is removed from the contact graph, the EntityDataIndex used for mapping entities to graph nodes is not updated. This can cause bugs and even crashes when an entity with th...
It was just a dumb oversight where it wasn't clearing removed colliders from a structure that maps entities to graph nodes
so I guess I would need to simulate it by myself atm..
Not sure I have the knowledge or energy :P
Other question... more important&confusing
the magenta squares are the aabbs I'm using in a spatial query to find touching colliders. the yellow circle around the red nodes should be the debug rendering of their colliders.. the magenta line between them shows the spatial query is returning one from the other... now I'm just very confused why, as the aabbs obviously don't touch the colliders
the aabbs are touching each other
ah right.. another layer of aabbs
I always forget
thanks π
there cannot be enough gizmos to make this clear to my brain
nice!
Hmm I'm trying to fix this by adding a ColliderId component... It should be an opaque identifier represented as a generational index, which is exactly what Entity is. Question is, do I make it internally store Entity, even though it doesn't actually represent an entity in the ECS sense, or do I copy the whole Entity type
TIL Bevy also has an Identifier that is "for all entity and similar IDs" except it packs an IdKind into the high bits which I don't necessarily want
bleh I guess I'll copy Entity for my purposes, it's not that much code
yep, fixed
to the actual thing I tried to solve.. is there a way to hackily enable sleeping for jointed RigidBodies? tried to inserting Sleeping manually, but it's ignored/removed when connected to a joint, is what I take from that message?
Yes, sleeping currently doesn't work with joints
can I work around it?
detecting when one of the rigidbodies moves to then disable sleeping in the other should work kinda?
so I'd need to modify the library?
Yeah; we don't have simulation islands just yet (though I do have an implementation in the works), and without them we only have per-body sleeping, which can be problematic for various reasons for objects that are interacting with each other
which is why sleeping is currently used only for dynamic bodies that aren't interacting with other dynamic bodies
I don't have a complex physics simulation, I just use it for graph layouting so I guess that's why I'm not too concerned, but I understand that's not the main target for the library.
Looking forward for islands :)
And maybe I can work around it for now.
thanks for your help!
I have a question on FixedJoint: let's say I have two entities that were spawned independently with different Transforms. I would expect that spawning a FixedJoint like this:
commands.spawn(FixedJoint::new(id1, id2).with_local_anchor_1(Vec3::ZERO).with_local_anchor_2(Vec3::ZERO) would just fix them relatively to each other with anchors located at their centers. But they actually become overlapping each other like the joint overwrote the transform of one or both of them.
Why do I need to know the local position of one with respect to the other at the moment of the joint creation to obtain the desired result?
The local anchors are the points on each body that the joint attempts to align. If the anchors are just zero, it means that the joint will make the centers of the bodies align.
The joint needs these values in local space, because if they were in world space, they would become invalid as soon as the bodies are moved or rotated. We could have an API however to help initialize the anchors more conveniently in world space
If you guys had to make hitboxes that are basically cuboids , which dimensions rely a tad bit of the given mesh information. How would you guys do it?
that'd be great. Because I find myself often creating objects and then having to translate the global translation and rotation into local just to create a FixedJoint. Ideally in my opinion, the simple operation commands.spawn(FixedJoint::new(id1, id2)) should preserve the Transforms of the two objects while constraining their relative motion from then on.
Yeah, makes sense. I think it should ideally default to preserving the initial relative transforms, but you could still also manually specify the anchors in either local or world space
Hmmm maybe I actually want to keep using Entity but should switch to slotmap::SparseSecondaryMap π€
or just an EntityHashMap if I want to be really simple
too many choices aaaa
Welp, I ended up vendoring my own version of slotmap::SparseSecondaryMap since it had some problems (like not supporting no_std)
branch here, a bit WIP though
hey, sorry if this question has been answered many times, but discord search is hell
i'm trying to spawn a very minimal scene for testing but i can't get a capsule collider to behave, as it keeps bouncing
// this is just a cube
let scene = assets.load("models/level.glb#Scene0");
commands.spawn((
SceneRoot(scene),
ColliderConstructorHierarchy::new(ColliderConstructor::TrimeshFromMesh),
RigidBody::Static,
CollisionMargin(0.1),
));
// "player"
commands.spawn((
Visibility::default(),
RigidBody::Dynamic,
Collider::capsule(0.25, 2.0),
LockedAxes::ROTATION_LOCKED,
LinearDamping(0.8),
Transform::from_xyz(1.0, 15.0, 1.0),
Player,
));
here's what it looks like
(light mode warning, sorry about that)
I uh.... I'm so sorry. I "fixed" it and I have no idea how
at first I thought the CollisionMargin component was the problem, but then added it back in and everything still worked
source control rollback and recheck? or somehow a cache/local issue
it's a very minimal "hello world" type of thing, no meaningful vcs practices
I'm more inclined to blame the export Blender at this point
but I'll keep an eye out, sorry again for the spam
@vestal minnow not sure if I asked this before, but would you mind giving avian_pickup a little code review before I publish it? π
I recommend running the prop_playground example, that one's fun to play around with
Sure, I'll give it a review later today
Made a smol documentation clean-up PR like you saw. Overall it looks pretty great, and the examples feel nice!
A few things that came to mind:
- I'm not sure I love using
EventWriter<AvianPickupInput>for performing actions; in general, I treat events as a way to respond to things that have happened, not as something that makes things happen by itself. - Maybe
PropThrownandPropDroppedshould be observable events? This would allow you to observe specific entities, which could be useful for e.g. sound effects or other things that may vary per prop. - For 0.16: Avian has a
RigidBodyColliderscomponent now, which should simplify therigid_body_compound_colliderstuff.
Also, I noticed that inplay_catch, R doesn't seem to actually reset the prop?
Another small thing: There's a solid chance this is intended, but often when I'm grabbing things that are close to each other, it kinda shifts focus between them and ends up launching both towards the player, rather than locking onto one
- I don't love it either :/ Very open to suggestions!
- Good idea, I like that. In general, I tried to stick to events due to ordering and better potential performance when running a lot of actors, but I may have been overly cautious
- Ah, great, thanks! Is the Avian
mainbranch ready for me to already target it? I assume you have not yet released an Avian RC, right?
The "R" thing is weird, I cannot reproduce it. I just googled "Finnish Keyboard" and it says that the R key is on the same physical location as on the QWERTY keyboard, so that's not an issue. hmmm.
Honestly, not sure what HL2 does in this case. I'll check π
Thanks for the review in any case π
Oh huh, seems to be a system ordering issue. On some runs it works, on others it doesn't
Avian's main branch is targeting the Bevy 0.16 RC, but I haven't made a release yet, there are still a few more things I'd like to land. I'll probably make the release once 0.16 is fully out, like in the past

I'll try to target it later today and report back on whether I encountered any issues π
I'm really puzzled why this is the case. The reset logic runs in RunFixedMainLoopSystem::BeforeFixedMainLoop, so it should
- run every frame
- run before avian_pickup
- run before avian itself
Update: Avian main + Bevy 0.16.0-rc works like a charm π Only had to change ColliderParent.
I'll now try the RigidBodyColliders
@vestal minnow are all rigid bodies guaranteed to have a RigidBodyColliders component?
ColliderOf is a Relationship and RigidBodyColliders is the RelationshipTarget, so it should exist on all rigid bodies that have one or more colliders attached
Mind giving me a hand? I tried this, but the new behavior is buggy; the held distance is too big and somehow changes when I turn around while holding the prop
Update: think I got it
Btw, I lost track of the difference of Position + Rotation and Transform while interpolation is active. I remember that with my plugin, I had a strict "Transform is screen stuff, Position + Rotation is the real physical simulation" doctrine. Does Avian's interpolation just handle everything so that Transform is the physical position during PhysicsStepSet::First?
Yeah, the code should be using the colliders relative position to the rigid body and not their global positions
(By transform I mean GlobalTransform, sorry)
Position + Rotation is always the physics position, and isn't affected by interpolation. Transform gets interpolated in between fixed time steps, and always matches the "true" Transform (the end state of the interpolation) after FixedFirst, before any physics stuff runs.
So Avian itself doesn't really see transform interpolation in any way, it's all handled by bevy_transform_interpolation and primarily happens outside the fixed update
So, am I understanding it correctly that I can safely change all my references to Position and Rotation to use Transform?
(if the object in question has no parents)
I don't think you update GlobalTransform, right? So that one would be outdated, I presume
Hmm I believe GlobalTransform is currently updated for physics entities in PhysicsSet::Prepare, right before the PhysicsSchedule
Oh, so I can just use GlobalTransform everywhere?
Is there a best practice you would recommend?
Mmm I would say yes, you should be able to use it pretty much everywhere. I don't know if there's anyone using only Position and Rotation without GlobalTransform (and if we even care about supporting that)
Alright, I change avian_pickup to only use GlobalTransform then
I still personally consider Position and Rotation to be primarily internal physics components, not something the average user should be using. So in general, I would encourage people to use the de facto transform components provided by Bevy (Transform and GlobalTransform) unless there is a clear reason not to
of course the transform situation in Bevy isn't ideal either though, 2D transforms sure would be nice...
Alright, I'll change the crate accordingly π
I just update to the latest main and now EventReader<CollisionStarted> doesn't seem to be yielding any events? Collisions are still happening in the simulation but those events don't seem to be going out any more. Did something change?
The sensor example prints events, so they are working there. Sigh. Must be something I've done.
Collision events are now opt-in with the CollisionEventsEnabled component, since you very rarely need events for all collisions, and it had some overhead. This is also the default in e.g. Rapier, Box2D, and so on
Migration guide in this PR
Ah, that makes sense. And it was right there in the example. I'm just blind. Thanks.
Oh lol this is wrong, PhysicsStepSet has not been removed π that's meant to be PhyicsStepSet::ReportContacts
I actually think I'm going to switch to CollidingEntities which suits my usecase better.
Hadn't noticed that before (maybe it's new).
And replace all the places I manually query Collisions
Just fixed a pretty major bug in bevy_heavy's AngularInertiaTensor::shifted method (an incorrect sign), which fixes angular inertia computation for child colliders in Avian. I had this bug because I originally used Parry as reference for this, and it's wrong 
Kinda wild how Parry/Rapier still has bugs like this and people haven't caught it, it's a major correctness issue and makes behavior weird for compound shapes, including colliders using convex decomposition or convex hulls I believe
Here you can see it being broken in bevy_rapier3d. The body with three boxes joined together is using child colliders (Collider::compound is similarly broken) while the other body is just a single cuboid. The mass properties should be the same, but the angular inertia for the compound one is wrong, 4.5 instead of 0.5 for the y axis, which leads to it spinning with much more inertia and overall behaving wonky
(the initial velocity and orientation is the same for both, the video is just trimmed a bit from the start)
Avian was similarly broken before, but it's now fixed for child colliders, so this three-cube case behaves the same as the single tall cuboid. Collider::compound is still broken because of Parry though, so I'll need to fix that upstream
Fix for Parry here
cc @grizzled depot, this one is pretty important
Thx! Iβll check it out tomorrow, canβt look right now so Iβm not sure if that might be related to https://github.com/dimforge/parry/pull/331
Yeah no hurry! That PR is different, that just fixes the unit angular inertia tensor computation for tetrahedra (and therefore trimeshes). My fix is for MassProperties::construct_shifted_inertia_matrix, which is used when summing MassProperties together, which is done for compound shapes and child colliders
woah, I've seen this happen in avian_pickup after yeeting stuff! I just assumed physics worked like that, haha
will avian properly handle spin caused by friction on colliding spheres? e.g., for pool / billiards.
there are a lot of pool nerds who know how the game works with real-life physics. im hesitant to make a pool game without looking into physics engines, since i'm sure someone would complain if the physics weren't just right.
i'm not a physics programmer, so i don't know if the important factors in cue ball physics are trivial to physics, or something that is usually simplified / glossed over in physics engines.
im sure pool snobs are used to inaccuracies in digital versions of the game, though. but getting spin upon ball contact feels like something that should be handled somewhat properly for a pool game.
It should be fairly accurate, but I don't know pool well enough to really say
I imagine there might be a lot of very subtle details that are important in pool but might not be perfectly accurate in a game physics simulation
if a spinning sphere hits a stationary sphere, will the stationary sphere start to spin?
i think pool / billiards is such a niche case that it doesnt reallly matter if this particular thing isn't handled correctly in avian. i was just curious if the answer to this is known / presumable by someone smarter than me lol.
the ground / plane the spheres are on should have 0 friction, just a heads up!
with some restitution
how do people hook sound into Avian anyway? i tried with collisions' normal total impulse and it didn't work properly with anything but two boxes in a vacuum
aye! nice
Oh heck, we have a similar problem for the SpatialQueryPipeline, with Parry resizing its vecs for the Qbvh to contain max_index + 1 items. Unlike the contact graph stuff where it mainly costs memory, here it's actually horrible for performance (this is a million empty entities and 1276 collider entities)
so yeah we need ColliderId...
why does it allocate space for every entity ID?
Would this be fixed with obvhs?
I currently hand it entity indices for indices and ofc collider aabbs
Not sure, but I think so? We could handle this differently on Avian's side too though
I think regardless of the BVH, we need to map BVH proxies to entities and vice versa
I think this is because the AABBs must be stored contiguously for perf reasons, and the indices correspond to the vec indices. To make sparse Entity IDs work without unnecessary allocations, we need a mapping from Entity IDs to these BVH indices
@vestal minnow I'm back to working on the SpatialQuery stuff ... Have some partial progress, but I'm now at the point where I need to make some architectural decisions on how this will look ... I'm thinking we can just make SpatialQueryPipeline collider-agnostic, then pass in the collider type from SpatialQuery (which can default to C = Collider if that's enabled) ... Then we could either pass that type + necessary context to the methods, or we just pass a method to SpatialQueryPipeline that returns the necessary data ... The latter sounds cleaner, and lets us remove _predicate vs not-predicate from this layer ... And we would need a QueryCollider trait or whatever which provides raycast impls, shapecast impls, etc
Alternative would be to make SpatialQueryPipeline per-collider, which gives us the generics there to do things directly, but we would still need to take a Context there as input
Sounds good, changing SpatialQueryPipeline to be collider-agnostic probably makes sense... I'm guessing you'd then pass the methods a query or something for fetching colliders?
so it'd mainly be just a wrapper around a BVH, with methods for querying it
Also damn I'm experimenting with yet another redesign of the contact graph stuff, it sure is going through a lot of iterations... We need collider IDs that are separate from Entity, but we also need to map those to nodes in the contact graph, so I was thinking I could combine these and use a generational arena to store the next_contact edge index for each collider. This way the contact graph node indices would be the collider IDs themselves, and I can minimize mapping stuff
Kinda, we pass in a FnMut that queries stuff + runs the collider-specific calculations + does any _predicate or other method-specific logic
Yeah that sounds fine
When it comes, to rigidbodies, the kinematic bodies are affected by the transform component, but not the dynamics bodies those ones you should hard set via position and rotation components?
The Transform -> Position/Rotation applies the same to all RigidBodys, but you don't want to be updating positions during a simulation at least, that'll be treated like teleportation after all
Ah yes if you dont have syncconfig tranform -> position which I had e.e
This is just to set start position
PhysX source code released: https://github.com/NVIDIA-Omniverse/PhysX/discussions/384
This sure is becoming one hell of a type
#[derive(SystemParam)]
pub struct SpatialQuery<'w, 's, C: QueryCollider> {
pub(crate) colliders: Query<'w, 's, (&'static Position, &'static Rotation, &'static C)>,
/// The [`SpatialQueryPipeline`].
pub query_pipeline: ResMut<'w, SpatialQueryPipeline>,
context: StaticSystemParam<'w, 's, <C as AnyCollider>::Context>,
}
What are the swing_axis and twist_axis fields in SphericalJoint?
@vestal minnow do you think there would be any value at all in having "get the ray hit distance" and "get the ray hit normal" separated? OBVHS is largely set up to just take a distance and then compute the rest at the end, but we could just combine it too
cast_ray should probably still return the full RayHitData, but we could have an additional ray_distance query yeah
also why did I name it RayHitData and not just RayHit π€ should probably be renamed
or maybe RayCastHit and ShapeCastHit since ShapeHit would be a bit more ambiguous
You can think of spherical joints as having a sort of "limit cone", where the relative orientation of the bodies is limited to remain within a cone shape. twist_axis is the axis passing through the apex of this cone (from the tip to the base or vice versa), and the swing_axis should be any direction parallel to the base of the cone. These axes essentially determine the orientation of the cone.
Then, the swing_limit determines how wide the cone is, and twist_limit determines how much the bodies are allowed to rotate relative to each other on the twist_axis
Roblox actually has a pretty good visualization of this π
https://create.roblox.com/docs/physics/constraints/ball-socket
I was mostly thinking about the QueryCollider trait methods, but I guess if we do support it separated this would actually be a pretty nice optimization I guess π€
is transform interpolation broken? when I enable it, everything seems to slow down and gets even less smooth
might be this thing #1124043933886976171 message
I am changing the rotation of the transform but not the translation
doesn't matter which property it is, mutably accessing the Transform at all currently affects transform interpolation since it updates the component's change detection ticks, and the interpolation isn't aware of what changed and what didn't
for ExternalForce::apply_force_at_point(), it says that all the arguments (force, point, center-of-mass) should be in world space, but what does that mean for a force?
ah, I see, rotated by the parent xform
2d: if I have a row of flush square colliders as part of a same static rigidbody (its a tilemap with a flat surface), a dynamic rigidbody moving on top of them bumps up when it meets each corner. is there something i can do about it? (short of merging these squares into a single polygon or something)
can try changing the physics scale or body's ccd
best bet is to make a hull or otherwise compose the colliders, though
for sure i'd do that if it wasnt for ludum dare xD
edit: ccd or scale didn't work
then maybe just do a quick trimesh of two tris per square
like 2 polylines per tile? not sure if that'd be any better
i kind of got it looking ok by playing with the gravity and timestep, good enough for now, can only notice it maybe 10% of tile crossings
What's the best way to apply a force as if it were applied from a certain point offset from the center of the rigidbody?
What would be the best way for multiple objects to all contribute an immediate force to a single body ?
I could have a persistent external force on it but that would mean resetting it to 0 every frame.
Guess i'll do that but wondering if there is a more ergonomic way
Seems like resetting it every frame prevents all movement, even though I reset it before the frame. Not sure why
ExternalForce/ExternalImpulse components, I think? They have functions to apply at points
There's a setting on the external force component to clear it every frame
Yeah that's what i'm using (ExternalForce), it's the resetting that is tripping me.
I want the force component to remain, since it means I don't have to spawn a new one every frame.
So I tried .clear()-ing it's value in Pre/PostUpdate but both simply stop all forces
Try using the persistent field set to false
I tried messing with peristence but it didn't help
I'm going to make a simple reproduction
fn main() {
App::new()
.add_plugins((DefaultPlugins, PhysicsPlugins::default()))
.insert_resource(Gravity::ZERO)
.add_systems(Startup, setup)
.add_systems(PreUpdate, reset_forces)
.add_systems(Update, force)
.run();
}
use avian2d::prelude::*;
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins((DefaultPlugins, PhysicsPlugins::default()))
.insert_resource(Gravity::ZERO)
.add_systems(Startup, setup)
.add_systems(PreUpdate, reset_forces)
.add_systems(Update, (force, gizmos))
.run();
}
#[derive(Component)]
pub struct Car;
fn setup(mut commands: Commands) {
commands.spawn(Camera2d);
commands.spawn((
Car,
RigidBody::Dynamic,
Mass(1.),
ExternalForce::default().with_persistence(true),
));
}
fn reset_forces(mut cars: Query<&mut ExternalForce, With<Car>>) {
for mut force in cars.iter_mut() {
force.clear();
}
}
fn force(mut cars: Query<&mut ExternalForce, With<Car>>) {
for mut force in cars.iter_mut() {
force.apply_force(Vec2::Y * 100.);
}
}
fn gizmos(mut gizmos: Gizmos, cars: Query<&Transform, With<Car>>) {
for transform in cars.iter() {
gizmos.circle_2d(transform.translation.xy(), 10., Color::WHITE);
}
}
Here is the minimal reproduction
I also tried this while creating a new External force component every frame but it also doesn't work
you're applying the force in Update (after physics) but clearing it in PreUpdate (before physics)
so it never really gets applied
I see, thanks
I ended up using persistence = false which worked just fine.
I'm now struggling with angular velocity staying at 0 even though it's saying my external force has torque.
Make sure the body has AngularInertia or a collider that automatically gives some angular inertia. Zero angular inertia is invalid and treated as infinite (like a static body)
Hello again, is there a built-in way to get the linear velocity at a point of a rigidbody ?
Something like rapier's linear_velocity_at_point or unity's getPointVelocity ?
Would be really handy for my vehicle physics
There isn't really a convenient helper for velocity directly, but it's just lin_vel + ang_vel.cross(offset), where offset is a point relative to the center of mass
Or if you use Query<RigidBodyQuery>, then the returned items also do have a velocity_at_point helper
thanks
I tried the first one, and my code didn't work so I tried the WorldQuery which also didn't work (probably an error in my code), but the surprising thing is that they didn't agree on the linear velocity for the same point on the same body, so i'm not sure which one to trust
They are kind of flipped version of each other
[4.5047007, 9.038669] [-9.071604, 4.513233]
This is your formula I adapted for my 2d case
let tire_vel = **velocity + **angular_velocity * local_transform.translation.xy();
for 2D it's lin_vel + ang_vel * offset.perp()
thanks that was it
I was looking though the examples for avian2d and cant seems to find anything on creating colliders using something like a polygon. Would anyone happen to have any info on this
https://docs.rs/avian2d/latest/avian2d/collision/collider/struct.Collider.html#method.trimesh
Or one of the other methods there, like convex_decomposition
Or maybe polyline if you really just have a single polygon.
Thanks trymesh works I just had to meshify my polygon first.
Are there any examples/resources on implementing so called 'soft constraints' described here: https://docs.rs/avian3d/latest/src/avian3d/dynamics/solver/softness_parameters/mod.rs.html
That's just how Avian's contact constraints are implemented internally
(and how joints will work once we switch them away from XPBD)
@vestal minnow FYI PreSolveRotation and GlobalAngularInertia are not type registered, so a Scene I loaded in avian "0.2.1" that contained those types crashed at runtime. I manually added them, not sure if I should open a PR or whether you fixed it already.
I haven't fixed that IIRC, there might be some other types too that aren't registered
hmm maybe we could have some test for it so that (some) missing registrations would get caught by CI π€ like spawn a rigid body and collider, turn that into a Scene, and try to load it
I think that would be neat, yeah
wouldn't catch everything (unless we manually add all components :P), but the required components that get auto-inserted
There ya go https://github.com/Jondolf/avian/pull/691
I never know what labels to use for stuff like this π₯² does this count as C-Bug, or C-Usability, or...
Yes
would it be possible to implement caching for ColliderConstructor::TrimeshFromMesh so that all entities with the same Handle<Mesh> use the same SharedShape? as it stands, if you try to construct hundreds of colliders with the same trimesh it will duplicate the vertices across each instance for the collider and spike the memory usage
IIRC that should be simple to implement
Hmm but then again, Collider is always inserted directly into colliders, there's no Handle<Collider>
I suppose one could create a kind of collider that holds an internal RwLock and clone that across all objects with the same Handle<Mesh>?
I take that back, maybe it's not that simple
im looking at it a bit. internally, colliders hold a SharedShape, which is an Arc for the collider mesh data. so the machinery is there to support this, its just a matter of hooking it up
currently im trying to add a MeshColliderCache resource that's just a HashMap<AssetId<Mesh>, Weak<dyn Shape>>, both weak pointers so they don't keep references to the mesh/colliders alive unnecessarily
i still need to differentiate between convex hull / convex decomposition / trimesh, but baby steps
hmm, i thought it would be that simple, but the memory usage is still spiking high....
ill try to work on it more tomorrow, i think im just missing something obvious
okay from further testing it seems that the majority of allocations come from contacts, NOT from the colliders themselves π
I remember a year ago there was this thing about contact reporting needing to be opt-in to be efficient. Has anything happened in that regard in the meantime?
it's opt-in on main
the new contact graph stuff has a small memory usage problem, which this should fix, but I'm not entirely satisfied with the solution there so I'm experimenting with alternatives
but contacts still also just inherently require a decent amount of memory
yeah, i forgot that collision contacts would induce allocations
Congrats on finally implementing it, I remember you were mentally chewing on that for a while π
thanks π it's a part of this pretty chonky PR
https://github.com/Jondolf/avian/pull/683
Is it just me or are these performance improvements huge?
they are, I also have an optimization that cuts the combined cost of the narrow phase and constraint generation in almost half again (if multi-threaded)
#1124043933886976171 message
Damn, not bad
I see, my dream of yeeting 100 boxes at the same time can finally be fulfilled
I also have a SolverBody optimization that makes the solver (our biggest bottleneck) more than twice as fast, but that's kinda blocked on me finally switching joints away from XPBD (or doing ugly hacks)
Uuuh that one is one of the upstream blockers
Love it when one of those gets resolved
I do have impulse-based 2D and 3D revolute joints and spherical joints working, it'll get there eventually...
it's not a very motivating thing to work on tho since implementing the math is way more complicated and the immediate result is likely slower than with XPBD
I've been using that branch for my game and it gave me like 20-30+fps improvement, I was like π€© when I first switched to it
You mean the main branch or something else?
the contact-graph branch
do AnyCollider impls only work for interactions between those colliders?
seems so, though it's possible IntoCollider can smooth things over a little
Hello, wondering if there are plans to make mass independent "forces", similar to ForceMode.Acceleration in unity
I find it really useful when having to tweak enemy masses for example without affecting their speed
Also wondering if there is a way to get the direction of a collision ?
Someone correct me if I'm wrong, but it looks like that data is in the ContactManifold
A contact manifold between two colliders, containing a set of contact points. Each contact in a manifold shares the same contact normal.
I guess an average or something would get me there
I guess I'm not sure what you mean by direction of collision.
Do you mean the direction from entity1 to entity2?
The ContactManifold.normal1 seems to be that value.
Disclaimer, I haven't used that feature, so I could be misunderstanding it.
Correction, normal1 isn't the direction from the entity to the other entity, it's the normal shared by all contact points in the manifold.
you probably want the position relative to the center of mass
I'd like to implement something like that, yeah. I have a redesign of the force APIs half-implemented on a local branch, just haven't had time to focus on completing it
I tried switching my project from rapier2d to avian2d, but encountered a strange issue. When a ball naturally slows down to a stop, changing its CollisionLayers has no effect. Iβve already added SleepingDisabled to the ball and set the global SleepingThreshold to a negative value, but modifying CollisionLayers still doesnβt work. However, when the ball is still moving, changing CollisionLayers works as expected.
Does avian support computing mass properties for hierarchies? Like if I have a single dynamic rigid body with two children with mass + moment of inertia + transform offset, will the root entity calculate its mass properties with respect to the whole hierarchy?
Yeah by default children colliders mass is accounted for in the parent rigid body
Hi, I am trying out avianand I believe I've ran into a bug. I am listening to collision events with an EventReader<CollisionStarted> and I modify the collision layers of the colliding entities after the collision has started. However, it seems that sometimes this causes the collision not to resolve correctly and the two colliders end up passing through each other.
I think this is a bug because the CollisionStarted event is fired correctly, but I assume because I modify the collision layers the rest of the collision does not play out correctly.
have you tried ordering your listener after physics entirely?
Yes, although I'm not 100% sure what would be the correct scheduling here as I'm relatively new to bevy/avian.
Would app.add_systems(Update, handle_collisions.after(PhysicsStepSet::Last)); be correct?
sometimes
you want FixedUpdate or Physics
specifically: fixed schedules happen during update, but sometimes don't happen or happen multiple times depending on frame time
Ah, good catch on Update vs FixedUpdate but it does not make a difference for the issue I mentioned though. Also, I'm a bit confused by what you mean by Physics as that's not a schedule.
maybe it's PhysicsSchedule or something
you could try delaying the layer change by a couple ticks
*before Update π
thx
more detail: https://docs.rs/bevy/latest/bevy/prelude/struct.Main.html
0.16.0-rc.4 removes the bevy_log feature flag in favor of tracing
Hi, I ran
git clone https://github.com/Jondolf/avian
cd avian
cargo run --example one_way_platform_2d
rustc complains thus:
It's getting reverted again :(
https://github.com/bevyengine/bevy/pull/18816
I'm guessing this is a bug where changing CollisionLayers while the body is already in contact doesn't update the contact pair. I'm working on a fix to that now
It's technically easy to fix, there's just three different ways I could do it
- Have a system that just queries for
Changed<CollisionLayers>and removes contact pairs whose layers no longer match. Requires full table scans :( - Same as 1, but make
CollisionLayersan immutable component, and observeOnInsertevents. More efficient for sparse changes, but makes changing layers a bit more annoying :( - Always check if layers are compatible in the narrow phase. Adds a (very) small extra cost for every contact pair :(
Definitely not a fan of 1 at least
yeah I'll probably just do 3 for now, and leave a TODO to handle it better if we ever get fine-grained change detection
I think I found an interesting bug in the process
I'm setting CollisionLayers::NONE at runtime for all colliders in this test scene, but for some reason it only removes half of the contact pairs at a time, even though it should remove them all at once
edit: figured it out
is there a stable approach for "teleporting" a dynamic rigidbody while keeping its momentum? I've been just changing the entity's Transform but not sure if that's a good idea
I think the key to "stable" teleporting is really just to not teleport into something, doesn't really matter how you move it since it's always going to be weird, and Transform vs Position/Rotation doesn't make much of a difference here
I suspect what I'm running into is that the interpolation makes it stutter just slightly... seems like I should be modifying the linear velocity instead? Like... apply a significant force for one frame?
Applying a significant force sounds like a recipe for disaster, you'll hit something and it will explode ... I think Jondolf talked about a way to skip interpolation for frames with a teleport before π€
yeah, I think he had a couple ideas but not sure what he ended up going with
I don't think we got a real solution, but you might be able to just modify the thing for interpolation and make it so that the from and to values are the same
I guess, maybe this is an XY problem... what I really want is to put the player in a repeating area for a variable length of time and then when some condition is met have them able to exit the area
like uhh mario 64's repeating stairs
I can't decide whether it's better to handle that by teleporting or by spawning more area in front of the player forever
Spawning more area for ever could end you up in inprecision land which isn't ideal π€
If you need it to be smooth you might need to modify both the start and end of the interpolation so it's the same as if would've been if you hadn't teleported but just started there
that's kinda what I was afraid of
I wonder if disabling interpolation during teleportation would work
If you disable it you'd notice that the motion isn't continuous anymore
Note that changing
Transformmanually in any schedule that doesn't use a fixed timestep is also supported, but it is equivalent to teleporting, and disables interpolation for the entity for the remainder of that fixed timestep.
hmm, I might not be able to get around that
Fixed some of the contact pair removal problems
https://github.com/Jondolf/avian/pull/693
Objective
Contact pair removal currently has some issues.
Contact pair removal is done using the EdgeIndex directly, but removing an edge can move the indices around (due to swap_remove), which ca...
and also left a lengthy comment re: observable collision events
https://github.com/Jondolf/avian/issues/481#issuecomment-2798807785
hmm yeah this is an interesting scenario, it'll also be relevant for big_space support I think (changing grid cells without breaking interpolation)
We should probably add a command like Teleport to bevy_transform_interpolation that teleports the given entity to the given position, kinda like changing the frame of reference, but allows keeping the smooth interpolation in some way
Oh BTW @vestal minnow in case you were wondering ... I'm still working on the SpatialQuery rework ... It is starting to look a bit sus though, like this ext trait:
pub(crate) trait BvhExt {
fn cast_traverse<...>(...)
fn cast_traverse_dynamic<...>(...)
fn dist_traverse<...>(...)
fn dist_traverse_dynamic<...>(...)
fn point_traverse<...>(...)
fn point_traverse_dynamic<...>(...)
}```
that doesn't look too bad
what's the difference between the _dynamic and non-dynamic versions?
The non-dynamic ones just call dynamic and construct some stuff to not clutter up the calls
right makes sense
The dynamic ones allow you to early-exit, while the non-dynamic ones just keep traversing the whole BVH to get the best value
Dynamic is also necessary if you want multiple results or like the _callback versions
if I were to alter the transform to teleport... when in the frame would be best?
After FixedUpdate, before the propagation in PostUpdate, but it also depends a lot on your other game logic
Is there even a good example to test spatial query stuff? π€
Not a good one, the only one dedicated to spatial queries is probably the ray_caster example and that's very basic
some other examples also use shape casts but only as a side thing (like ground detection for character controllers)
@cinder summit I made a smol PR for handling entity disabling
https://github.com/Jondolf/avian/pull/694
There might be some other edge cases I'm missing in terms of hierarchies or something π€
Does this work fine for the case where both Disabled and ColliderDisabled get removed at once?
why would you have both
I guess the AABB interval thing should be changed to remove duplicates
Hmmm, I just realized that AnyCollider isn't actually a valid input for shape casting, since the thing you cast might not be your collider type at all (like with the VoxelCollider example we probably don't want to be casting chunks against chunks)
Here's an example that just spawns a ton of (custom) colliders in a grid and moves them around randomly. Could be modified for stress testing BVH updates or various spatial queries (might want to disable the BroadPhasePlugin in that case)
I had it lying around on a branch with BVH broad phase experiments from a while back, I just updated it now and removed some stuff
it's based on one of the Box2D stress tests for dynamic BVHs
it uses the CircleCollider from the custom collider example just so that it doesn't use Parry, but that can be changed to something else
Hmm this needs more testing, but I might have a potential fix to the interpolation problem? π€
test without moving the camera (the cyan object gets teleported backwards by just changing its Transform)
and with the camera following the object (notice no stutters)
Basically: If the transform is modified outside the fixed time step (e.g. in Update), compute the difference between the current interpolated transform and new Transform, and add this difference to the start and end states of the interpolation
I believe this doesn't truly teleport, i.e. the transform at the end won't necessarily match the target Transform it was set to (since it finishes the old interpolation, just with a different current interpolated transform), but people can turn this into an actual teleport by setting the easing states to None first. For that, we could expose something like a ResetInterpolation command
I believe this also makes bevy_transform_interpolation Just Workβ’ with big_space, for the most part π
I'm getting perfectly smooth grid cell transitions rn
I'm trying to have a gliding rigid body object on a trimesh static collider floor move smoothly, but I keep getting the object jumping whenever it hits an edge on floor. It seems as if the rigib body capsule is penetrating the floor just by a little, enough to make it jump up when hitting those edges.
Is there any hack to workaround something like this?
You could try if using TrimeshFlags::FIX_INTERNAL_EDGES when creating the trimesh helps, either through Collider::trimesh_from_mesh_with_config or ColliderConstructor::TrimeshFromMeshWithConfig
This won't help for edges between separate trimeshes though
Yes, I tried with:
TrimeshFlags::DELETE_BAD_TOPOLOGY_TRIANGLES
| TrimeshFlags::FIX_INTERNAL_EDGES
| TrimeshFlags::MERGE_DUPLICATE_VERTICES,
))
Are you sure the bumps are between edges of triangles that belong to the same mesh, or between separate meshes? Your'e using ColliderConstructorHierarchy which implies that you're maybe spawning a scene with multiple meshes
Adding a small CollisionMargin (adds some thickness) around the capsule and/or terrain might help a bit in some cases, though it's not really a proper fix
That's the mesh
Let me try with CollisionMargin
Not really working I'm afraid π
Mm I'm not getting any bumps in my test scene with trimeshes if I'm using TrimeshFlags::FIX_INTERNAL_EDGES
What kind of collider are you using for the player?
capsule
thanks, I'll try with that
Thanks.
@earnest iris Just moving around and rolling a ball on the ground, I'm not really seeing any bumps π€
(this is the character controller from the dynamic_character_3d example)
Would you mind sharing the test code with me? π this looks great!
Amazing! Thanks, a million β€οΈβπ₯
@little maple When you have time, could you try this with the new smooth-teleports branch of Avian? Just changing Transform directly to teleport the entity and see if the stuttering is gone or if there are any new problems
I made this PR for bevy_transform_interpolation, which that branch uses
In my testing, it seems like it should fix all the problems with mutably accessing Transform breaking interpolation, when e.g. y-sorting or using big_space
FYI @glacial nebula, this ^ seems to make bevy_transform_interpolation Just Workβ’ with big_space, assuming my test case isn't faulty
That PR (ignore the stutter at the start, I switched window focus)
What it was like before
(here the grid cells are small just to make it switch between them often)
ah, might take some time.. I'm still on 0.15 π
I'll take a look when I get a chance and see if I can cherry-pick that though
@vestal minnow i'm so glad this "just works", it's awesome
@vestal minnow any idea what's up with these guys?
- The plates fall through the floor
- The mugs jitter
- The books breakdance
The prop colliders and the floor are all convex hulls
Is there any obvious setting I could tweak?
Did you try f64
whew, I get a ton of ambiguity errors then
I guess some of my dependencies activate f32
Hey I'm having trouble understanding contact manifolds. I'd appreciate some insight!
My problem is that given two intersecting colliders A and B (not enclosed), I want to find the best position inside collider A to place collider B, such that A fully contains B.
So something like this:
I've been researching, and I think I need to get the normals from contact manifolds. It makes sense. But I'm not sure what the contact manifolds are exactly.
For example, in the diagram above, do I get 2 manifolds with two different normals...? What about this...?
If so, what about this case?
i have a dumb question
i have been 'teleporting' my character by settings its Transform
but this no longer seems to be reliably working !? since i added TransformInterpolation
sooo am i doing something wrong ?
Are you running into this maybe? https://github.com/Jondolf/bevy_transform_interpolation/pull/10
@vestal minnow @gentle cave i'm kind of stuck using both avian and ecs_ldtk together. i have the minimalest possible setup for both you can think of. here's what i've investigated
Oh it stopped . Nvm i think i was doing something else incorrect
so far this works but it's super hacky
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn((
Camera2d,
Projection::Orthographic(OrthographicProjection {
scale: 0.5,
..OrthographicProjection::default_2d()
}),
Transform::from_xyz(1280.0 / 4.0, 720.0 / 4.0, 0.0),
));
commands.spawn(LdtkWorldBundle {
ldtk_handle: asset_server.load("tile-based-game.ldtk").into(),
..Default::default()
});
}
fn init_added_player(
mut commands: Commands,
assets: Res<Assets<Image>>,
player: Single<(Entity, &Sprite, &Transform), Added<Player>>,
) {
let (player_entity, player_sprite, sprite_transform) = (player.0, player.1, player.2);
let player_size = Vec2::new(1.0, 1.0);
//assets.get(&player_sprite.image).unwrap().size_f32() * sprite_transform.scale.truncate();
commands.entity(player_entity).insert((
RigidBody::Dynamic,
LockedAxes::ROTATION_LOCKED,
Restitution::ZERO.with_combine_rule(CoefficientCombine::Min),
Transform::from_scale(Vec3::new(0.5, 0.5, 0.5)).with_translation(Vec3::new(
sprite_transform.translation.x,
sprite_transform.translation.y,
10.0,
)),
Collider::rectangle(player_size.x, player_size.y),
));
//
//commands.spawn((
// Player,
//));
}
I can also send the revy details which show every component of the entity at each time step
stuck on what, i had basically no problems switching over
actually nvm it was still xpbd back then, so something might've changed
i've figured it out
it's hacky
but you have to manually set a high z index on the Transform for the player
when you setup it as an avian physics object
i had both player and enemies spawned in LDTK itself
i just took the platformer example and adapted it to xpbd and it worked
idk what xpbd is
old avian
it switched from position to velocity-based solver, i could see new bugs appearing but i don't see how that's relevant here xD
lol well you have the results of my investigation
make of them what you will
i can reproduce everything htere
like what was even the problem, layers being backwards?
you're spawning camera at z 0.0, so that's not surprising... but i don't understand how moving player fixed that
A contact manifold is basically just a contact surface. If you had the two boxes colliding, the contact manifold would be the area where they touch, and it can have one or more contact points. For example in this case there are two points (the red line just indicates the contact surface where they touch)
Here's a more interactive example of what the manifolds are for this box-box case
the green arrow is the outward normal on each object's surface
For all convex shapes, there is only one contact manifold at a time, but concave shapes and composite shapes (trimeshes, heightfields, polylines, compound shapes) can have several
The jittering and breakdancing sounds like it could be either an angular inertia problem or a contact accuracy problem in Parry
In the past I've noticed that contacts between some shapes are much more prone to instability than others at small scales (see #1124043933886976171 message)
Any chance of backporting this to 0.15 or should I update my stuff to 0.16 in preparation for the official release?
I won't make a new release for 0.15, but I could maybe set up some branch that has it cherry-picked
so you could then target that branch until you switch to 0.16
Made a PR to fix some of the egregious memory usage problems and overhead of the SpatialQueryPipeline
https://github.com/Jondolf/avian/pull/696
Need to test a bit more to verify that I didn't break anything, but it seems fine :P
Oh no, a merge conflict π
I assume your stuff is pretty different anyway though? Since it doesn't even use Parry for the BVH
pub struct SpatialQueryPipeline {
pub(crate) bvh: Bvh2,
pub(crate) colliders: HashMap<u32, SpatialQueryItem>,
}
``````rust
struct SpatialQueryItem {
generation: u32,
layers: CollisionLayers,
position: Position,
rotation: Rotation,
aabb: ColliderAabb,
}
I guess I can just adopt this proxies approach though, that might even allow for resorting so I can get rid of the extra indirection, though I'm not sure if that makes sense to do performance wise
The array lookup would also be faster than a hashmap lookup, though I guess the lookups don't happen that often if the BVH is culling effectively
Yeah whatever works best in terms of perf is fine, for the current spatial query pipeline the allocations and overhead were insanely large with the old approach lol
I'm not sure why I did it like that originally, I must have had some weird reason 
No both of us just didn't understand BVHs 
I even remember helping with the generations thing but the implementation makes no sense
Also as for that TODO
I just changed my impl to get rid of position/rotation
It's just Entity, CollisionLayers, Aabb now
I need to query some C: QueryCollider anyway π
Yeah that's pretty ideal, assuming the cost of ECS queries isn't a problem
Shoudln't be an issue considering how much the BVH can skip
Box2D also does a thing where it stores category bits (our CollisionLayers::memberships) in internal BVH nodes, which lets it early-out for incompatible layers earlier. That would probably require changes to OBVHS itself though
also I have to say that from a dev POV, the physics diagnostics stuff is probably one of the best features I ever added to Avian π it makes it so much easier and more motivating to optimize things and detect bottlenecks
It does seem pretty neat yea
That'd be mint thanks!
I started down this path last night and did run into
the package
bevy_transform_interpolationdepends onbevy, with features:critical-sectionbutbevydoes not have these features.
and I stopped there because I was watching a movie and it started getting crazy
I'll try to set up a 0.15 branch with that later today
I think I just need to remove the no-std stuff in my fork of bevy_transform_interpolation
ah, there's a bit more... I don't know, I probably should be working toward using 0.16 anyway
Ahh that makes a lot more sense, thank you!
@chilly cradle @little maple There's now a bevy-0.15-smooth-teleports branch for bevy_transform_interpolation
what could make 2 rigidbodies move differently, when rigidbody A is moved by a joint and I copy the velocity over to rigidbody B.
Rigid bodies are moved multiple times per timestep in the substepping loop. You'd need to copy the velocity right before position integration within the substepping loop to get similar behavior
similar behavior means, it's not a good way to do it? :P I basically just wanna "group" a bunch of rigidbodies, and mirror the movement of a placeholder to all of them.
If you want the other entities to replicate the movement of one body exactly, do those other bodies need to be (dynamic) rigid bodies, or could they just be normal entities whose transforms you update manually to mirror that one body?
they are part of a simulation, but I set them to kinematic for the time they are moved
so I tried setting the transform, but that desyncs, so it would need a more complex approach of removing them completly from sim and then back?
Curious how would in avian avoid camera 3d clipping into collidables?
I haven't implemented a camera like that but I think typically you'd do ray casts or shape casts around the camera to see where it can and can't move and how far it is from the environment
what happens if you put a collider on the camera according to the near plane? :p
It follows player around so it becomes very jittery when colldiing
I don't think it should cause any visible desync for a kinematic body, assuming the velocity is zero and the transforms are up-to-date and set correctly π€
hm okey I'll try that again.. I think I tried with parenting, did that cause the desync?
Ehhh maybe, I generally wouldn't nest rigid bodies in a hierarchy, the behavior there isn't very well defined or tested atm
so set the translation according to.. what exactly? I'd love there to be delta movement accessible
I guess that when such ray collision occurs, I must move it in the nroaml direction given by the raycast correct/.
I think you'd rather do the ray cast before the camera is moved, and limit the movement such that the camera doesn't move past the hit distance returned by the ray. So rather than moving the camera back along the normal, you'd prevent it from intersecting things to begin with
I am gonna give it a shot, I think that would be a cool example to add to avian and panorbit camera π
Or I think a simple approach is to just cast a small sphere (or ray) from the character to the target location of the camera. If the sphere intersects something, (smoothly) move the camera to the closest point of intersection
There are likely a lot of edge cases that you might need to handle though, depending on how you want it to feel
https://www.reddit.com/r/godot/comments/1ezjnli/advanced_clipping_camera_for_my_fpstps_game/ This guy made something quite sensible, from what I can see
Like there are many ways to handle being close to a wall and rotating the camera from one side of the wall to another
I tried changing the prop colliders to primitives and keeping the floor a convex hull, but that didn't change. Interestingly, the mass seems to make quite a difference. No matter the shape, if I up the default_density in the ColliderConstructorHierarchy, the problems lessen. At density 1, everything looks as in the video. At density 10, the only artifact is jitter. At density 100, there's just a bit of jitter occasionally.
Dunno if that's relevant information, but at least it's a workaround for now
I remember there used to be an issue laying around that involved small shapes colliding with big triangles, maybe that's related?
Ah, it's your own issue π
https://github.com/Jondolf/avian/issues/159
This is most likely an issue in Parry. See dimforge/parry#166.
guys, what do you use for 3rd person player?
I tried to use this example
https://github.com/Jondolf/avian/tree/main/crates/avian3d/examples/kinematic_character_3d
All works except kinematic_controller_collisions, it has an error on add_systems and then 9 errors inside the system
In these examples, the ground is a 20,000 x 20,000 convex hull, but even 500 x 500 has issues.
oh nvm my triangles are like 20 m big
Use Tnua
with avian, right?
Do not use tnua if multiplayer
what to use?
A deterministic implementation, unfortunately tnua went a little too deep on the dyn types. Making serialization and validation quite a nuisance
If singleplay he is perfect tho
I just need collider with terrain so as not to fall through the ground . All other (gravitation, movement velocity etc) works already
Hmm I have no idea how to help you with that. HAHAHA, i dont use kinematic characters
what do you use for character/player ? Or you dont use characters at all π
Is there anything special I need to do to add this to my project or should cargo add --path "../local_path_with_branch_checked_out" do it?
I'm adding it that way to my crate and it's exploding when I change grid cells π’
hmm how do you deal with X/Z rotations what should not be on player?
LockedAxes::new().lock_rotation_z() ?
hm, switched to Dynamic body, it moves not too smooth ) what I need to know about Dynamic body for player model?
Two option make it floati
OR disable floor friction
what do you mean?
Make it floati means make it float, either turning off gravity or making a spring dampener in it is lower bounds
Usually the later should be the go to
In the end friendorino, a controller is an expression of your game, lots of variables and things you may wanna change
Grid cells as in big_space grid cells?
Yeah correct
Are you using Avian?
Yes, avian3d
Avian itself doesn't support big_space (yet), that branch should just make bevy_transform_interpolation work with it
Oh I've misunderstood then. I thought it was an underlying package of avian
That would then enable support when using this branch, my mistake
Yeah Avian does use bevy_transform_interpolation, but that's only for interpolation support, doesn't make it work with big_space
are collision events sent on the frame where the collision ends?
I notice Contacts has is_colliding_current/past_frame
but I can't seem to catch the end of the collision with Collision, though CollisionEnded works
What is the diff between cast_ray and cast_ray_predicate?
"predicate: A function called on each entity hit by the ray. The ray keeps travelling until the predicate returns true."
ah did not see that argument doc
so, I have good news and bad news π
the good news is that I did end up getting it to behave smooth enough for my purposes without using the smooth-teleports branch (I'm using the avian branch contact-graph)
the bad news is... if I go to my avian fork and change it to use the smooth-teleports branch of bevy_transform_interpolation, it does this
I know I'm altering the translation and the rotation and it seems to get stuck spinning there when I'm trying to change the rotation (to make the vehicle point forward/be upright)
I feel like I'm taking crazy pills - I can't get my sensors to detect collisions
commands.spawn((
Transform::from_xyz(0.0, 0.0, 100.0),
Sprite { image: asset_server.load("player.png"), ..Default::default() },
RigidBody::Kinematic,
KinematicCharacter,
Collider::circle(12.0),
DesiredMove::default(),
ApplyDesiredMove { max_speed: 100.0 },
Player,
));
commands.spawn((
Transform::from_xyz(200.0, y as f32 * 32.0, 100.0),
LinearVelocity(Vec2::new(-60.0, 0.0)),
Sprite::from_image(asset_server.load("fireball.png")),
Collider::circle(8.0),
RigidBody::Kinematic,
Sensor,
Projectile,
DeleteProjectileOnCollision,
));
fn handle_projectile_collisions(
mut collisions: EventReader<Collision>,
projectiles: Query<(), With<Projectile>>,
mut commands: Commands,
) {
for collision in collisions.read() {
let is_projectile_1 = projectiles.contains(collision.0.entity1);
let is_projectile_2 = projectiles.contains(collision.0.entity2);
dbg!(collision);
//... some other stuff
}
}
And I definitely have the physics plugin added
I think it's this... you're checking that both entities that are colliding are projectiles
well
Yeah but I don't use that fact until after the dbg print
hmm
Like I'm not getting any printing
Hence why I'm going crazy haha
This is avian2d btw
have you tried turning on the avian debug visuals?
Yup, they seem to show the colliders in the right spot!
The fireballs have colliders seemingly
when's the system run?
.add_systems(
PhysicsSchedule,
handle_projectile_collisions.in_set(PhysicsStepSet::Last),
)
Possibly the wrong spot, but even if it was, I would still expect events to be handled for the next frame
WAIT WHAT THE HECK
This system isn't even running???
i am so dumb
i didn't add the dang plugin
arghhhhhhhh
that's what I get for splitting up things into separate crates so early
Thank you both! π π π
Oh that's a little awkward - I'd like to delete my projectile if it hits something this physics frame, but deleting the object in PhysicsStepSet::Last causes a panic in avian...
Oh wait perhaps not, it's just my code again
Bleh
How can I stop rotation/angular motion (2d) when a dynamic body collides with a static body? I'm using TranslationExtrapolation instead of TransformExtrapoliation, and I even added added NoRotationEasing but it continues to happen. I only want avian to handle the linear translation part of things.
RigidBody::Dynamic,
Collider::circle(16.0),
TranslationExtrapolation,
NoRotationEasing,
LinearDamping(2.75),
edit -- I should also add that I'm only updating LinearVelocity in the movement system function.
yessss ROTATION_LOCKED is what I was searching the docs for. Thanks.
I am getting weird issues loading assets with blenvy, which result in Position and ColliderParent being wrong
Heirarchy is wall (Rigidbody::Static) -> wall_segment (Rigidbody::Static) -> collider (Collider via ColliderConstructor)
I am not certain of what order components are added, but it seems like the behavior is probably a bug for avian regardless.
Note that position != global transform, and ColliderParent skips over wall_segment and goes to wall
wall_segment does indeed have Rigidbody::Static, and if I set it to dynamic and back to static everything corrects.
if I change the transform or position of wall_segment everything breaks again
it seems in this state position is synced to transform instead of global transform
Responsible for synchronizing physics components with other data, like keeping Position and Rotation in sync with Transform.
maybe this is the expected behavior?
very odd though, since it results in collider to not line up with the object
Do you happen to have negative scaling somewhere?
IIRC there might be some transform propagation issues for colliders there
I fixed my issue by just not having nested RigidBody's
I saw your comment somewhere above that that isn't well tested
cool, yeah for now I'd try to avoid nested rigid bodies where possible
for static bodies (or any rigid body really) you can just have one root body and child colliders
and to answer this, I double checked and nope, no negative scale
I am still a little confused on how the syncing of transform <-> position is supposed to work without taking into account parent transforms
Though it seems I can change the transform of wall (no longer a RigidBody), and it gets reflected in the Position of wall -> wall_segment -> collider
OH
When synchronizing changes in Position or Rotation to Transform, the engine treats nested rigid bodies as a flat structure. This means that the bodies move independently of the parents, and moving the parent will not affect the child.
I read that backward
position -> transform, yeah it makes sense for it to work that way
Yeah right now there's a lot of confusing sync logic to write the physics Position (which must be in global space) into Transform (which is in local space), but we also ideally want people to be able to just change Transform directly, so we have the inverse of that as well. But it's somewhat unclear how Transform changes should work within hierarchies for physics entities, and making it work properly gets pretty cursed
hey i have some weird dependency issue i cant get behind, basically im using avian2d with f32, but it imports parry2d and parry2d_f64 for me, so some types come from one crate, some from another
cargo.toml definition:
avian2d = { version = "0.2.1", features = ["serialize", "simd"] }
what can be done here?
have you double checked your use statements to see if everything is consistent there?
cargo tree is often very useful for figuring stuff like this out since it lets you see where a particular dependency is coming from.
it looks like the rc4 release broke the bevy-0.16 branch; is that something you'd take a PR for?
the main branch supports the latest rc
Clean-up PR for collision detection modules and re-exports
https://github.com/Jondolf/avian/pull/698
@vestal minnow Made that little code we talked about was wondering if you would like to give any opinions especially when it comes to handling the precision of the raycast distance, which becomes quite imprecise when anchored entity moves. It works fine I think
/// Check ray direct
fn avoid_wall_collisions(
mut query: Query<(&mut ThirdPersonCamera, &Transform), With<MarkerPrimaryCamera>>,
transform: Query<&Transform, Without<MarkerPrimaryCamera>>,
spatial_query: SpatialQuery,
) {
let (mut tps_camera, camera_transform) = query.single_mut();
let entity = tps_camera.anchor;
if let Ok(transform) = transform.get(entity) {
let direction = (camera_transform.translation - transform.translation).normalize_or_zero();
let dir = Dir3::new(direction).unwrap_or(Dir3::Z);
let opt_ray_data = spatial_query.cast_shape(
&Collider::sphere(0.4),
transform.translation,
Quat::IDENTITY,
dir,
&ShapeCastConfig::default().with_max_distance(6.5),
&SpatialQueryFilter::from_mask(GameLayer::Map),
);
let smoothing = 0.1;
if let Some(ray_data) = opt_ray_data {
// Means camera is probably colliding with something behind itr
if ray_data.distance <= tps_camera.radius {
let safe_distance = (ray_data.distance - 0.2).max(0.1);
if let Some(prev_pos) = tps_camera.target_radius {
tps_camera.target_radius =
Some(prev_pos * (1.0 - smoothing) + safe_distance * smoothing);
} else {
tps_camera.target_radius = Some(safe_distance);
}
} else {
tps_camera.target_radius = None;
}
} else {
tps_camera.target_radius = None;
}
}
}```
@vestal minnow i'm moving and rescaling transforms with colliders when resizing window, and while the game is paused colliders don't get updated until game is unpaused, what's the right way to update them without unpausing or stepping?
Two physics Gltf extinctions are planned this year https://github.com/eoineoineoin/glTF_Physics?tab=readme-ov-file waiting for review/ratification. Blender Gltf physics importer/exporter is also ready https://github.com/eoineoineoin/glTF_Physics_Blender_Exporter and adds additional physics panel (see screen). We can't implement Gltf physics importer in Bevy repo until Bevy has it's own physics, but maybe we can add (hacky) support to Avian when these extensions are ready (or draft in Bevy repo with Avian)?
New Gltf roadmap 2025 https://youtu.be/jeYE23Dn8r8?t=518
Plugin for Blender to enable export of rigid body info when exporting glTF files - eoineoineoin/glTF_Physics_Blender_Exporter
The Khronos Group held "3D on the Web," a special event in San Francisco on March 19th during the week of GDC 2025. The gathering united the brightest minds in glTF, WebGL, WebGPU, and the future of interactive 3D on the web.
Damn, they intend to actually move forward with glTF physics? That's pretty cool, I knew there were (multiple) designs in progress but didn't think it'd actually happen any time soon
(also cc @valid fog)
I haven't looked at the spec too closely in a while, but it'd be cool to support it in some way. It could be a separate crate or just in Avian directly, behind some feature flag