#Avian Physics
1 messages · Page 44 of 1
with normals, the .y value happens to also be the cosine of the angle between the ground and the up direction (if Y = up)
e.g. in that snippet, I validate that the normal.y is above 40.0_f32.to_radians().cos() before accepting it as a ground 🙂
where a degree of 0 would be a perfectly vertical wall and a degree of 90 would be perfectly flat ground
I could Apple the same reasoning for wall sliding that’s genius
What does "to Apple something" mean? 😄
Apply
aaah gotcha
My corrector
yep, totally!
If you replicate Quake-like air acceleration on top, congrats, you have working surf maps 🙂
Thanks you !
But kinematic are not affected by gravity, so I just need to add a downwards Vec Y of 9.3? For gravity or there is a better way?
Yeah, though usually in kinematic controllers that is only applied if not on ground 🙂
alright thanks
Also, use move_and_slide() to actually move your guy
the standard gravitational acceleration IRL is defined as about 9.81 m/s², but for games and especially a character controller, use what feels best for the game
https://en.wikipedia.org/wiki/Standard_gravity
It's usually way higher for KCCs, try 20.0
does anyone know if there is a example of despawning or know of anything we need to do. i keep getting collision crashes when i despawn elements that have colliders..
That sounds like a bug. What's the error message?
cargo/git/checkouts/avian-5a22c167119f3550/567b9f5/crates/avian3d/../../src/collision/collider/mod.rs:512:9:
assertion failed: b.min.cmple(b.max).all()
it seams like it happens most when i get down the last 1 or so in my set
as im despwaning them
that message almost always means that something became NaN
i have a system that despawns the entities 1 at a time
and as it gets down the end it crashes like that... not sure where to check for a NaN... any ideas where i could look
yeah, print all Position and Rotations
those are often affected
also the Transform
ok thanks.
here is full error also
thread 'main' (5680258) panicked at /Users/pro/.cargo/git/checkouts/avian-5a22c167119f3550/567b9f5/crates/avian3d/../../src/collision/collider/mod.rs:512:9:
assertion failed: b.min.cmple(b.max).all()
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `avian3d::collision::collider::backend::update_aabb<avian3d::collision::collider::parry::Collider>`!
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`!
2025-12-18T19:08:41.793387Z ERROR winit::platform_impl::macos::event_handler: tried to run event handler, but no handler was set
will avian be upstream to bevy ?
Probably not, at least not directly. When Bevy one day starts working on upstream physics, it may very well have great similarity with Avian, but it won't be a straight up upstream
@vestal minnow correct me here if I'm wrong
alice mentioned that bevy will eventually need physics and that avian is the best candidate so far
My view on this is that Bevy will most likely have a built-in bevy_physics crate with the general ECS interface used for physics, but no actual physics engine will be upstreamed under the Bevy org itself. Instead, you'll be able to choose any physics engine that has an integration for the ECS interface. This could be Avian, or Rapier, or bindings to Box2D or Jolt, etc.
However Bevy does probably also want to pick one of the engines as more "official" and best supported, since I think it should still have some default physics solution out of the box, especially for Bevy's own examples and demos
thanks for the answers
about that, is there any good kcc already done for avian outside of tnua ?
Tnua is not a KCC
oh
but yes, I made one 😄
You need to depend on the repo directly and patch avian for now
can i enable gravity easily or i need to implement it myself ?
It’s all builtin
that's lovely
wdym by patch avian ?
See the top line of the readme 🙂
oh so basically i need to use directly the avian git repo
And depend on bevy_ahoy = { git = … } for now
alright, the controller seems really nice
Yep, since it uses unreleased new Avian stuff
I still need to write docs, but until then minimal.rs should serve well
I'll try it and ill give you my reviews 🙂
Yea plz!!
It'll be interesting to see what exactly an "official" physics integration will look like from a governance perspective. If we look at engines like Unity (uses Box2D for 2D) and Godot (uses Jolt for 3D), they don't use an up-to-date physics engine directly, Unity actually uses a forked version of Box2D and Godot has an older version of Jolt in-tree. So they technically have full control over the physics, and could change stuff independently from the original physics engine (but e.g. Godot doesn't)
I think in Bevy's case, if we had Avian as the "official" physics solution, we could maybe have some Bevy maintainers in the Avian org 🤔
I would really like that bevy export some physics trait or something like that, and then choose the engine ourselves
so that every physcis engine as some commons thing, but also some differences
idk if it's a good vision tho
Knowing Bevy, forking Avian sounds like a no-go
Yeah I would not fork or directly upstream personally
But yes keeping the bus factor high is a good idea
I personally try to give maintainer rights very quickly to trusted people with interest juuuuust in the case something happens to me
Mainly we want Bevy to have some level of confidence and control over whatever it chooses as an "official" physics solution
(Or I become inactive for longer)
Hence why e.g. I instantly gave you and vero rights to ahoy
Agreed
And also be able to e.g. publish a critical hotfix instantly when necessary
@visual sparrow
10) Why is it that when I use the Earth gravity value, it feels like the Moon gravity instead? It's not just here, it seems it's the same in other physics engines. What am I missing?
11) I'm not sure I would, but is it even possible to override some movement parts, e.g. only describe jumps or movement acceleration my own way without forking the whole plugin?
12) What's unground_speed?
13) If you press W and A/D and turn mouse while walking or crouching (not in the air), speed may increase past speed, is it also intented?
14) Is it possible to disable repeating jumps, i.e. when a player holds Space, they only jump once and have to release it and press again to jump once more?
15) Not sure if the question is about ahoy or BEI, but how does mouse movement get calculated? E.g. previously I used Res<AccumulatedMouseMotion> and multiplied it by 0.003 (sensitivity), now I use 0.175 as sensitivity to get roughly the same results. Is it some radians/degrees conversion or something else?
16) Is jump height when crouching scaled by collider size or something like that?
yeah I've always found realistic gravity to seem super light compared to real life in every single engine I've used
- that’s because air gravity is surprisingly slow! In real life you don’t notice because your jumps are extremely low and jumping from high speeds usually is a stressful situation, changing your perception. Most KCCs that allow high jumps thus have higher-than-earth gravity 🙂
- more or less. I want to split all individual moves into systems you can order against, and then you can choose to just not bind the default jump. But I intentionally don’t want deep custom behavior because of maintainability (see design philosophy on the readme)
- that’s the Y speed at which you are considered to not be grounded, no matter what. Useful for when you’re realllllllly fast and moving i to a ramp, so you can properly fly off from it.
- ye that’s a ground strafe 🙂 it feels snappier that way.
- yep, add a
Presscondition to the binding. That’s a BEI feature, see its examples for how (or come say hi in #1297361733886677036 - uuuh BEI should use AccumulatedMouseMotion. Did you notice that there is a scaling factor on the binding already? Otherwise you're scaling it twice
- crouching reduces all speed, including jumps (same as Source)
gravity is also often a scale thing, you need to make sure object sizes match the real world if you want Earth gravity to feel accurate
Of course.
- Not sure what you mean by “air gravity”, but a feather and a hammer fall with the exactly same speed in a vacuum, because
v = v0 + gt. In the atmosphere there is air resistance that slows things down, but it must be a separate value, and per object, because it slows down every object differently. Also, my perception doesn't change when I watch a video with a falling object in real life vs. a falling object in a game, while sitting in a cozy chair at home. Btw in Obenseuer gravity feels more real, i.e. you feel the weight of the character for some reason. They must've just increased the gravity by a multiple, but still... I would like to just put the real Earth gravity value into “gravity” field and call it a day. And then use some air resistance values per object. Because I really hate to pick random numbers for stuff that's actually known. And if I need a higher-than-real-life jump, I'd rather increase CC's impulse, velocity or whatever. But, I guess, that's already the question to @vestal minnow. - Yeah, I understand how cumbersome it may be to make everything customizable. It's just that, for example, I am currently working on a calm escape room puzzle game that may or may not have stuff like jumps and crouching, but definitely doesn't need Clustertruck's movement behavior. So I can imagine not everyone wants to make the latter kind of game, and there doesn't seem to be a lot (if any) alternatives. But I also understand it may not be your intention “to provide for everybody”.
- Before I was using:
mouse: Res<AccumulatedMouseMotion>,
...
let (mut yaw, mut pitch, _) = camera.rotation.to_euler(rotation_order);
yaw -= mouse.delta.x * _MOUSE_SENSITIVITY;
pitch -= mouse.delta.y * _MOUSE_SENSITIVITY;
Now I use:
Scale::splat(MOUSE_SENSITIVITY),
Or do you mean some other value?
Probably not a big deal, just curious where the other numbers come from and why 50 times difference. The closest I can think of is 180 / π = 57.2957795.
16) Ah, yes, I forgot about that.
17) Does the KCC first penetrate objects and then gets depenetrated? Because, for example, in UE penetration only happens when something went utterly wrong. Probably also the question to @vestal minnow.
*earth gravity, damn autocorrect haha
Yeah you'll want to fork in that case, but that should be simple: fn run_kcc cleanly lists out all the steps, you can just remove whatever you don’t need. Let me know if you need help with that!
I have no clue either where that difference is coming from. Curious if you find out!
The upstream move_and_slide does
- depenetration
- movement iteration
- depenetration
- Thanks!
@visual sparrow Btw, did you know “ahoj” in Czech means both “hi” and “bye”? Well, it's derived form “ahoy”...
I did not! That’s cool 😄
does that channel ever actually provide information about things
its like a news bites thing
I don’t get the point of this conversation ?
the paper is from 2022? it is kinda a clickbait video but also idk if I would have seen it otherwise 🤷♂️
pretty much every video he does is clickbait
very cool cloths and bouncy physics in the video for reference. nothing special
Sorry, moving question there.
no worries
I'm able to create colliders for voxels using Collider::voxels(), works fantastic. I also use this crate: https://docs.rs/bevy_vox_scene/latest/bevy_vox_scene/ which allows you to load MagicaVoxel models. I was wondering if it would be possible to setup avian colliders for the spawned .vox models. I've tried using ColliderConstructorHierarchy::new(ColliderConstructor::VoxelizedTrimeshFromMesh { .. }) but it doesn't work.
Latest version docs.rs CI dependency status Bevy tracking codecov
Update: loading models with the bevy_vox plugin, combined with VoxelizedTrimeshFromMesh => it works, but it generates a large amount of colliders.
Is it possible to use apply_force_at_point somehow? It's not a public function and RigidBody is an immutable component but is there another way to apply a force at a point?
Didn't realize there was a separate Query<Forces>. Then it makes more sense.
Can't seem to get forces to work. Changing translation directly works but not using forces.
Is there an example with Forces and some visualization? Can't find any in the repo.
Ah damn PhysicsPlugins::default() 🤦♂️
Is there an example out there of a spaceship game that uses avian ?
Mine does, but you likely mean 3D :)
Hello. Yes, a 3d spaceship game. You're working on one ?
No, mine is 2D
Ok.
Is your project public, is it published somewhere ?
Awesome ! Thank you !
i'm puzzled by this. i'm also trying to do unit tests. these worked before on 0.15, i'm updating to 0.16 rn. this is the avian update that added diagnostics.
someone else in this channel (ethereumdegen) also ran into this, but for headless avian, and someone on github ran into this when testing nostd (https://github.com/avianphysics/avian/pull/703#issuecomment-2814013538).
PhysicsDiagnosticsPlugin requires a feature i don't have enabled. why are these diagnostics present w/o the feature? searching the repo, i'm having trouble figuring out what these are even for - neither gh search nor rustrover are showing any usages outside of diagnostics plugin.
i may be missing something here but i think this should be in the migration guide/elsewhere in documentation regardless
The diagnostics are present in resources like SolverDiagnostics even without the feature, but what the bevy_diagnostic and PhysicsDiagnosticsPlugin do is write these diagnostics to Bevy's built-in DiagnosticsStore.
The diagnostics themselves should have very minimal overhead, and would be kind of annoying to put behind a feature, which is why they are currently tracked regardless of enabled features; just the integration with Bevy's built-in diagnostics stuff is feature-gated
As for what the diagnostics are for, it's for profiling physics at runtime. The PhysicsDiagnosticsUiPlugin provides a built-in UI for displaying the results, but you could also build your own UI, reading the diagnostics from DiagnosticsStore or from the individual resources.
The diagnostics stuff is also covered in the 0.3 release notes
https://joonaa.dev/blog/08/avian-0-3#physics-diagnostics
Make sure you run app.finish() after initializing the app if you're writing tests
that's something you should do with Bevy in general, it's not necessarily an Avian thing
it runs finish for all plugins, which can often do some final setup stuff; in Avian's case, it's where the diagnostics resources and systems are initialized
I'm getting this error and I'm unsure what it implies, does it mean 2 static colliders are overlapping?
thread 'main' panicked at avian2d-0.4.1\src\dynamics\solver\constraint_graph.rs:173:9:
assertion failed: !is_static1 || !is_static2
based on a previous convo I found it seems that is what this error means, is there any way to get around this error if I want to allow overlapping statics?
I'm spawning the colliders with the bevy_ecs_tiled package and they seem to overlap slightly on generation
sorry yeah i went on a bit of a tangent - i meant specifically docs for the requirement of the resources
i don't think i have app.finish though, i will add
app.finish() does work without inserting resources!! thank you for that. seems like ownez got the message too so that's good
I have this worry that iterating over MessageReader<CollisionStart> and filtering just for the collisions I care about every frame would eventually become some sort of bottleneck so I just have one system that iterates and then on each iteration I check every variant of collision pairs I care about.
I'm wondering is that what everyone else does or do you all just make separate systems for each type of collision you care about and not worry about efficiency?
I use the collision observer API instead
Usually I don’t need to check anything special. For example, instead of observing player collisions and filtering trigger zones, I instead observe trigger zone collisions
Since the collision layer setup guarantees that trigger zones can only collide with the player, I don’t need check the colliding pairs at all
And if I really need to ask "is this thing we collided with a Foo?", that’s just a single if in the observer with an early return otherwise
ah, hmm, I wonder if I started doing this before the observer API existed
this might be something I don't understand about how the collisions are reported
from this example
fn on_player_stepped_on_plate(event: On<CollisionStart>, player_query: Query<&Player>) {
let pressure_plate = event.collider1;
let other_entity = event.collider2;
if player_query.contains(other_entity) {
println!("Player {other_entity} stepped on pressure plate {pressure_plate}");
}
}
is there something that causes the player to always be "collider2" or is it like... every collision has two messages where the order is one way for one message and then swapped on the other message?
the event is triggered for both entities with the observer API, with the target entity as collider1
for the message reader API, there's only one collision event per collision, so there the entity order is basically arbitrary
If you were to read collision events with a global observer (i.e. no target), you would indeed see "duplicate" events, with just the entity order swapped. But the intended approach is to only use observers for observing specific entities, and a message reader for when you need to efficiently process lots of events in batches, or need specific system ordering
ah, cool. That makes sense and addresses my concern
dang, observers are so cool
would it be worth renaming the fields to make it clearer that collider1 is the reciever of the event?
That would require using a different type for the message version of the event, since that does not have a "receiver"
true true
Hello. Am I experiencing phantom collisions or phantom friction or something else? The expected behavior is for the cubes to stay stationary because the ground has no friction, and fall to the hole once the hole is beneath them.
Context:
- The ground is a cuboid with a hole poking through it and the cubes are cubes (both made in blender).
- Friction for ground is zero for both static and dynamic with mode
Min. Cube frictions are left default. - Cubes are dynamic bodies, and ground is a kinematic body. Cubes are constructed by
ConvexHullFromMeshconstructor and the ground is constructed byTrimeshFromMesh. - I tried both manually updating the ground position, and giving it linear velocity. Both result in same kind of behavior.
- Only the ground is being moved in the demo
Possibly a weird idea: But what if the ground were two colliders, one would be a flat plane, and another would be a cylindrical hole.
The plane collider would have a collision filter that would ignore collision contacts that happen over the hole.
Only the cylindrical hole would move around, the plane collider would be still
i tried that, once the cylinder contacts they just phase through the ground, not giving that satisfying feeling of "tipping over the hole"
yeah that would not allow you to collide with the edges of the hole properly
But edges of the hole would be separately done by collision with the cylinder
Can you filter only certain contacts, or do you need to filter the whole collision?
^repro code
You can filter out individual contact points with a custom collision hook
so yeah that could work in theory
it'd be basically like my portal collision idea
Yeah, that's what I was inspired by
Basically this is a bit of a weird problem to solve because what is physically happening is not motion of rigidbodies, but the deformation of a body interacting with rigidbodies
The hole isn't moving, it's deforming the ground collider to appear in different places
At the sides of the hole these two things coincide, but at the top there is a difference
So that's why I thought of having a stationary plane + a moving hole
I think I understand what you mean, I can do that
currently the hole is not moving, it's like the whole platform (plane+hole) is moving
like an illusion
Oh I see, the problem is that you're applying the zero friction to the rigid body, but the scene spawns colliders as children, and you need to set the friction for those separately, otherwise they use the default of 0.5
there should be a thing to set friction on ColliderConstructorHierarchy IIRC
Setting friction to 0 is a workaround to mask the problem, but then your floor is slippery
nvm there isn't :/
there's with_default_layers and with_default_density but no material config
I think what you'd need to do is
commands.spawn((
Ground,
SceneRoot(asset_server.load("ground.glb#Scene0")),
RigidBody::Kinematic,
ColliderConstructorHierarchy::new(ColliderConstructor::TrimeshFromMesh),
Friction {
dynamic_coefficient: 0.0,
static_coefficient: 0.0,
combine_rule: CoefficientCombine::Min,
},
Transform::from_translation(Vec3::new(2.0, 0.0, 0.0)),
))
.observe(
|ready: On<ColliderConstructorHierarchyReady>,
mut commands: Commands,
children: Query<&Children>,
colliders: Query<(), With<Collider>>| {
let entity = ready.entity;
for child in children
.iter_descendants(entity)
.filter(|e| colliders.contains(*e))
{
commands
.entity(child)
.insert(Friction::new(0.0).with_combine_rule(CoefficientCombine::Min));
}
},
);
hmm. right. but the thing with your approach is it's hard to render the hole (and the cubes falling through it) on top of the stationary ground.
i guess i can just give cubes some linear velocity damping as fake friction so they slow down?
lemme
Oh I'm just taking about the colliders, you can keep the rendering setup you currently have
oh an invisible collider, right
Yeah
Because your plane is moving at subrelativistic speeds, it makes no difference to the renderer (not like bevy_render would support relativistic rendering anyway), but it does make a difference to the collision physics
so you can use a different approach for each problem
(Yes I approach game design using a physics degree sometimes a little too much)
they're still tweaking, lemme try @novel umbra's approach first before stealing more of your time. that's a nice info I learned though, definitely a hard to catch bug (for me)
Hello, i have a question, i'm spawning a collider and immediately cast_ray from its center to a direction to get a surface point (using solid: false) but this not works because i'm trying to do both in the same tick, is there a easy way to do it on seperate ticks ?
incoming bevy_render feature request
The renderer is the least of my worries here
you would need to completely re-architect the scheduling and simulation together with a completely new transform system
this works, but you have to wake the body once you update the CollisionLayer 👍
What's your code now? (out of curiosity)
I'm so happy that this is done lol 🥳
needs cleanup but here's the current state of it
Hi! Question about debug mode performance:
I have 24 colliders parented to animated bones for hitboxes. I'm seeing very different debug performance between shape types:
- Capsules/Spheres: Significant frame drops in debug (drops to ~10 FPS)
- Cuboids: No performance issues in debug
- All shapes: Perfect in --release mode
All are sensors. Is there a reason capsules are so much more expensive than cuboids in debug builds? I'm guessing it's related to AABB computation complexity, but wanted to understand if this is expected behavior.
Thanks!
To show what I mean, here's a minimal reproduction:
- with capsules: ~70 FPS on my machine
- with cuboids: capped at 120FPS
- in release mode: both capped at 120FPS
Did you forget to enable optimizations for dependencies?
^ that config is:
# Enable a small amount of optimization in the dev profile.
[profile.dev]
opt-level = 1
# Enable a large amount of optimization in the dev profile for dependencies.
[profile.dev.package."*"]
opt-level = 3
Haaa, found the issue! My config did have the optimizations enabled, but because I'm using a workspace, it was being ignored. Adding opt-level to the workspace Cargo.toml solved it. It works flawlessly now. Thank you both! ❤️
I know im probably jumping the gun quite a bit here, but is there a working build for the 0.18-rc?
Wanting to try out some of the new features
ah i saw that but wasnt sure if that was the right build, cheers
When is ContactPoint.normal_speed updated and/or what update is its value expected to be from?
Consider a world with 2 single-collider bodies: a static body ground and a non-sleeping dynamic body player. player is currently resting on ground, pushed onto it by built-in Gravity.
A one-off linear acceleration is applied in PreUpdate to player away from the contact normal. This will eventually separate them until player falls back down.
Until player falls back down, I'm expecting not to see touching contacts with non-negative .normal_speed in FixedPostUpdate .after(PhysicsSystems::Last).
This isn't the case though: I see one on ~the next frame.
If I calculate the normal speed myself, it also doesn't match the contact.
let relative_velocity =
rb2.velocity_at_point(point.anchor2) - rb1.velocity_at_point(point.anchor1);
let calculated_normal_speed = relative_velocity.dot(manifold.normal);
While contact.normal_speed is 0.0, calculated_normal_speed is e.g. 6.0967197.
Context:
I implement omni-directional jumping by reading from Collisions in Update and storing the last "best surface". This is retained briefly for coyote time (a grace window after you leave the surface) and used when a jump input is observed.
To prevent jumping again within the coyote time window, jumping clears the last surface. This doesn't work because the same contact is detected as a valid surface immediately afterwards.
- (PreUpdate) Jump input observer
- ForcesItem::apply_linear_acceleration_at_point
- Clear last surface
- (FixedPostUpdate, .after(PhysicsSystems::Last)) Set last surface
(specifically, the contact with the greatest penetration has normal_speed=0.0, normal_impulse=0, penetration=0.00002720952, flags=ContactPairFlags(81)) - -- next frame --
- (PreUpdate) Jump input observer (can jump again, there is a valid last surface)
Are child entities supposed to get their transforms updated when parent is a rigidbody? I attached a child to an entity expecting it to update automatically so that it appears "attached" but it doesn't work for me, so wondering if it's supposed to and I messed something up, or if I need to do something else. Child is not a physics object (only has Transform) but parent is.
Ah, just realized that maybe that hierarchical transforms are not enabled in the DefaultPlugins?
says in the doc, normal speed is before that frame's collision sim
*fixed frame
should be
Hello, im trying to use a shape cast for ground detection but it uh. it trips on my player no matter how i set up collision layers. do shape casts even follow them?
yup, shapecast should hit anything that has at least 1 matching layer, you can also just exclude player entity in case you're making something reusable by enemies
does it include default into everything derived from an enum?
cause i quadruple checked the layer masks
i'm not using an enum so idk 😅
how does raycast behave?
exactly the s ame
// player rigidbody
CollisionLayers::new(GCL::Player, GCL::Terrain)
// sensor shapecast/raycast
CollisionLayers::new(GCL::Sensors, GCL::Terrain)
// terrain
CollisionLayers::new(GCL::Terrain, [GCL::Player, GCL::Sensors])
and filter includes just the terrain?
yep
those are copy pasted
well i shortened the name of the enum to GCL but you get the picture
i mean ray/shapecast filter, not collisionlayers
it has a filter
set to only GCL::Terrain?
no i didnt touch those
then it's hitting everything iirc
i expected they would use the same component as colliders
nope
there might be cases where you want completely different behaviors
e.g. detect you're above water, but don't collide with it
in that case id just make a child
doesn't make sense considering how common it is
one being a component and another being a field is pretty weird i think
although them being different types is handy, excluding specific entities is nice
ig the point is to allow you to have a lot of casts from an entity without making a bunch of children, which is fair
i think that would warrant a mention in the documentation though
wow it works
thata gizmo is SO GOOD
also my rigidbody is gone
@sleek thicket thank you
how would I interpret the values of ColliderDensity? like what's a typical value of Oak Wood per-se? Quick search says: with American White Oak around 770 kg/m³ so should that be 770.0 in the f32?
cool! good to know, thank you
distances are assumed to be meters by default in bevy_render, gravity, and tolerances
Bevy 0.18 leaked into my 0.17 version of Avian, breaking me
hmm, updating seemed to make it go away, knock on wood
It's odd that pinning to a specific rev of Avian caused a 0.18 leak though
I do have to say that Avian gives me the most dependency problems of anything in Bevy by far
It's better than Rapier was though 🙂
I think the biggest headache is the mix of api breakage and bevy compatibility in a single release. From a migration perspective as a avian user I would prefer a release that changes almost nothing but the bevy dependency and then separately a cycle of avians own api changing
It's also the fact that Avian consists of so many repos. bevy_heavy broke me, as did bevy_transform_interpolation
It might be easier if things like bevy_heavy that are pretty much just part of Avian were part of the Avian repo
we could fairly easily do the opposite, where we have an Avian API update and then a separate Bevy update on top, but doing Bevy update first would mean that we need to migrate Avian to each Bevy version twice, once for "old Avian" and once for "new Avian"
this upcoming release is currently very light on breaking changes (and new stuff in general), although my current BVH work might result in some minor breakage, we'll see
so far we only really have move-and-slide as a new thing for 0.5
I'm hoping to get at least the broad phase (and spatial query?) rework in too, and possibly the joint motor PR if the author has time to finish it
definitely a lighter release compared to the previous one though
Is the author here ? This would be an awesome addition
Not sure, I don't know their Discord handle
do you use egui at all? I find avian a piece of cake compared to egui and crates using it
egui is a pain point too.
I do think some pain is expected using a 0.x engine 🤷♂️
what does this mean? 2026-01-01T10:21:39.825090Z WARN avian3d::dynamics::solver::islands:😴 Tried to wake body 828v2 that does not exist
2026-01-01T10:21:39.825090Z WARN avian3d::dynamics::solver::islands::sleeping: Tried to wake body 828v2 that does not exist
this what I change form avian 0.3 to 0,4 to get this warning
any help?
Can you show all the components that your entity has ?
big chunk
Mesh3d(prim.mesh.clone()),
MeshMaterial3d(material_handle.clone()),
Transform::from_translation(transform.translation()),
Visibility::default(),
RigidBody::Dynamic,
collider,
Fragment{
life_time: Timer::from_seconds(3.0, TimerMode::Once)
},
CollisionLayers::new(GameLayer::Objects,
[GameLayer::Ground, GameLayer::Building]),
ColliderDensity(1.5),
LinearDamping(0.5),
AngularDamping(2.0),
ConstantLinearAcceleration::default()
));```
I create a physics fragment with a force from inside to outsite
in order to make a explosion the fragments it works with me by using ExternalImpulse in 0.3 avian3d
but the remove it in avian3d 0.4 😄
I try LinearVelocity but also I get the same warn
does is the same render::mesh::MeshAabb = camera::primitives::MeshAabb?
LinearVelocity works but I multi the stength of explosion by 5 to see something on screen
If it was an impulse before it makes sense, they do not share the same units iirc and represent different things
this is the system
supposed to use the Forces querydata
yeah they were I was just being dumb and querying Transform instead of GlobalTransform
quick question, why are overlapping statics considered an error?
it's not "overlapping statics", it's "edge in the contact graph between static bodies"
the graph shouldn't have any edges like that, because it doesn't do static-static collision checking
When I add Position, should it be in pixels or translate it to meters and some rate somewhere?..
Depends on whatever scale you're using for your world, if your object sizes are defined in pixels then positions should also be in pixels, yeah
SI units (meters, kilograms, seconds...) will typically give the best results, so some 2D games use those for objects, but scale the viewport to the desired pixels-per-meter scale. For some games it might be easier to instead just use pixels for object positions and sizes though, which is fine, but it's recommended to set the PhysicsLengthUnit for better stability in that case (see its docs)
A units-per-meter scaling factor that adjusts the engine’s internal properties to the scale of the world.
From a user POV it won't actually scale any inputs or outputs, but it scales some internal thresholds and tolerances that are normally tuned to work best with SI units
Thanks.
Hello, I have a 2d ball bouncing off a rectangle collider, but for some reason the bounce angle is incosistent, sometimes coming back towards where it comes from.
I thought it was the angular velocity so I locked the axes but it still behaves weirdly.
Any ideas ?
is it hitting a corner (even internal)?
I'm not sure what you mean exactly so here is a video
I don't understand the difference 🙁
What does that mean?
can anyone help figure out the weird bounce angles ?
the angle at which the ball bounces looks wrong
especially at 0:09
it comes in at an angle and bounces off almost perfectly perpendicular to the wall
hey all, is there any way to disable physics sleeping easily? trying to use avian with GGRS and getting rollback to work with sleeping looks like a huge pain
I could just add the plugins manually but I would prefer to configure if there was an option
is there something to be aware of if I take an entity with a rigidbody and use .clone_and_spawn() to make a copy of it somewhere else? It's like the cloned one's rigid body doesn't collide with anything
possibly physics island stuff
the angle on certain bounces is wrong like vero remarked
what cursor ?
that's the player, there shouldn't be any collision between the two, and once they are apart it should not result in a modified bounce anyway
it is despawned and spawned
this is how it should bounce in my head, though maybe the angle in avian is wrong because of how the contact between the two is computed, I'll have to explore that
The player can redirect the ball if it's close enough if I click
but it shouldn't influence bounces on the walls
does that factor in rotation?
if you mean angular velocity, I locked the rotation axis
if you mean the sudden change in the ball's direction it is me hitting the ball, unless I misunderstood
I've made a shorter video, it is a bit subtle but basically the angle is too shallow
do you know if there's something that resets or recalculates the island stuff? I thought there was some observer that fires when a rigidbody is made or something 🤔
ok nvm i see what you mean @golden python
I tried sweptCCD but it didn't help
actually, I think I fixed it by just inserting a rigidboy::dynamic
it looks as if it reflected force but in the flipped direction, cancelling it out
does it keep happening only at sharp angles?
it's mostly sharper angles yeah but it can get egregious even on larger
that's still sharp angles, how often does it happen when it's more than 90 degrees?
I don't think it happens on those angles
i guess jondolf accidentally flipped a sign somewhere
I'm not sure if he would mind being pinged
I'm sure @vestal minnow won't mind 😉
does it have friction?
if yes, you could try Friction::new(0.0).with_combine_rule(CoefficientCombine::Min)
on the ball
Seems like that was it, thanks Mr jondolf
Yeah I'm not entirely sure why it's inconsistent like that 🤔 It's expected that friction would change the trajectory a bit and dissipate some energy, but that seems extreme
although locking axes is also inherently kind of non-physical
seems like the high velocity could do that
Hello, is there a way to have a rigidbody act like a sensor with certain layers, but collide normally with other layers ?
clone the collider into an identity-transform'd child, then make that a sensor
Is this plugin designed to run in Update or FixedUpdate? My first instinct was to run the systems that apply forces to entities on a fixed timestep, for determinism/stability, but it seems like I've introduced a lot of jitter.
Ah nevermind, I found the interpolation feature 🙂
FixedUpdate
can someone help me understand?
I can't tell exactly what you're asking, but I think what they were saying is that the physics engine shouldn't waste time calculating collisions between static bodies because they're not moving so it doesn't really matter.
the issue is that it throws an error
when they collide? (idk what the difference between that and overlapping is)
if it notices it's done calculations for a static-static pair, it throws an error because that shouldn't have happened
normally overlapping statics just don't show up on the graph
I assume my error is caused by overlapping colliders being changed from nothing to RigidBody::Static then?
not having a rigidbody should act the same as having a static rigidbody
then how does this error usually occur?
changing a dynamic body to static, i assume
Is there any way to make all the faces of a trimesh collider single-sided? This would be a single large trimesh that has the static collision for a level; many unrelated triangles in different places, not a single manifold shape.
I noticed that parry TriMesh has is_backface(FeatureId), so my first thought was to prevent contacts based on that in filter_pairs, but that only has the body entity IDs. Maybe it could be done by immediately dropping all those contacts with modify_pairs instead, assuming I can query and downcast to the actual TriMeshes.
I looked a bit at TriMeshFlags::ORIENTED, but it seems that's mainly for point manifold containership tests?
there was an example for a one-way collider, it might be for 2d but still worth taking a look
I use raycasting to implement a basic grappling hook. Could that also be used to have some kind of "flashlight" (in front of the player) that scans anything with a collider illuminated by the flashlight ?
With shapecasting ?
not a conical one
A ShapeCaster with a Collider::cone wouldn't work ?
what would make the shapecast cone shaped ?
😇
The docs say: "The shape being cast represented as a Collider."
Well, its supposed to sweep the shape across from start to end so im not sure if a cone is much different than say a sphere, I guess if you point it forward maybe? Never tried it
Is this for the grappling hook or something else?
If ur trying to do something like a shotgun its probably better to just do several line traces
In a cone spread
i'd also like to know if there's a better way though
you can create a biig cone and check its intersections
it'd let you see through the walls though
yeah you still need to validate with a ray after an intersection
in my case, I create a trimesh because I don't literally want a cone for sightlines, as that implies that the vision into the corners is further than the vision ahead
and doing ray shotgun for each enemy in a stealth game doesn't sound like a good idea,
and validating with a ray would only point wherever you tell it to, most of your body could be sticking out ._.
well there's a few options 😄
for a shotgun with spread, the actual shots should be individual rays anyways IMO
the cone is just for "can I see the target"
then you raycast for the actual shot, offset by the spread
that gives you the exact location you hit
for seeing bits of the body sticking out, I've seen games do multiple raycasts
in that case a dot check would be just as good and probably be less of a performance hit than colliders 🤔
makes almost no difference perf-wise
having a collider means you can nicely visualize it though
(for debugging)
you already did a benchmark?
yeah
nothing scientific
just some simple numbers eyeballing to make sure it's still in the same order of magnitude
relative to my frame budget
that's the kind of stuff i was wondering about for years but never bothered to do a bench 🫠 it would make a good video
depends on how many enemies you expect to have ofc
I will at most have like 20 enemies aware of you
with each having staggered AI ticks, i.e. spreading their updates across different frames so there are no dips
If you instead have 2000 enemies and they need very frequent updates, story looks different
(and that's a silly number already, in practice it will be at most 3 for most situations, 20 is just an upper plausible limit if you decide to fuck around)
I'll at some point for sure do a video about Thief-flavored AI
learned a ton from that codebase
i think in a stealth game where you focus on your own cover instead of enemies looking/listening, it would be pretty cool to have a small army of enemies all around you,
probably just hiding in plain sight like assassins creed or hitman
but either way, even though for the gameplay it might not matter that much, it really breaks immersion when all of your limbs are sticking out of the bush just after enemies were alerted, and they just don't notice that
depends on first vs third person too!
in first person you can get very sloppy with your checks
one neat trick I learned: sample your first person visibility from the feet
that's what players check to see if they're in the dark
why not multiple points
i kinda understand that it's not fun to hide without seeing what's going on, but this is what i imagine guards seeing every time they say "must have been a rat" while i'm looking at them straight in the face
I think it is possible to determine TOI (time of impact) by repeatedly extending the collider instead of moving it with iterative shapecasting, but it won't be much different than intersecting with a cone and sorting results by distance.
If you want your scans to be occluded by walls, you can render the scene with simplified geometry and include objects IDs into vertex attributes, this way you will get kind of segmentation image, where each pixel contains ID of its object.
Iterative shapecasting, sweet. So right now i have a shapecaster with a cone collider but the cone is not in the right position, the flat base is on the character's side, it should be the other way around, haven't seen how to rotate a collider yet.
haven't seen how to rotate a collider yet
Collider::compound or collider as child entity
I believe the shape cast function takes in a rotation
Apart from Jolt implementation there is Unity https://www.youtube.com/watch?v=KKXZ3860o7w
Related gh https://github.com/dbrizov/NaughtyWaterBuoyancy/tree/master and article (with calculator) https://scienceprimer.com/buoyancy
If an object has density lesser than the density of the water, it will float. If an object has greater density than that of the water, it will sink. If for example an object has density equal to half the density of the water, then the object will submerge exactly half of its volume. The other half of the volume will be above the water.
Water Buoyancy Simulation for Unity Engine
Source code: https://github.com/dbrizov/NaughtyWaterBuoyancy
Water Buoyancy Simulation for Unity. Contribute to dbrizov/NaughtyWaterBuoyancy development by creating an account on GitHub.
When asked why do some things float and others sink, the first thing that comes to many people's minds is the weight of each item. While weight*, or more properly, mass does play a role, it is not the only factor. If it were, we could not explain how a giant ocean liner floats while a small pebble sinks. Mass matters, but there is more to it. Th...
it just needs some geometry stuff to be added to Parry (or Peck if/when we switch to it)
Is "geometry stuff" still missing or was it already implemented?
Still missing
By geometry stuff I mean helpers for computing the submerged volume for different shapes
Some shapes have analytic formulas, and for convex hulls there's a general algorithm that is described in Game Programming Gems 6
which is also implemented in Jolt
(maybe more a Parry question but...) Is there a way to do a rounded compound collider? It looks like Shape is only implemented for RoundShape<T> for some specific shapes T but not for Compound. I'd like to have a collider for a shape composed of cubes, but rounded (including "inverse" rounding e.g. for an "L" shape in the inner edge ). So I could have a compound of cubes, then add a Round around that. Note that this is not the same as compounding some rounded cuboids. If not I'll make a trimesh but that sounds like a waste.
Something like that:
The rounded shapes probably wouldn't be implemented for concave cases anyway, since those are very complicated and expensive to calculate
this is not possible with the collision detection algorithms that exist today
you could do it with alternate representations
but this is very much not a thing any physics engine im aware of implements
"collides" (ie non-static iirc), "reacts to collision" (ie dynamic), "moves according to velocity" (ie dynamic|kinematic), and "syncs physics transform" (maybe all three? or unrelated) could just all be marker components, right?
i think that would only add to confusion, especially if you're coming from another engine
can still have dynamic/kinematic/static
either with required components or hooks
could even just call that second one "dynamicbody"
would either really work if they have to track multiple components?
should also have a marker for "this is a body, descendants should refer to this"
a single component with toggles would work i guess
can do anything with hooks if the component's immutable
it's mutable though
you often need to switch from kinematic to dynamic for ragdoll on death
can just use a command
iirc there's even a pr for splitting the rb component to three markers
bevy is the perfect place for crazy experimental ideas but this needs way more thinking that i'd rather see going into a standalone collision lib 😅
that'd only care about one of the markers
Oh right I got confused for a second, obviously the GJK radius applies to convexes only. And for concave parts the radius / Minkowski sum wouldn't produce that rounding anyway, it would produce a hard edge offset by the radius. So indeed no simple solution. I'll use a trimesh, I don't need precision in the rounded area, they're only used to mask out picking from what could be behind them. The picking only matters on flat surfaces for my use case. Thanks!
Would anyone object to making rigid bodies required for all colliders? (both normal ones and sensors)
This would have several benefits:
- Contact data, collision events, and spatial queries could store an
Entityinstead ofOption<Entity>for the rigid body. - Internals would have less branching, as they could assume colliders to always be attached to rigid bodies.
- This would fix the confusing behavior where a body-less collider and static sensor are currently behaviorally equivalent.
- This would fix the footgun where users coming from Unity might expect a collider without a body to behave like a static body (they don't, dynamic bodies won't be affected by them).
- This would greatly simplify my current BVH work. I'm putting colliders into dynamic, kinematic, and static trees based on the body type, but if we allow colliders without a body, we'd need a fourth tree for "standalone" colliders.
If we do this, we could probably have an optional warn! for colliders without a body. Note that Godot also works similarly
as long as it has no performance hit then sure, just don't call it a rigidbody then
Alternatively, we could go the Unity/USD route and remove the concept of a "static body", and just make body-less colliders act as static collision geometry. I'm just not entirely sure if I like it conceptually
i.e. RigidBody would only have Dynamic and Kinematic variants
iirc Bepu also works like this
if you're doing that then you might as well go further and try to see what you can do with @sweet sundial's suggestion
we still want markers for dynamic and kinematic bodies, further markers are kinda unnecessary imo and would just complicate internals further
its not a rigidbody if it can be a sensor, how about calling it physicsbody or something like that
that's also a rigid body by general physics engine convention
@vestal minnow do you benefit from RB being an enum?
no, we want to split to RigidBody (shared marker), DynamicBody, KinematicBody, and maybe StaticBody
but those still need to be mutually exclusive
either via archetype invariants or "archetype invariants at home" aka hooks
which one?
RigidBody marker component + mutually exlusive SensorBody DynamicBody KinematicBody StaticBody
in Avian the body isn't a sensor, the collider is, you could have both a sensor collider and non-sensor collider on the same body
what's the difference between kinematic and static internally? velocity?
this is different from some other engines but is more versatile imo
so really RigidBody is a Collider root
A RigidBody is a physics object that you can attach shapes (colliders) to
the colliders can be directly on it or on children
yes
when the root is a sensor, are all the children colliders also sensors
no, just that specific entity's own collider
okay
so Sensor really is different
and if you have a rigidbody dynamic with a collider and a child with a collider and sensor, does the child affect parent's collisions or is it just sensor
just a sensor
each collider attached to a body also currently has its own collision events
so collisions are between colliders, not bodies
(but they affect dynamic bodies)
unlike some other engines
Most of this design is motivated by Avian using Bevy, Bevy having an entity hieararchy, and people expecting to have per-entity behavior and configuration. With typical physics engines you don't have an actual hierarchy, you just have bodies and they can have one or more shapes attached to them, but the body remains as the core "thing"
Dynamic and kinematic bodies are part of simulation islands and can sleep, unlike static bodies. They also have a SolverBody component when they are awake, which contains the body state that the constraint solver reads and writes to (velocity, delta pos and rot, and flags). Static bodies are not mutated, so they don't need a SolverBody. Because of this, static bodies are also not a part of graph coloring, which improves parallelism, since you don't need to worry about race conditions for static bodies.
For my current BVH work, different body types are also in their own trees. Unlike the dynamic and kinematic tree, the static tree does not need rebuilds, and only needs to be incrementally updated when static bodies are added/removed or teleported
(though you may still want occasional optimization via reinsertion or something)
So yeah, there's a lot of optimization for different body types, and it's important to keep a clear separation both conceptually and in terms of internals
Dynamic and kinematic bodies are more similar to each other, with the latter mainly just having infinite mass and angular inertia. But this also allows some optimizations, for example kinematic bodies don't really need velocity integration or CCD
non-dynamic body pairs should also not have collision detection unless they're sensors, although currently they do
aren't static bodies mutable, but only manually and not by physics engine?
yes, users can modify them, but the solver doesn't write to their body state, which allows accessing the same static body from multiple threads in parallel without race conditions
unlike with dynamic and kinematic bodies, which require graph coloring to avoid race conditions
this is my main motivation for the many-marker thing
so static is already a misleading name for it
not really, it's not meant to be moved in a dynamic way, it's just if you need to e.g. teleport geometry from one place to another
the body is static (shouldn't be moved), its collider and other properties can be freely modified
the alternative name is Rapier's RigidBody::Fixed, which I really don't like personally
i associate static as a name with things like lighting, where "moving this will break everything, there are no incremental updates, you'll need to rebake everything for a minute or more"
moving a static body with velocity or forces doesn't work, and changing the transform directly is bad for almost anything other than teleporting from point A to B (ex: big_space moving objects around) so in practice they really can't/shouldn't be moved
it's not a "you literally cannot move this or everything breaks", it's more of a semantic "this should not move in relation to other geometry, it is a static object"
it just takes a while to build intuition for how dynamic/kinematic/static/sensor work and interact, and there might be a better way to convey the meaning if you're going to split everything up into individual components anyway
Wait I Cant like lerp move a static body? Otherwise It Will break?
how would sensors work in this then? now that i look closely, i see that the entity i'm using Sensor with already has RigidBody::Static. so iiuc - that's not currently required, but would become so
Trying to understand why i can't get collisions to work with gltf models using ColliderConstructor::ConvexDecompositionFromMesh ... This is what i spawn:
commands.spawn((
MagicPortal,
SceneRoot(asset_server.load( GltfAssetLabel::Scene(0).from_asset("european_and_american_game_scencemagic_portal.glb"),
)), ColliderConstructorHierarchy::new(ColliderConstructor::ConvexDecompositionFromMesh),
Transform::from_xyz(-225.0, 0.0, 280.0),
RigidBody::Static,
CollisionEventsEnabled,
));
The 3d model loads fine, the colliders are correctly created.
But raycasting or shapecasting doesn't work, while it does for colliders created using Collider.
When you use ColliderConstructorHierarchy, does it create subchildren entities for each collider ?
"A component that will automatically generate Colliders on its descendants at runtime". Ok so i need to make a query that has MagicPortal as parent.
gltf scenes are a whole hierarchy, could be grandchildren or further
That's what i've just found out, i think the query would be costly ...
going up the tree isn't awful
Nvm, I missread that thought were removing static status completely lol.
Yeah the RigidBody would be required
I can see if I can still support body-less colliders for 0.5 so we can let the design cook for a bit longer... It just makes some of the BVH stuff a bit more annoying
well you can, but semantically it should be kinematic if you're going to be moving it, and if you just change the transform directly instead of velocity (for any body, not just statics), then
- collisions will not consider the movement correctly, since from the engine's POV the velocity of the body is still zero
- speculative collision won't work properly, since the velocity is zero
- restitution won't work properly, since the velocity is zero
- if you're moving a body sideways underneath other bodies, they won't move along with it by friction, because the velocity of the body is zero and you're effectively just teleporting it
Would anyone object to making rigid bodies required for all colliders? (both normal ones and sensors).
Deformable/soft bodies will have separate colliders/handled differently?
Soft bodies could reuse some of the component APIs used by rigid bodies, but they would work very differently. In practice they would store a bunch of particles and constraints between them, in their own structure, not as entities or using traditional colliders, and they would have their own stage in the simulation where movement and collisions are handled.
I would like that 🙂 I’d have to migrate a couple of rb-less colliders to use sensors, but that sounds easy
Yeah I think I'll try to avoid meaningfully breaking users for this release, but I definitely want to change things for the next one. From a performance and usability standpoint, I would really like if code could always assume colliders to be attached to a body, but for apps that just want spatial queries or collision detection but no rigid body behavior, "standalone colliders" also make sense. It's also kind of strange if you mark a collider as a Sensor but it doesn't do anything until you attach it to a rigid body as well. So it's a trade-off
I think my current thoughts on the ideal design are:
- Only dynamic-dynamic, dynamic-kinematic, and dynamic-static pairs should have collisions by default. These are the only pairs that make physical sense, the rest are unnecessary for the simulation. This is also how other engines work.
- Pairs like kinematic-kinematic can still be useful for niche cases, like KCCs that use contact data directly. If possible without hurting performance, we should support these nicher pairs with an
ActiveCollisionTypescomponent, similar to Rapier (link). - All colliders, even "standalone colliders" without a body, should still be queryable via spatial queries. We can have an optional spatial query filter to filter out body types.
- Sensors should detect overlaps against all other colliders, but not compute contact data. They should just store overlapping entities and send events.
you sure you don't want to do it in one go?
the migration is trivial
Ideally I'd have the full design more or less locked down instead of breaking users in consecutive releases, and we're getting pretty close to 0.5 here with 0.18 probably releasing today/tomorrow
so I'd like to avoid big last-minute breaking changes if possible
and yeah whether we support standalone colliders is still up for debate, but I think the general approach here would be decent
from a physics engine POV I don't really want to support them, but I can see reasons why they could be useful (ex: using Avian just for collision detection without rigid bodies)
and Rapier does also support them afaik
"using avian because it has a great library of colliders compared to upstream" is definitely a use case I've had before 😅
would spatial queries not work with them either?
if they would then it's a valid use case and makes perfect sense, just needs to be explained right away
If we do decide to not allow colliders without a body, then I would prefer not to support spatial queries for them either
(also to be clear, if support were dropped I wouldn't have a problem with it. I'd prefer if avian was fun to work on for y'all, etc)
It's not too bad to support, but it does add some extra complexity and minor overhead. The most important part for me though is just a clear mental model and ideally not having many ways to do the same thing
right now a collider without rb, a sensor collider without rb, and a sensor collider with a static body are all pretty much functionally equivalent 🙃
Removing "static bodies" and having colliders without a rigid body act as static collision geometry would be the other way to solve this
I think this could be more efficient too in some ways
i think i like this option the most, would it break anything if you made just that 1 change before 0.18?
I mean yeah it'd be a pretty big breaking change, RigidBody::Static wouldn't exist and standalone colliders would work differently
(since they'd be equivalent to the old RigidBody::Static)
internally or for users? for users it shouldn't be an issue
for both
in that case 5.5 makes more sense 🫠
fwiw i'm in favor of making this or a similar change.
probably aware, but there's an error on the 0.18 branch with f64 enabled about Vec3A::from
Ugh, bevy_heavy ruined my day again, pulling in Bevy 0.18 when it shouldn't have
bevy_heavy is my nemesis
I actually don't quite know how to proceed. Avian's versioning is such a dumpster fire
I can't just take the upgrade to 0.18 because egui.
It's really unfortunate that bevy_heavy breaks builds of existing Bevy projects whenever a new Bevy version releases.
that is so strange. I've seen you mention it a couple times, but I can't think through what's actually happening there. bevy_heavy has a version on "0.17.0" on all its bevy crates.
In an older version there was a git dependency, but I think that was fixed before avian 0.4.0 🤔
If for some reason something still pull it in as a git dependency, you could add a patch block to point it to the specific commit you want (one that uses bevy 0.17)
could it be the devdep on itself with a path="."?
As long as it is just a path and just in the devdep, shouldn't be a problem
its path + a feature enable, but just in the devdep afaict
Yea, I think that's the common pattern to enable features in dev mode, though it causes some weird issues in certain cases, it should never be an issue externally
Like even if that was resolved, it would just point bevy_heavy 0.3 to the folder of bevy_heavy 0.3
That said, I do know that avian had a git dep for bevy_heavy, and other crates had to copy it for it to behave correctly. If avian or any other crate still has any of those git deps, then calling cargo update, or having it happen indirectly would pull in bevy_heavy main which uses 0.18.0-rc
This was changed somewhere in the release cycle of 0.4 iirc
yes in https://github.com/avianphysics/avian/commit/7333c252871f9f7febffcebb3f84203150a2b74e they got a commit rev, and in https://github.com/avianphysics/avian/commit/8add2486621e576bf7f5fb75013a65956c414353#diff-6f370894a9f51f6123b5404b781a4904837c878c095f0594dd224be6f27cb5a7 (which is afaict the actual release commit) they got versions
would this be part of the ghost collision mentioned in: https://github.com/avianphysics/avian/issues/612 ?
Is there any way to stop / lessen the impact for now?
Assuming that floor is using a trimesh collider: I've seen decent improvements using TrimeshFlags::FIX_INTERNAL_EDGES
Cool! I will test that out! Thank you
is there something where adding a collider or a rigidbody or a collision layer that would cause an entity to reset its transform to Transform::default?
adding a rigidbody during the part of the schedule that assumes Position is accurate might
it might be something like that...I think I sorta figured it out it's like.. I have a collider that has an observer and when something collides with it, it spawns an entity by cloning a disabled, hidden entity. it's something about cloning an entity that has a rigidbody&collider in the observer of a collision keeps the original transform even if I'm inserting a new transform on the cloned entity
but I "solved" it by just queuing the clone to happen in the next fixed update
that thing is so common i'm wondering why the fix isn't enabled by default 🤔
it's a lot of unnecessary compute if the normals don't have the problem iiuc?
I would probably be in favor of enabling it by default
Originally I didn't since Rapier also doesn't, and I wasn't sure of the performance impact
I still haven't measured that but the problem is so common that I'd rather have it fixed by default and take a small perf hit for it
worth noting that it should only fix it for the internal edges of the mesh, and doesn't help with edges where different colliders meet
but the latter is what ghost collisions usually are known for, so internal collisions are extra confusing
guess it's time to upgrade
which shiny new features are getting delayed by 2 weeks?
move and slide!
broad phase BVH
(-> sleeping dynamic bodies are now essentially free)
Like Jan mentioned, at least:
- Move-and-slide
- Broad phase BVH
Most likely also:
- Joint motors for revolute and prismatic joints
- Spatial query rework, using the broad phase BVH
- Updated character controller examples, using the move-and-slide algorithm
I'll try to get 0.6 ready in time for the game jam though
jondolf you are the goat
Jointdolf you are the joint (implementor)
Blender works on XPBD based physics solver node https://projects.blender.org/blender/blender/pulls/145341
It seems there are no issues with license?
yeah Jolt (which even Godot uses) also uses XPBD for soft bodies
I'm not personally concerned about the patent or other legal issues, but some Bevy maintainers still would prefer to be extra safe
but idk we'll see
I'd like to switch away from XPBD for joints regardless
joltdolf
If we eventually implement soft bodies, we'll need to consider what makes the most sense for that, probably either XPBD or something VBD-like
VBDolf
is there a suggested approach for despawning entities? I've been going with the Chainboom approach of despawning at a specific point in the frame (I'm doing my despawns in FixedPostUpdate after TransformSystems::Propagate)... that has avoided any panics for the most part but I still get these sometimes
Tried to wake body 3127v2 that does not exist
Hmm I might know what's causing that, I'll test in a sec
But yeah despawning entities should "just work", at least outside the PhysicsSchedule
Avian's main branch is now on Bevy 0.18. I'm working on getting the 0.5 release out too now
there is 2 thing iam hyped
Bevy having a editor
and Avian being added on Bevy officialy

()
Yeah I fixed this, on main it should work
yippee
It's late so I won't get to this right now, but I made an issue and also reproduced the problem
https://github.com/avianphysics/avian/issues/922
should be a fairly straightforward fix I think
ayyeee ty ty
and grats on the release
time to break my project and spend an hour patching it >: )
nvm everything just worked
for a precision platformer, would it be effective to use avian for collision detection but handle movement purely by code?
Move-and-slide: The fundamental movement and collision algorithm for a Kinematic Character Controller (KCC).
i think i might wait for 0.6 then
kinematic is what i want i think, i have rigid rn but it doesn't feel very good to control
hi,
i have a question, how do i handle ramps?
the relevant nodes my player has are:
RigidBody::Dynamic,Collider::cuboid(1.0, 1.0, 1.0)
and my ramps contain:
RigidBody::Static,
Friction::new(1.0),
Restitution::new(0.0),```
i feel im missing something very simple
surface of a cube against a high-friction flat surface isn't going to slide
you could try reducing friction? not sure what effect you want
slopes and stairs are basically half of the reason why char controllers get complicated 🥲
i have a system ... you can go down ....
and if you wanna go up ... you teleport up
until i fix this
ill look through more examples and get it eventually
urface of a cube against a high-friction flat surface isn't going to slide i think this is the main issue tbh
A detailed look at how we built our physics-based character controller in Unity for our game Very Very Valet - available for Nintendo Switch, PS5, and Steam
BUY NOW!! https://toyful.games/vvv-buy
~ More from Toyful Games ~
- Animation Deep Dive mentioned in the video - https://toyful.games/blog/character-animations
- Custom Car Physics in Unity...
make the cube's friction 0.0 with the 'min' or 'multiply' combiner
if you want to just ignore friction and add it in post
and avian 0.6 is supposed to have a kinematic CC, it'll PROBABLY handle slopes and stairs
just use tnua for a floating controller
i took a look at it, it seemed so overcomplicated compared to my 2 lines of code i just didn't bother
... what are the two lines?
i was already sending ray to check for ground so i'm excluding that, and after that it's just
if player.up.dot(hit.normal) > 0.95 {
velocity_change += player.up * (((target_distance - hit.distance) * spring_strength) - ((player.up.dot(lv.0)) * spring_damping)); }
steepest possible slope of pi/12 is a bit harsh
it's so that i don't forget to configure it properly later 😄
my custom controller has a cutoff for vertical vs horizontal surfaces at something like a dot of .125
doesn't actually stop doing things then though, it just changes from "jumpo off floor" to "run up wall"
*-o
i just have 1-u stairs it automatically climbs because i won't be sure about slopes until i have a dozen levels with them for playtesting
i usually really dislike slopes in games because the cutoff is never intuitive
be a force for change, make it attenuate by angle with no cutoff
the games with climbing/wallrunning are better but i don't wanna go down that rabbit hole
i guess i could just make some kind of shader that shows a clear line where slopes become too steep 🤔
like grass stops growing, or snow stops accumulating
cel shading + directly overhead light + tuning
but what would i do in areas where gravity changes
make the light overhead anyway ww
It'll have move-and-slide, and some other core features to facilitate KCCs, and ideally better examples demonstrating some simple KCCs, but it probably won't have built-in KCC components yet
Right now I would recommend Jan's bevy_ahoy crate for 3D KCCs, either directly or by vendoring it and modifying it for your needs
but does move-and-slide have a slope check?
(Or bevy_tnua for a floating character controller if that's what you prefer)
No, but there's a callback that is called for each hit surface, which I think you could use for this
if it's in the examples then it should be good enough
bevy_ahoy handles slopes and stairs and uses Avian's built-in move and slide algorithm utilities
So it should be possible
I haven't looked too deeply into what bevy_ahoy is doing though, it's mostly Jan's stuff
it probably won't fit most games just because of air strafing 🫠
yeah, it's a bit specialized in some ways for sure
Eh, all Quake-derived engines have some form of air strafe, even Call of Duty
I think it’s fine for most
You can tweak the amount of air control down if it’s really a problem, or reset momentum on landing
or just fork it and do whatever you want as suggested in the readme
If you set the Visibility of an entity with a RigidBody and Collider to "Hidden", does it make the Collider inactive and therefore spatial queries won't hit these colliders ?
yeah but bevy isn't quake-derived, it's cool if that exact kind of movement is desired, it's just strange when you need a hacky workaround to fix a bug that was included intentionally
Visibility is a purely graphical component, if you want it to stop colliding you can use avian's components for that or entity disabling
Ok. I need the entity to be hidden and stop colliding. I just saw the ColliderDisabled component, will try it. Thanks!
A rigid body is for dynamic simulation. A collider is for collision detection. The former uses the latter, because it needs the collisions to simulate, but not the opposite. I don't think coupling them makes sense. You should only have rigidbody require collider, not the opposite. I don't really understand why 3. exists in the first place, can't "sensor" be removed/merged? Same for 4., can't this be fixed? This is the standard behavior not only in Unity.
material properties such as friction and restitution is usually associated with the bodies, so rigid body vs just a collider does usually not make sense
having standalone colliders just complicate things imo
just create some dummy static body for a bunch of colliders if needed
A rigid body is for dynamic simulation.
Yeah, or more specifically I would define a rigid body as "a non-deformable physics object that can participate in dynamics simulation". Dynamic, kinematic, and static bodies are all rigid bodies (they can affect the dynamics simulation) but colliders that only do collision detection are not.
A collider is for collision detection.
Agreed (and commonly also for spatial queries)
I don't think coupling them makes sense.
I agree with this in principle. In practice, I would split contacts into roughly three categories:
- Sensor overlaps: You want a list of overlapping entities, fast. No need for actual contact data.
- "Geometric contacts": You compute raw geometric contact data between intersecting colliders, including the points, normals, and penetration depths. These are for collider-only applications that don't need a full physics engine.
- "Rigid body contacts": You compute contacts used for the dynamics simulation. Contact data may additionally include warm starting impulses, separated contact points (for speculative collision), island node handles, constraint handles, various flags, and more.
Physics engines typically only support (1) and (3). For a game that does not use rigid bodies, (3) is kind of overkill and has additional overhead and rb-specific assumptions that you may not want for general-purpose collision detection.
In general, I would recommend implementing (2) manually, either using a collision detection library like Parry (or soon Peck), or by just using sensors and Avian's contact helpers to compute what you need for the overlapping entities.
I don't really understand why 3. exists in the first place, can't "sensor" be removed/merged?
A sensor is for detecting overlaps. Like Area2D or Area3D in Godot. Really they shouldn't compute contact manifolds like we currently do, and should use more efficient overlap tests, I just haven't gotten around to implementing this yet.
Additionally, you may want a single rigid body to have both sensors and non-sensors. For example, a player character with a capsule collider and a sensor at the feet for ground detection (though in practice, this specific thing would rather use a shape cast). These have very different behavior and semantics, but both broadly perform "collision detection" and are attached to a rigid body.
Same for 4., can't this be fixed? This is the standard behavior not only in Unity.
It's what PhysX does(nvm see my message below), which is most likely a big reason why Unity and later USD also adopted it (NVIDIA and the Omniverse are fairly heavily involved in USD). Personally, I'm still not fully sold on it conceptually, since having a body-less collider act as a static body without being explicitly tagged as one feels a bit wrong to me. But it does have some benefits, and we should consider it, see my message(s) below that one.
Godot, Rapier, Avian, Jolt, and Box2D (and soon Box3D) have dynamic, kinematic, and static bodies as separate concepts. A shape by itself is just a shape, but you can attach it to a dynamic/kinematic/static body to act as a collider. This is the more common convention I've seen in engines.
Edit: or well Avian and iirc Rapier currently have standalone colliders too, but still, static bodies are an explicitly defined body type
okay sorry for the wall of text lol
Yeah, that's the main reason I'd like to drop support for them
It adds extra overhead and complicates internals for something that would be better handled by a custom solution anyway
Ex: you probably don't even need full contact manifolds if you're not using rigid body dynamics
Oftentimes you'd only need the deepest point, or just a boolean overlap test
Ah nevermind, apparently PhysX has explicit static rigid bodies too
it's only some game engines like Unity and scene formats like glTF and USD that have static geometry not use rigid bodies in the same sense
and Bepu technically has "statics" which are not bodies
so in the future, if you only need colliders and shape casting, that would theoretically be a "not avian" usecase?
I just ran into this again this week doing some simple games (block breaker, etc), upstream bevy doesn't have shape casting but does have raycast against aabb/circle. So just trying to figure out directionally where the usecase lands.
(I guess that's peck/parry then?)
I haven't fully decided on anything here, but I think I would mayybe still support spatial queries for "standalone colliders"
Or more specifically, in an ideal world, I would like to design our collider BVHs to be flexible enough that you can define a marker component like GizmoShape, and then all colliders with that marker component would go into their own "gizmo tree" that you can query independently of other colliders. Vaguely similar to Jolt's broad phase layers. This could be useful for editor-like things (ex: gizmo picking), or for those non-physics cases that only need colliders
yeah, absolutely understand this is theorycrafting atm
Mainly just the built-in collision pipelines would probably not do anything unless a collider is on a rigid body, But yeah I'm not sure yet
I think I'm losing my mind. Does ColliderConstructorHierarchy work properly for non-static things? I have a gltf that I spawn. Using skein, I add a component whose required components include RigidBody::Kinematic and ColliderConstructorHierarchy::new(ColliderConstructor::TrimeshFromMesh). But when I do this, the collider child keeps getting its transform reset to keep the original global position.
With the track_location feature, this function is mutating the position often crates\avian3d\..\..\src\collision\collider\collider_transform\plugin.rs:84
Ok my mistake, this looks to be the fault of lightyear_avian/lightyear_frame_interpolation in some way
hey! is there a way to ensure the entity will keep minimal velocity? I'm having trouble to figure it out myself.
I want the body keep going lets say 10 m/s but what is the right way to do that when the velocity can be Vec3 { x: -4.0, y: 4.0, z: -16.0}?
essentially you want the vector's length to be 10 then
i'd do linear_velocity.normalize_or_zero() * 10.
tysm
np, note that it'll not move at all if the vector fails to be normalized tho
for example when it's (initially) not moving at all
nah, should be fine
Should get fixed by #924
I was running into this exact thing but I'm not using lightyear_avian 🤔
Is MoveAndSlide in 0.5.0?
No, it'll be in 0.6, see the release post
https://joonaa.dev/blog/11/avian-0-5
It's on the main branch if you need it early
Note that the callback APIs are not fully correct and will change slightly
and the KCC examples in the repo have not been updated to actually use move-and-slide yet
other than that, it's functional, and is being used in bevy_ahoy
So there are no proper examples right now? (Other than digging through someone else's code, which I am not a huge fan of.)
there are the 2D and 3D move and slide examples but they're not proper KCCs, more like flycam with collisions
bevy_ahoy is currently the only proper KCC that uses our built-in move-and-slide
but we'll definitely add more examples, and eventually official character controller features, yeah
I tried the 3D one, it has its issues.
Unfortunately, it doesn't fit to our project. But I guess I will have to dive into it for examples...
Also, how do I select 0.6?
use the main branch
avian3d = { git = "https://github.com/avianphysics/avian" }
you can also use a specific commit rev if you want
What issues did you see? I know one spot where it kinda gets stuck while sliding (the wedge of the rightmost green set of angled walls) but that's because Parry gives incorrect normals there, not because of the move-and-slide algorithm itself
other than that I'm not really aware of other issues
unless you mean with the API or example usage or something
Tbh I don't remember, it's been a while, but I tried 2 different examples from there. I made a post on GitHub about one issue though back then.
But that's probably about the old example.
Also curious, if I first calculate LinearVelocity from the input and then translate KCC by my own rules (using LinearVelocity value), is it possible to tell Avian that I've already dealt with movement so it doesn't have to, or should I just not use LinearVelocity, but some custom velocity instead? 🤔
We added a CustomPositionIntegration component that basically tells Avian "don't move this body based on velocity, I'm handling that myself"
This way you can just use LinearVelocity, but handle translating the body with your own logic
Thanks!
oh nice! so we can use transform/position movement now as long as we keep linear velocity up to date?
I ran into this trying to build some character controllers in the past and trying to figure out how to best integrate, but found that I had to let linearvelocity drive everything at the time
This is useful. It probably makes sense to upstream these components to Bevy?
Together with character controller right after we have bevy physics.
how do i get rectangle collider shape in avian2d bevy
A collider used for detecting collisions and generating contacts.
the size from an existing collider?
I am trying to run Bevy + Avian3D in a fully headless setup (no windowing, no rendering), using MinimalPlugins and ScheduleRunnerPlugin::run_once().
This minimal example compiles and starts, but panics immediately at runtime with a Bevy ECS validation error:
Parameter `...::messages` failed validation: Message not initialized
Full minimal repro:
use avian3d::prelude::*;
use bevy::{app::ScheduleRunnerPlugin, prelude::*};
fn main() {
App::new()
.add_plugins(MinimalPlugins.set(ScheduleRunnerPlugin::run_once()))
.add_plugins((
TransformPlugin,
bevy::asset::AssetPlugin::default(),
bevy::scene::ScenePlugin,
))
.init_resource::<Assets<Mesh>>()
.add_systems(Update, hello_world_system)
.add_plugins(PhysicsPlugins::default())
.run();
}
fn hello_world_system() {
println!("hello world");
}
[dependencies]
avian3d = "0.5.0"
bevy = "0.18.0"
The panic comes from bevy_ecs complaining about an uninitialized Message parameter (suggesting Option<T> / If<T>), but this happens before I register any Avian-specific systems myself.
Is this a known limitation of Avian in headless / MinimalPlugins setups, or am I missing a required plugin or resource initialization for physics-only use? Any guidance on the minimal plugin set needed for Avian without rendering would be appreciated.
yes, I want to debug draw them
nvm there's a plugin for that
If you know the type of the message, and can access it, you can use app.add_message::<T>() This shouldn't happen in the first place, though, as far as I know.
I upgraded to 0.5 and the debug plugin has stopped working for me! Am I missing something?
turns out I was missing bevy_gizmos_render which is new
will this still work if colliders have different CollisionLayers
If they have incompatible collision layers then they won't collide with each other and won't be included in CollidingEntities
unless world or default layer is same as characters, this shouldn't collide
are there other way to check if they're colliding
Is there any way to force avian to ignore the previous or reset the Position component value?
I am having a problem where adding ColliderDisabled and RigidBodyDisabled,moving the Transform and later finally reenabling produces some jerky movement.
I suspect it's because it performs physics calculations with the pre-disabled Position Component.
how do i fix this?
&mut avian2d::dynamics::rigid_body::LinearVelocity conflicts with a previous access in this query. Mutable component access must be unique.
forces contains LinearVelocity
or maybe i shouldn't use this
Forces has a linear_velocity_mut helper you can use
yeah
yeah, a collider as a child entity
does colliding entities include their children?
Thanks :D it was .add_message::<AssetEvent<Mesh>>()
if I have a sensor (sensorA) and entity B is inside of it.. if I move sensorA by updating its transform so that it's no longer colliding with entity B, would entity B get a CollisionEnd event triggered?
Is there any way of speeding up the simulation?
it should, yes, assuming it has CollisionEventsEnabled
ah, I think I have yet another "is this an avian bug?? no, it's a me bug"
Thanks a lot
hello, I have a child entity with a bunch of children. When I modified the child's transform without removing its parent, its children's colliders remain in place without following the entity to the new location. How to solve this?
which entities have rigidbodies?
none
try sticking a static rigidbody on the root
I found the real problem after trying your solution that wasn't working: if I pause Physics, moving objects won't move their colliders. Avoiding to pause makes it work even without RigidBody. Only thing is I'd like Physics to be paused when I do that
in other words, how do I make the collider follow the entity when physics is paused?
https://docs.rs/avian3d/latest/src/avian3d/collision/collider/collider_transform/plugin.rs.html#124 here's the function that does it
Source of the Rust file src/collision/collider/collider_transform/plugin.rs.
could try running the schedule once with zero delta time?
thanks for your help
btw, *collider_transform = ColliderTransform::from(*transform); won't work, not sure why. I am manually modifying it. It queries the colliders from the right entities.
might need to sync Position, but depending on what you're trying to do that might still not work
changing Position will move the body but not the collider, this is puzzling 🤦
I do think this should be easier to do, if it's possible at all. One might not want physics to run but still need a collider for picking, which might need to be moved
it doesn't do collision detection unless the schedule runs
i ran into the same issue and ended up just ticking fixedpostupdate manually, it was just a placeholder and i already removed it, but i'm really curious what the proper solution would be @vestal minnow
we could probably allow spatial queries but no actual collision detection while paused
i.e. update internal physics positions and BVHs but not run the actual simulation step
Could someone try out the obvhs branch to test if it breaks anything?
https://github.com/avianphysics/avian/pull/927
I think I've fixed the issues I've seen in my own test scenes, but this is one of those PRs that could have various edge cases in real use
If everything works well, you shouldn't see any new crashes or major changes in behavior
it should mainly be a perf boost
this fails to compile on my machine - i suspect because obvhs depends on glam 0.29.3 whereas everything else is on 0.30.10:
error[E0277]: the trait bound `glam::f32::sse2::vec3a::Vec3A: From<bevy_math::Vec3>` is not satisfied
--> /home/ty/.cargo/git/checkouts/avian-5a22c167119f3550/39a9d32/crates/avian3d/../../src/collision/collider/mod.rs:557:34
|
557 | min: value.min.f32().into(),
| ^^^^ the trait `From<bevy_math::Vec3>` is not implemented for `glam::f32::sse2::vec3a::Vec3A`
Avian uses the insertion_removal branch of OBVHS, which does support glam 0.30
It compiles fine for me 🤔 are you on bevy 0.17 or 0.18? Avian expects 0.18 which uses glam 0.30
(fwiw the CI failure isn't because of conflicting dependencies, it's because the examples currently need to support both the f32 and f64 features but my bvh example currently just uses f32 types)
Hey! When using the ColliderConstructor::TrimeshFromMesh, I'm having these weird contacts with the triangle edges. I am unsure why this happens and how one could work around this, except manually composing the collider from cuboids. Also I am still on avian 0.4, as I'm waiting for hanabi to get to 0.18.
The same thing does not occur when using ConvexHullFromMesh
ok i think i just needed to run cargo update. once i got it running, i observe that my observers that are triggered by systems that check for collisions are no longer being triggered
e.g. i have some hanabi particle effects and seedling audio that is triggered correctly when using avian 0.5 and does not trigger when using that branch
cool, yeah I also just noticed some problems with collision events, I'll try to fix it today
(and collision hooks)
can give it another go whenever you like
btw I added notes about two sets of panics on this branch to the PR.
Hey y’all, is there any part of the docs that need attention? I contributed to the docs a while back and looking to feel out the code base a little better.
Am I overlooking an existing Issue or is this actually expected/intended behavior? I just tried an minimal example on avian 0.5 / bevy 0.18 and it is awfully obvious:
[package]
name = "avian_bug_trimesh_from_mesh"
version = "0.1.0"
edition = "2024"
[dependencies]
avian3d = "0.5.0"
bevy = "0.18.0"
(left clip is using ConvexHullFromMesh and works fine, right one uses TrimeshFromMesh and does not)
@rocky seal @wet niche Those crashes and collision event bugs should hopefully be fixed now if you run cargo update again 🙂 I'd appreciate if you can give it another try when you have time
no hurry though, I'm headed to bed right now and will likely be fairly busy tomorrow
These are called ghost collisions, basically the body is colliding against the internal edges of the trimesh. You could try using this:
ColliderConstructor::TrimeshFromMeshWithConfig(TrimeshFlags::FIX_INTERNAL_EDGES)
see the docs of TrimeshFlags
Flags used for the preprocessing of a triangle mesh collider.
note that this won't fix the problem at the edges where two different colliders meet, it only works for the internal edges of any given mesh
Also see this post if you're interested about ghost collisions, it's 2D but the same core concept applies to 3D as well
https://box2d.org/posts/2020/06/ghost-collisions/
Dealing with ghost collisions is a challenging problem in game physics. The basic idea comes from motion across a flat surface. You may have several shapes joined together to make a flat surface, like a triangle mesh in 3D or a chain of edges in 2D. Convex shapes can hit the internal connections and have their motion blocked. This is undesirable...
Hi! Something that could be useful is going through all of Avian's user-facing APIs (primarily components), and making sure they have at least one useful code example in the docs
Most of them should already have a code example, but I'm sure that some are missing, and some of them are also really basic and don't really demonstrate anything that is actually useful
Outside of that, it's useful if you can think of something that you wish was documented, but isn't
Keep in mind that these are mostly API docs though, so they should mostly focus on "what is this, how can I use it, what should I be aware of, and how does it relate to other APIs", instead of higher level guides or tutorials
Nice, that works for my case! Adding a little extra line that mentions this at the trimesh_from_mesh function would be a neat little documentation PR, no?
A collider used for detecting collisions and generating contacts.
Had not encountered this yet, but thanks for pointing that out, I wont be surprised when it happens the first time now :)
Yup, that too! @native sky
We've been considering enabling the flag by default since it's such a common problem, I'd probably accept a PR for it as well
though I have not profiled what the performance impact of the flag is
but I'll take slightly worse performance over bumping on every edge of every trimesh :P
I did a small PR with a comment on Collider::trimesh_from_mesh and the same comment on Collider::trimesh_from_mesh_with_config
https://github.com/avianphysics/avian/pull/931
This is a great starting point thank you! Honestly I’ve probably been a little over zealous trying to get out and contribute, when in reality I just need to make some games and get my hands dirty… I’ll let the PRs flow naturally from there.
Oh no I just realized this will only work for flat things, and does not fix it for meshes where normals are pointing towards another
so FIX_INTERNAL_EDGES works only when no neighboring triangle has an angle less than 180°
In this mesh, crossing from bottom right over the middle line to the top left works fine since there is another plane to the left with an 180° angle, but from the top left to the bottom right does not get fixed, because the plane on the right is a slope
TransformInterpolation seems to break determinism. I'm using Position instead of Transform here to handle bumper logic also with FixedUpdate, but it still creates inconsistent behavior. 1st video without, 2nd video with.
Something I found helpful to debug this is to turn the fixed update rate down to like 10 Hz. It makes it more clear what is being simulated and what isn't (though in my case I was using a kinematic character controller, idk if collisions will behave reasonably in that case haha)
I'm not sure if this is something I'm doing though. I'm avoiding using Transform at all in this interaction and only using position, which should be using the physics position instead?
It still might be worth doing. I've found Avian has bad behavior if Position and Transform are both mutated (which could be happening if you're using transform interpolation)
I don't mutate the Position or Transform, i just use it to calc the bumper velocity direction to apply
I think in this case it's fine to just not use interpolation tbh, but just something i've noticed
I think I've encountered this before, IIRC the only way I could find to solve it was to fork parry and patch the normal constraint code to ignore concave edges when constructing the cone of allowed normals
for some reason ActiveCollisionHooks is not a valid component when inserted with other components, but I can insert it separately?
would it be possible to calculate the force of a collision without having to have them actually collide? I want destroy a collider if the resulting collision would have been big enough, without having to affect the dynamic object's trajectory
I'm trying to use hooks, but that doesn't seem to do what I want
Hi,
Do you think it would be possible to implement a decimate modifier with the trimesh collider ?
https://docs.blender.org/manual/en/2.82/modeling/modifiers/generate/decimate.html
That would be really useful to reduce collider computing without compromising on collider shape, but I dunno if it's doable :/
I would like to eventually have some utilities for simplifying mesh shapes, yeah. This would most likely be its own crate that isn't tied to Avian or Parry, and just produces a simplified mesh from the given vertex and index buffers
More specifically I would like to have PaMo, since it also plays really well with CoACD for convex decomposition (which I have a Rust port for)
https://seonghunn.github.io/pamo/
Parallel Mesh Optimization (PaMO) — GPU-based pipeline for low-poly, intersection-free, manifold meshes with high quality.
I'm just curious how you will solve ghost collisions in the CoACD output?
It looks more difficult than with trimesh
trying to make a simple RevoluteJoint between two objects but it seems to just get stuck
it's supposed to create a revolute joint between the ball and the center purple thing, hopefully so the ball can spin around it
I fixed this by adding Sensor and Rigidbody to the center object, and using a DistanceJoint, but now it doesn't handle rotation currently
I think I need revolute joint + distance limit which im not sure is possible
have you tried a RevoluteJoint with a non-default JointFrame in either frame1 or frame2?
just tried this it's very funny and very weird
turn up the compliance?
putting it on frame1 does nothing, frame2 does that
or down
that's with 0 compliance
i can try negative compliance, but that would get funky
yeah more/less compliance seems to break the joint
more/less compliance
same behavior
just completely breaks the joint
more being how much?
could try just, both
distance and revolute joint at the same time
i reckon the revolutejoint will mess with the distance joint
either it will do nothing or it will add janky behavior to the distance joint
ive had revolute joint so far
- do nothing
- wobbly thing
- completely stuck
- teleport it to the center
can raise the compliance
if i dont use offset, it will teleport to center
if i do use offset, adding compliance will break it entirely
if i dont use offset and add a ton of compliance, it would influence the trajectory i think
i think i will stick with distance, and maybe hardcode a rotation function to manually rotate it if I really care
because revolution joint has only brought sadness
you want wobbly thing plus distance joint
notice how the wobble still has the alignment perfect
it just doesn't have the right force for keeping the mass on the circle
then raise the compliance, which is the inverse of stiffness, to make it do less in the ways you don't need
you can just compare with and without
yeah, probably
point_compliance specifically if that was ambiguous
i understand i think i will avoid it for now
tried this, it just kept spinning
adding point compliance seems to have broken it entirely
how's it work with all zeros in compliance
it has a janky flicker but technically works, also i found a crash with avian2d when despawning joints
could try setting either the joint frame rotation or just the body's rotation
i care more about the crash i think at this point xd
when are you despawning them?
i think i despawn one of the connected colliders
when in the schedule
this seems to heavily affect the trajectory as well
seems to give it a lot of extra speed
do not like the jiggle
fun
yeah it does
Putting it here for other people to use:
```
pub fn collect_started_or_changed_collisions(
collision_started_listener: &mut MessageReader<CollisionStart>,
collisions: &Collisions,
just_changed_collision_layers: &Query<(), Changed<CollisionLayers>>,
) -> HashSet<(Entity, Entity)> {
let mut collider_pairs_to_check: HashSet<(Entity, Entity)> = HashSet::new();
for CollisionStart {
collider1,
collider2,
..
} in collision_started_listener.read()
{
collider_pairs_to_check.insert((*collider1, *collider2));
}
for ContactPair {
collider1,
collider2,
..
} in collisions.iter()
{
if just_changed_collision_layers.contains(*collider1) {
collider_pairs_to_check.insert((*collider1, *collider2));
}
}
collider_pairs_to_check
}
(It collects both started collisions and ones where the CollisionLayers was changed)
Is there a way to manually trigger collisions?
The entities with changed CollisionLayers aren't in the Collisions query
Hmm are the entities sleeping or something?
If they are then you can probably just do commands.queue(WakeBody(body))
(or remove Sleeping)
If not then I'm not sure why it wouldn't be detecting the collision, assuming they are actually touching
They are
Thanks!
Is there a way to prevent CCD from passing through a sensor? I have a sensor that teleports a fast moving object, but it triggers the sensor and also triggers collisions with further rigid bodies
as shown here
it both goes through the portal and hits the plank
I want the CCD to stop at the first sensor
ive got 10k box Colliders and performance is already taking quite a hit.
bevy = { version = "0.18", default-features = false, features = [
"default_app",
"common_api",
"3d_bevy_render",
"ui_bevy_render",
"default_font",
"multi_threaded",
"std",
"x11",
"png",
] }
avian3d = { version = "0.5", features = ["simd"] }
[profile.dev.package.bevy]
opt-level = 3
[profile.dev.package.avian3d]
opt-level = 3
(0..10000).for_each(|_| {
let v = AREA_SIZE / 2. * random_in_box(&mut rng);
commands.spawn((
Transform::from_scale(Vec3::splat(2.)).with_translation(Vec3::new(v.x, 0.1, v.y)),
RigidBody::Static,
Collider::cuboid(2., 2., 2.)
));
});
Am I missing something obvious ?
having a lot of colliders should be much, much cheaper in the upcoming release
ah okay, so it (probably) isn't me having something mis-configured ?
So the problem is in just the number of entites then ? If I were to merge them into a few colliders (same geomtry tho) would that significantly improve performance ?
Are CollisionsHooks cached somehow? I'm using them to support separate floors with Avian2d as stated in the docs:
fn filter_pairs(&self, collider1: Entity, collider2: Entity, _commands: &mut Commands) -> bool {
// Only allow collisions between entities in the same interaction group.
// This could be a basic solution for "multiple physics worlds" that don't interact.
let Ok([group1, group2]) = self.interaction_query.get_many([collider1, collider2]) else {
return true;
};
group1.0 == group2.0
}
But when I change the group of a collider it sometimes still collides with the colliders of its previous floor. Disabling and reenabling the rigidbody that changed floors fixes the issue. I can open an issue if this is a bug.
I've confirmed that doing Collider::compound on everything as a single entity improves things quite significantly
At this point I guess I should probably have collision serialized and just load it for a map, huh
Sooo to do compound, i needed to destructure any nested compound shapes like this. Looks quite gross :
let comp_coll = Collider::compound(children_query.iter_descendants(map).filter_map(|child| {
let Mesh3d(handle) = mesh_3d.get(child).ok()?;
let mesh_asset = meshes.get(handle)?;
let &ChildOf(parent) = childof_q.get(child).ok()?;
// Parent is the Blender object which contains the properties
let (t, GltfExtras{value}) = gltf_extras_q.get(parent).ok()?;
let gltf_props: serde_json::Map<String, Value> = serde_json::from_str(value).unwrap_or_default();
let mut collider = (match gltf_props.get("Collision") {
Some(Value::String(s)) => match s.as_str() {
"Box" => {
let Aabb {half_extents, ..} = mesh_asset.compute_aabb()?;
Some(Collider::cuboid(2. * half_extents.x, 2. * half_extents.y, 2. * half_extents.z))
},
// Use `with_config`
"Decomposition" => Collider::convex_decomposition_from_mesh(mesh_asset),
"Hull" => Collider::convex_hull_from_mesh(mesh_asset),
"Trimesh" => Collider::trimesh_from_mesh_with_config(mesh_asset,
TrimeshFlags::DELETE_BAD_TOPOLOGY_TRIANGLES |
TrimeshFlags::DELETE_DUPLICATE_TRIANGLES |
TrimeshFlags::FIX_INTERNAL_EDGES |
TrimeshFlags::MERGE_DUPLICATE_VERTICES
),
_ => panic!("Unexpected property value for `collision`")
},
None => None,
_ => panic!("Unexpected property type for `collision`")
})?;
collider.set_scale(t.scale, 16);
Some(if let Some(compound) = collider.shape_scaled().as_compound() {
compound.shapes().iter().flat_map(|(iso, shape)| [(t.translation + Vec3::from(iso.translation), t.rotation * (Quat::from(iso.rotation)), shape.clone().into())]).collect()
} else {
vec![(t.translation, t.rotation, collider)]
})
}).flatten().collect());
hmm, how would i scale collisions to match transform
I would want it to apply to child colliders too
Collider::set_scale ?
yeh i made a script to auto scale them
if u got the 16 number from my snippet, do more research lol. i just kinda picked something random
i did the same thing idk what snipper you're referring to
oh
lmao we did the same thing
CollidingEntities doesn't seem to work if the transform is at 0,0,0 and rotation is 0
weird
if i even spawn it 1 pixel to the right, it does work
but when i move it back to 0,0 it doesn't work
right button is checking if the giant red rectangle is colliding w the item in the center
maybe i do manual collider queries
hmm, its not 0,0, its when two colliders are directly on top of each other in the same position and orientation
same w collision events
aabb is still colliding but manifolds is 0
I also ran into this while upgrading to 0.18
I went back to b5cd0ff and finished upgrading everything, did a cargo clean and build and everything was working.. and then I went back to 4e0c808 (avian main) and built and didn't run into this error
might be a weird dependency thing but I'd probably try a cargo clean and build first before digging into cargo tree
I am however running into a panic
thread 'main' (129238) panicked at forks/avian/crates/avian3d/../../src/data_structures/stable_vec.rs:334:13:
no element at index 9 in StableVec::index_mut
on 4e0c808
looks like it was introduced in 17d868e (1a1c5d5 doesn't panic)
I did try a cargo clean with no luck, same issue
I could try reproducing your process or trying cargo clean a few more times but
my laptop might get mad at me
ah bummer, yeah I wonder if it's something that you could narrow down by using cargo tree..
does modify_contacts only work for rigidbodies, and not collider <-> collider interactions?
Hi everyone! I'm trying to do the following:
commands.spawn((
RigidBody::Static,
Collider::heightfield(heights, Vec3::splat(1.0)),
));
heights is an array of 8192x8192 values
This doesn't work, my app crashes. Does Avian support such dense heightfields?
If no - then what is the best way to compute physics for my heightfield?
what's the crash say?
Hi ! I'm experimenting with swithing from rapier2d to Avian, and I have a collision to damage system (crash damage)
How could I access the impact strengh with Avian ? So far I only managed to get collision events, but they do not contain anything but the 2 entities colliding.
Edit: Nvm, I think I found the solution
OOM
(total_normal_impulse)
could try depending on nalgebra or parry directly, then using DMatrix::from_vec_storage?
I've solved it by dividing the map into 128x128 chunks. I'm not sure why it's better than a full 8192x8192 map, but it works
Collider::heightfield does an into_iter().collect()
Are there any tips/guides for optimizing a LARGE number of static colliders? I have a forest with trees represented by cylinders, and it's struggling to get the numbers up. The trees only need to check for collisions for a small number of more active entities, but I suspect it's still doing some O(n^2) calculations against the entire forest, despite configuring layer masks.
Ah, literally what was already being discussed. I'll go see if there's a beta version I can use until the release.
what's the best way to get the ColliderConstructorHierarchy entity off of a child collider's hit?
iter_ancestors
hey all, I have a few dynamic bodies connected with DistanceJoints forming a string, with a balloon on the end which has reduced gravity and a constant upward force. It works well, but if it stabilises, most of the bodies along the string including the balloon will get permenantly fixed in place. I am not sure where to begin debugging this, its for the ongoing bevy jam. Has anyone dealt with this before? Normally I would submit a full bug report, try to reproduce with minimal setup, etc, but just don't have the time this week. Thanks!
I also get the following warning for each body:
2026-02-10T01:58:26.079396Z WARN avian3d::dynamics::rigid_body::mass_properties: Dynamic rigid body 507v0 has no mass or inertia. This can cause NaN values. Consider adding a
MassPropertiesBundleor aColliderwith mass.
could that be related? I opted not to add colliders to them since I don't want them to collide with anything
ty yeah i figured this out after realizing i was doing iter and not iter_ancestors whoops
I suppressed this message by adding a small collider, and ColliderDisabled, however the bodies still permenantly freeze up once they get still. as long as I keep them moving, they don't freeze up
I am doing that already :/
that was my initial setup
Name::new("Balloon"),
Transform,
RigidBody::Dynamic,
// Collider::sphere(0.1),
// ColliderDisabled,
Mass(0.01),
CenterOfMass,
AngularInertia,
AngularDamping(0.8),
GravityScale(0.3),
ConstantForce(Vec3::Y * 1.5),
)]
I added CenterOfMass, and AngularInertia, since those are what is in the MassPropertiesBundle, but it didn't do anything
what's the default AngularInertia?
I tried removing the dampening as well
it derives default so Vec3 and Quat defaults
but it was happening before i added that component too
0 inertia sounds like it'd trip that
ill try that, thanks
that did the trick, thanks! Ill just keep SleepingDisabled on for those entities specifically
maybe a bug with DistanceJoint not waking up entities it applies forces to? The only thing which wakes up entities, listed in the documentation which could apply to these DistanceJoints:
A force, impulse, or acceleration is applied via Forces, without using non_waking.
is there a component i can add that gives an entity a collider that is always up to date with its mesh?
the docs say this for ColliderConstructor
A component that will automatically generate a Collider at runtime using Collider::try_from_constructor. Enabling the collider-from-mesh feature activates support for computing the shape dynamically from the mesh attached to the same entity.
butcollider-from-meshis not a feature
it is, according to the feature table
$ cargo add avian2d --features collider-from-mesh
Updating crates.io index
Adding avian2d v0.5.0 to dependencies
error: unrecognized feature for crate avian2d: collider-from-mesh
disabled features:
bevy_diagnostic, diagnostic_ui, enhanced-determinism, f64, parry-f64, serialize
simd, validate
enabled features:
2d, bevy_picking, bevy_scene, debug-plugin, default-collider, f32, parallel
parry-f32, xpbd_joints
what are you using colliderconstructor for in 2d?
¯_(ツ)_/¯
just threw stuff at the wall
i just want a collider that updates with my mesh
or at least some way to build a collider from a mesh handle, that i can manually set up to update when the mesh changes
Anybody else getting crashes in 0.6.0-rc1?
I got a bvh related crash a couple of times but I have not been able to reliably reproduce
I think, I got that same crash. Something in the bvh tree regarding a None and .unwrap()
Currently trying to reproduce as well
tips for having my objects not clip through the terrain? (im using ConvexHullFromMesh)
so, i'm a little confused here, still. how do i build a collider (with mass) for a 2d mesh?
i suppose storing primitives in RAM and updating the GPU mesh and converting with Collider::from() is good enough. not sure if there's a better way to do this
I'm trying to use a sensor collider.
I'm trying to make a fan where any entities within the zone have a force applied upon them.
These observers don't seem to work. They're definitely applied.
I've been getting this
thread 'main' (129238) panicked at forks/avian/crates/avian3d/../../src/data_structures/stable_vec.rs:334:13:
no element at index 9 in StableVec::index_mut
but.. it's difficult to reproduce because I only run into it the moment the largest portion of my game loads
how do i apply gravity to a rigidbody
gravity resource, gravity scale component, or constant acceleration component
oh
and it's a dynamic body with some mass (if it has a collider then it should have mass by default)