#Avian Physics
1 messages · Page 40 of 1
the latter factors in the GlobalTransform's scale
@vestal minnow do you know if mutating a collider at runtime is supported by parry?
If I'm using Collider::trimesh_from_mesh(&mesh),, is there some automatic way to just not add a mesh, if there are no triangles? E.g. empty chunk. To avoid this error:
Like, match it and add collider::none or something like that if it exists
If I do this instead:
let chunk_entity = commands.spawn((
//,
// Mesh3d(mesh_handle),
MeshMaterial3d(ground_material.material_handle.clone()),
RigidBody::Static,
Transform::from_translation(location),
)).id();
match Collider::trimesh_from_mesh(&mesh) {
None => {
let mesh_handle = meshes.add(mesh);
commands.entity(chunk_entity).insert((
Mesh3d(mesh_handle)
));
}
Some(collider) => {
let mesh_handle = meshes.add(mesh);
commands.entity(chunk_entity).insert((
collider,
Mesh3d(mesh_handle)
));
}
}
It still crashes with the exactly same error. Why?
I'd PR that to Avian directly TBH
A panic there is just not sensible
Collider::trimesh_from_mesh doesn't make any simplifications for the collider, right?
Not that I know of, but better check the code in case
At least for my meshes, it always looked like a 1:1 match
Just be aware that trimeshes are hollow
Hmm... I can't have that. I have 64x64x64 chunks
It would be like one big lag fiesta
There’s a voxel collider FYI if you need that
Whats that? Where is it?
Apparently "cannot borrow data in dereference of SharedShape as mutable
trait DerefMut is required to modify through a dereference, but it is not implemented for SharedShape"
collider.get_mut(entity).unwrap().shape_scaled().as_convex_polygon_mut().unwrap().points();
Do you maybe know which pull requests contains some info about it?
I think its this one
https://github.com/Jondolf/avian/pull/761
I'm always so impressed by how stable avian is
situations where I'd expect the physics to freak out, it just resolves it calmly
bevy excellence™
Today I discovered that the (avian/serialize feature) serde implementations on marker structs like Sensor change the required serialization format from:
{ "avian3d::collision::collider::Sensor": {} }
to
{ "avian3d::collision::collider::Sensor": null }
The information about alternative serializations is generally not available in the reflection information, so my first question is:
What is the purpose of the serialization feature and is this change in format intentional?
looks like it's just a #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))] on Sensor, no intention beyond a conditional derive
yeah, I was asking more why the feature exists at all. What's the intended use case?
feature-flag serde impls on most types
if there wasn't a feature, serde would always be pulled in, and a chunk of compile compute would always be used, even if the user crate doesn't use serde
sometimes extraneous derives even bloat the final binary somehow
I understand what serde is, what a cfg flag is, and what that's doing;
The question is why, not what. To clarify, the serialize feature breaks reflection based use cases attempting to seemingly duplicate the functionality of the reflection infrastructure.
the serialization changes when the feature is enabled, and that change breaks one feature (reflection) in exchange for what seems like the same feature but with less capability
it sounds like it's a bevy_reflect (or serde?) issue; why would #[reflect(Serialize)] break reflect's serialization?
if you're interested in why I'm asking, for more context, I left a message in #reflection-dev that also covers this topic: #reflection-dev message
reflect(Serialize) hides the serialization mechanism behind serde's implementation (or really, any arbitrary choices). So a consumer who is trying to use the reflection information for a struct no longer has the correct serialization information to produce a valid value
A similar example is glam's Vec3, which is a struct with x, y, and z fields, but implements serde to make that an array serialization. This information is unavailable to consumers so you can not produce a valid value that is accepted as a Vec3 (the consumer only has the information to produce the struct variant of the serialization)
seems like semver prevents that being too much of an issue?
that comment would suggest that reflection users should hardcode the arbitrary serialization logic for every third party crate, for every version of that crate
which is not really a scalable solution imo
more like, using the same version to ser and de at arbitrary times
from other languages?
clients written in javascript and python have to handle producing these values
i didn't know that was part of this
yeah, "reflection user" includes any client who needs to say, produce a valid component value from the introspected reflection information
so inspector use cases, or in my case a blender addon
BRP exposes the reflection information for the types, but serde's serialization isn't part of that information
this is getting very offtopic
can still just sync versions between interfaces, though
you can't though. I don't think serde's serialization can be exposed that way since they can be arbitrary code
in any case, the core question I was asking earlier is "why does the serialization feature exist", because I'm considering suggesting that the ecosystem and upstream no longer uses it
it currently seems like an anti-feature
- People wanted it https://github.com/Jondolf/avian/issues/243
- Upstream Bevy has it, implemented the same way
- Some types like
Collidercan only properly support Serde (because of Parry) and not bevy_reflect
yeah I figured 2) was a reason. If I'm not incorrect, 1) is already handled by Reflect implementations which support serialization through serde by default (although I have no idea if that was true in 2023) and don't need custom serde serializations.
I'll note 3 down. that's presumably because parry uses dyn traits under SharedShape or something similar?
- is already handled by Reflect implementations which support serialization through serde by default (although I have no idea if that was true in 2023) and don't need custom serde serializations
So you don't needreflect(Serialize, Deserialize)to support serialization/deserialization?
nope. The reflection example doesn't use them either afaik: https://github.com/bevyengine/bevy/blob/94bb6e158535f6f484c7750bf84a274e67766656/examples/reflection/reflection.rs#L90-L94
Okay interesting
What is reflect(Serialize, Deserialize) for / what does it do then 🤔
I'm not 100% sure tbh. I've only ever seen it in reference to serde's Serialize/Deserialize types, and the ReflectSerialize ident would be for serde too.
but SerializationData is already automatically registered, so I think the Serialize stuf is just serde and not serialization in general: https://docs.rs/bevy/latest/bevy/prelude/derive.Reflect.html#default-registrations
The main derive macro used by bevy_reflect for deriving its Reflect trait.
Mm yeah
It seems like the serialize feature stuff is mostly unnecessary for Avian then, but I'll probably keep it around until upstream Bevy chooses whether it's necessary
I'm not really familiar with the details of reflection and serde stuff, and in general I try to follow Bevy's upstream conventions and design for this sort of stuff
yeah, my plan right now is to make a suggestion via PR to upstream with reasoning and a brief survey of ecosystem usage, so knowing Avian's usage was very helpful for that
taking serialize off of the marker components would fix a bug a skein user has right now, but my current plan is to hardcode a fix so as to not put presssure on avian to make/release the change
that's presumably because parry uses dyn traits under SharedShape or something similar?
Yeah it stores anArc<dyn Shape>, and I'm not sure how bevy_reflect and serde deal with dyn types like that. But the reason is moreso just that Parry's types don't implementReflect, so we'd need some remote reflect shenanigans or something
yeah, and with ColliderConstructor the need to adjust the Collider stuff is less necessary anyway
@snow urchin Collider has a shape_mut method to mutably access the underlying Parry shape. I don't remember if this was in 0.3 yet, or if it's just on the main branch
However, not all shapes in Parry can actually be transformed or edited
For example, you cannot modify the vertices or indices of a TriMesh
Why
It's not just a vertex buffer and index buffer, it also stores a Qbvh, pseudo normals, topology information, connected components, etc.
All of this must be updated
Just update?
There could probably be some API for this, but Parry doesn't have that
There are some methods like TriMesh::append to append a second triangle mesh to it, or TriMesh::reverse to reverse the orientation, but I'm not seeing any methods to remove or transform individual vertices
there are no other "fully featured" collision detection libraries in Rust currently
hopefully my WIP crate Peck when I get time to work on it more
Dammm, you work hard Jondolf
Wait Ragdoll is possible rn with Avian?
Possible yes, I've made a 2D ragdoll once and I think some people have made simple 3D ragdolls
I see, thanks jondolf
hmm I don't think #[reflect(remote = SharedShapeWrapper)] would even work since it requires all fields to be public and to be a 1-to-1 match
the wrapper needs to be unsafely transmutable to SharedShape
when i spawn a hidden scene like this, everything is fine
commands.spawn((
SceneRoot(asset_server.load("models/ammo-box.glb#Scene1")),
ColliderConstructorHierarchy::new(ColliderConstructor::TrimeshFromMesh),
Visibility::Hidden,
));
but when i add rigidbody::dynamic, scene become visible. why is that?
@vestal minnow this got a bit buried #1124043933886976171 message
I'm working on an impl, don't want to get too far in just to hear it's not something Avian wants. Does this look reasonable?
So this would be basically like adding a child collider for the ball to act as the "collision proxy", except that the proxy may move in a different frame of reference than the ball? For example if the body was moving left into a portal and the other side of the portal points up, the "left" movement would be treated as "up" movement for the proxy, and vice versa
That seems quite difficult to implement properly since it's not enough to just transform positions and contact data and whatnot, you need to consider things like velocity, which is a per-body property, not a per-shape property
Exactly
I was thinking the proxy could have its own e.g. LinearVelocity compliments, and the user is responsible for updating them, rather than trying to automatically populate them
That would allow a lot of latitude in what the feature could be used for
I think I'd prefer this to be done in user-space and not built-in, though we could have an example for it
Could this be done in user space? I'd love that actually
I just assumed that'd be hard/impossible/result in duplicating tons of avian code
Mm I imagine it's possible to implement some version of it, though I need to think through the implications more
(brb need to be afk for a bit)
Ik you're busy, I'm certainly not asking you to solve this for me, a good starting point would save me a lot of time though! (Plus a bit of guidance here or there if you have the bandwidth)
So for a Portal-like portal, my intuition would be to start with this sort of approach.
At every fixed update:
- If a body overlaps a portal, create proxy body on exit side
- Write source body transform and velocity to proxy, transforming based on the portal
- Simulate physics like normal, treating the source body and proxy body as independent physics objects
- Compute total impulse applied to proxy body as
(vel - prev_vel) / delta_secs, and apply it to the source body - If the center of mass of the proxy has crossed the portal, promote it to the source body
- If the source body no longer overlaps the portal, remove the proxy
This approach shouldn't need any changes to Avian internals, you just treat the source body and proxy body as their own objects, but sync the source transform and velocity to the proxy each frame, and write back impulses applied to the proxy to the source body
It may not be perfectly accurate since it's not integrated into the actual solver or substepping loop, but I would suspect that it's "good enough" for most cases
I feel like actual two-way syncing for individual contact impulses and whatnot between the source body and proxy body would be too expensive and add a lot of complexity that I would prefer not to have for our internals
For more fully featured portals you may also need portal-aware joints and spatial queries, which will be its own challenge
When I try that method it says it doesn't exist.
yeah it's not in 0.3 but it does exist on main
https://github.com/Jondolf/avian/blob/main/src/collision/collider/parry/mod.rs#L542
hmm though I guess this does have some edge cases and makes things more annoying
for example you only want gravity for the source body
otherwise, you'd have double gravity, and also if you had the portal exit pointing downwards, you'd get sucked in as soon as you overlap the portal even a little bit, which you probably don't want
I guess you do kinda want a single body with just a collision proxy on the exit side
I'll give it a try. Definitely feels like it won't end up as robust as first-party though.
Also, two-way syncing? My thought was to just bypass the proxy object and generate contacts directly between the non-proxy bodies
aka if body A collides with proxy B, we generate a single contact between A and B, rather than (A, proxy(B)) and (B, proxy(A))
Yeah that makes sense
I would probably be down for first-party support as long as it doesn't add too much complexity or make the general case (no proxies) slower
I think you'd probably need to mess with the ColliderTransform, AABB updates, and narrow phase velocities
This is about what I've started into, good to know I was on the right track! Like I said I'll try the non-invasive solution first. If that doesn't work, I'll build it into the engine, and no pressure to merge it. I suppose considering how sparse reference material is as far as this goes, it is pretty niche. 🤷♂️
Who knows, maybe the impl won't be too complicated, but if it stays on a fork, that's not the worst thing
Are position <> transform only kept in synced via the SyncPlugin? (i.e. in the schedule provided to the sync plugin)
or are there other places? (like in PostUpdate)?
I see that we have
app.register_required_components::<Position, Transform>();
Do we also have the reverse?
that seems like an unrelated line of code
So next update?
Is there a way to define something like a global maximum velocity?
(My player keeps getting knocked out of bounds 🥹 )
Yes
MaxLinearSpeed on the bodies whose velocities you want to limit
The maximum linear speed of a rigid body, clamping the LinearVelocity, typically in meters per second.
Shortest jondolf message
Ye
Breaking his own record
On the main branch it's done by the PhysicsTransformPlugin, running in the schedule provided to it (defaults to FixedPostUpdate)
Note that the main branch also has hooks that compute the global physics transform from the Transform right after spawn, whereas previously this was handled by a system
In 0.3 it was messier, but yeah there it was done mostly by the SyncPlugin. I think the PreparePlugin handled computing initial transforms though
Avian doesn't run any systems outside the schedule given to PhysicsPlugins, excluding maybe some visual things like debug rendering
By global physics transform you mean Pos/Rot?
So the only sources of sync are:
- hooks for Transform -> Pos/Rot
- required components for Pos/Rot -> Transform
- systems in
PhysicsTransformPlugin(usually FixedPostUpdate)
I see cases where my entity's Transform doesn't match its Position, even though I have a system in PostUpdate that sets the Transform from the Position. Still trying to figure out why
Yes and yes. Or more specifically
- Hooks for Transform <-> Position/Rotation
- Systems in
PhysicsTransformPlugin - Optional user-driven manual sync anywhere via
PhysicsTransformHelper(this is new onmain)
The hooks are kinda confusing but right now it initializes Position/Rotation based on Transform, unless the user has manually specified Position/Rotation, in which case those override the Transform instead. I might change it to just always use the Transform though
The required components just make sure that every entity with Position/Rotation has Transform if position-to-transform syncing is enabled
thanks
Thanks
"cannot borrow data in dereference of SharedShape as mutable
trait DerefMut is required to modify through a dereference, but it is not implemented for SharedShaperustcClick for full compiler diagnostic"
avian2d::collision::collider::parry::Collider
pub fn shape_mut(&mut self) -> &mut SharedShape
fixed for now
How can I avoid a SpatialQuery::cast_ray from matching with the origin? I need to use the filter: SpatialQueryFilter? or is there a more elegant way
use the filter, yes
&SpatialQueryFilter::from_excluded_entities([origin]) i believe
Hello, does ColliderConstructor::TrimeshFromMesh also generates collider for other scene roots that are childrens of the entity ? If yes is there a way to have it not do that ?
bump btw, curious why it happens
Also I couldn't find a spring joint, is it a thing in avian or should I make it myself
Apparently
let points = collider
.get_mut(entity)
.unwrap()
.shape_mut()
.make_mut()
.as_convex_polygon_mut()
.unwrap()
.points();
Doesn't give you a vector to push new points/indices in, so I might need an rc vector and edit it that way
i think "add a point to this convex hull" is going to be something more like fn append_polygon(shape: &ConvexPolygon, additional: &[Point<f32>]) -> ConvexPolygon { ConvexPolygon::from_convex_hull(&shape.points().iter().chain(additional).copied().collect::<Vec<_>>()) } + a core::mem::replace
(apparently this operation makes like half a dozen vecs??)
In which case if what I said works it would probably be faster
there aren't any mut methods on ConvexPolygon
Well what I mean is I would put the vectors you first give to the colliders into an rc and then clone it into it
Then you can edit it while it's in the collider right?
the best you can do is skip the convex hull op and use from_polyline
the vecs are all parry internals
As in Collider::from_polyline?
"no method named from_convex_polyline found for mutable reference &mut avian2d::parry2d::shape::ConvexPolygon in the current scope"
... might be too new lol
No choice but to place hold by replacing the Collider with another then
yes, that was already the case, there's no ConvexPolygon::*(&mut self,..)
points is already ordered
points that is
Btw, added basic support for Avian to my FPS controller 🙂 https://github.com/qhdwight/bevy_fps_controller/pull/53
It seems a little more jittery than Rapier, but might be because Rapier is doing some form of interpolation by default
does it go away when you use the interpolation components described in https://docs.rs/avian3d/latest/avian3d/interpolation/struct.PhysicsInterpolationPlugin.html?
it may even be appropriate to add TransformExtrapolate only to the render player
nice FPS controller by the way, it works well and is very lightweight
Does this work?
&mut SpatialQueryFilter::from_excluded_entities([shooter]),
I use this and the in the logs i can see that the target that was hit is still the shooter
does your shooter have multiple colliders
it might have child colliders, yes
could it be that it hit one of the child colliders instead?
but then shouldn't the hit_data.entity be the entity corresponding to the child collider?
yeah...
this never happens to me though, maybe you did something incorrectly?
I'm doing something like
if let Some(hit_data) = query.cast_ray_predicate(
hitscan.start,
Dir2::new_unchecked(direction),
HITSCAN_COLLISION_DISTANCE_CHECK,
false,
&mut SpatialQueryFilter::from_excluded_entities([shooter]),
&|entity| target_query.get(entity).is_ok(),
) {
let target = hit_data.entity;
info!(
?hit_data,
?shooter,
?target,
"Hitscan hit detected"
);
}
and I get
Hitscan hit detected tick=Tick(7984) hit_data=RayHitData { entity: 258v1#4294967554, distance: 20.000002, normal: Vec2(0.1064226, -0.994321) } shooter=258v1#4294967554 target=258v1#4294967554
let me double check
ah you're right i was doing something wrong
the normal vector should be normalized?
maybe not
I was intercepting the spatial query and was doing some custom stuff on top of it
funny that i often instinctively leave the filter empty and do entity != shooter && target_query.contains(entity)
The docs on the predicate are wrong, no?
/// - `predicate`: A function called on each entity hit by the ray. The ray keeps travelling until the predicate returns `false`.
/// // Cast ray and get the first hit that matches the predicate
/// let hit = spatial_query.cast_ray_predicate(origin, direction, max_distance, solid, &filter, &|entity| {
/// // Skip entities with the `Invisible` component.
/// !query.contains(entity)
/// });
it seems to be that the ray keeps travellign until the predicate returns 'true'
Yes, I think it does, just tried it. Good call
Might do a small update
Thanks!
@vestal minnow Is a fluid solver on the agenda?
in the future that is
There is github issue https://github.com/Jondolf/avian/issues/265
omg it's my issue
why "peck"
nice short name available on crates.io, not already occupied by any other related project, and related to birds hitting things
pairs nicely with Avian
(and yes I'm aware that "peck" can mean other things too like giving a kiss :P)
well yeah I was more wondering why you were keeping up with the bird thing since it sounded like Peck wasn't really a bevy thing.
used in avian sure but a separate and generic rust collision lib
but I guess if avian is a bird thing then makes fair play
It's not tied to Bevy, and can be used as a generic thing, but it is still driven by the needs of Avian (and Bevy) and does use e.g. Bevy's primitive shapes and math types
Is this for replacing parry? I heard someone talking about this...
can the colliders give each other a kiss?
😖
features = ["enhanced-pecking"]
good candidate for a collision detection example
Should we implement that before or after the bread phase migration?
Hi. Godot has some issues with implementing Gltf physics extension:
Known issues
Godot Physics does not support mesh-mesh collisions; this plugin will create meshes whenever the input file has requested them, even if it may result in a collision pair which is unsupported by Godot.
Godot constraint spaces are parameterized on a single world-space transform (rather than specifying a coordinate system in the space of each body), which implies that the pivots of both bodies are aligned at scene load. When this is not the case in the input file, we lose information about the pivot on body B.
Will we have similar issues?
Avian supports mesh-mesh collisions, and also joints support local frames on each body as of #803
Hello, i'm working on my car controller still, it's getting there but it sometimes freaks out, i'm sanity checking all of my code, and i'm curious of this:
fn get_point_velocity(linear_velocity: Vec3, angular_velocity: Vec3, point: Vec3) -> Vec3 {
linear_velocity + angular_velocity.cross(point)
}
Is the point supposed to be global space or local space ?
In my head it's local space since the velocity and angular velocity are local afaik but I could be completely wrong.
(this is for getting the velocity at a point of a rigidbody)
should be in whatever space the inputs are in
The point does need to be relative to the centre of mass, but yeah, the rotation of the frame doesn't matter (so long as it's the same for all 3 inputs) (and the output will be in the same frame ofc)
Velocity is in world space
you can convert to local space by transforming by the inverse rotation
On first glance the world_axis calculation looks a little suspect - I think .down() is already rotation * -y so the end result will have the transform's rotation in it twice. Try just let world_axis = object_a.down();?
Thanks, that is correct, I deleted my code because I'm going to rewrite a lot of it to go back to raycasts
2d is all I need, so that would be perfect. I might be willing to contribute to a gpu prototype if need be, because it's imparative for a functioning ecosystem.
Well, Unity doesn't have official fluid sim, and neither does Godot :P but yeah a good fluid simulation crate for Bevy would be nice
There's so many different approaches to fluid sims too, depending on what properties you want
In my game for example I'm gonna specifically want to simulate water flows in some performant way. But some games want a fill volumetric thing. Others just want boyuancy + waves ... Would be hard to get this right in 1 crate
Buoyancy is definitely something I'd like to add to Avian, it just needs some geometry stuff to be added to Parry (or Peck if/when we switch to it)
SPH, FLIP, MPM, position-based fluids, etc. are better implemented as separate crates with an Avian integration for rigid body coupling though
What do these abbreviations stand for lol
Smoothed Particle Hydrodynamics, Fluid-Implicit Particle, Material Point Method
there's also a bunch of sub-variants like DFSPH, IISPH, XSPH, WCSPH...
Oh and then there's liquidfun's approach, which I think is not quite SPH but its own thing? I'm not sure how exactly it works
it was last updated 8 years ago 
They have slides here
https://docs.google.com/presentation/d/1fEAb4-lSyqxlVGNPog3G1LZ7UgtvxfRAwR0dwd19G4g
I know this sounds weird but is there a contain method that checks if a vector is inside a collider?
Ah there is contains_point
Yea, or point_intersections if you want it at the SpatialQuery level
Requires non-hollow shapes though I think
Interesting pfp
You mean clippy #4298?
Idk what is the hashtag or what does that meam i just menbered you used an anime pfp
Correct
-# See https://www.youtube.com/watch?v=2_Dtmpe9qaQ if you don't know why the clippies
Another question woudl that srill work with the collider does not exist?
If the collider hasn't been spawned you'd need the contains_point approach at least
thank you friend you are friend
Does setting gravity to 0, with GravityScale(0.) removes solver body from the entity?
Nope, if it did then you wouldn't have any physics for that entity
(collisions, joints, forces, etc. wouldn't do anything)
Weird. If I add GravityScale(0.) to my entity, then my queries that use SolverBody doesn't pass. Same happens if I add some small value, e.g. GravityScale(0.00000001). But, if I set it to e.g. GravityScale(1.0). Then everything is fine
I'm guessing it's marked as Sleeping since the velocity is so low and the body is effectively resting
This "removes" it from the simulation by removing SolverBody until something wakes it up
How can disable sleeping?
You can add the SleepingDisabled component
I'm curious why you're querying for SolverBody? Running some custom logic inside the solver?
I need velocities
If this is outside the solver then you should just use LinearVelocity and AngularVelocity, but yeah inside the solver you'd access the SolverBody
That worked. Thanks
can multiple collisions be handled at the same time?
This might sound weird but is it possible to check out if two colliders are overlapping each other, even if they dont technically exist (arent spawned)?
There should be, hold on let me check if I can find what it is
I think this is what you're looking for: https://docs.rs/avian3d/latest/avian3d/collision/collider/contact_query/fn.intersection_test.html
hmm
Hello, a bit of a math question but i'm wondering if there are built-in tools to solve it:
Is applying forces tied to the mass ? For example if I have a vehicle at a velocity of 100 m/s, if I want to apply a wheel resistance of 20% of it's velocity, do I need to take mass into account and what would be the best way ? (also I would probably have to multiply the 20% by delta_secs no) ?
I know some engines have some way to apply force regardless of mass or smth
Force times mass is acceleration, so you can just apply acceleration. That'll automatically scale by the timestep.
- force: delta-v respects mass and time interval
- impulse: delta-v respects mass
- acceleration: delta-v respects time interval
- velocity: direct delta-v application
How would I apply acceleration ? By directly changing the velocity ?
Mmmmm yeah I misremembered a linear acceleration component. Ok, in that case you either directly modify velocity after dividing by timestep, or you... apply force after multiplying by mass 😬
So yeah. Probably just apply force, taking target mass into account
But you don't need to worry about timestep that way
(note that on the main branch we do have APIs for applying acceleration, just not in 0.3)
will it realease with 0.17 ?
That's the plan ... Who knows if Jondolf will be able to fix the many bugs on main in time though 🤣
yeah that's the plan, we'll see when 0.17 releases
Though I guess islands isn't on main yet so that's less bugs on main 🤔
I believe 0.17 should be at least two or three weeks away still, considering even the RC isn't out yet
but I'm guessing the RC will come early-ish next week
Minimum for RC -> release is 2 weeks iirc
(also... I just made the mistake of installing silksong
)
Oh no ... I guess we'll have to hope cart does the same and delays the RC 
i am curious how is it possible for a collision event to start
but not have a secondary body
it is a ghost collision?
oh I just realized I did a play test on the islands branch 😬
nothing crashed though 👍
Damn that's crazy, my game literally crashes consistently when I do totally normal actions, and that's just on main 
wow, really? hmm, yeah, I'm on simulation-islands 🤔
I only see crashes when I have meshes go slightly into each other... but those were like.. static geometry that were overlapping. I had it crash while running with an island error one time otherwise
Math question convertin lin vel to dir woudl give me the direction that mesh is going?
going from Vec to Dir only normalizes (sets vector length to 1), so they both contain "a direction" in the loose sense
you could use one of the Vec3 (or 2) normalize functions if you want to keep the type
So converting my bullet limvel would give me the direction that iscflying towards
this is a common way to represent a direction yes
its unclear to me what you're using this answer for, but its worth noting that if you have a bullet's linear velocity, then you already have the direction its moving it. Its the linear velocity vector. normalizing that won't change the direction its moving in.
i want to project where my bullter is gonna be
I'm looking for a solution to interpolate Transform on a listen server (when the server is also a client).
bevy_transform_interpolation looks like a perfect fit. However, it seems to trigger change detection every frame, which is problematic because it causes networking crates like bevy_replicon to replicate the component even if it hasn't actually changed.
It's possible to replicate a custom position/rotation component instead, but that’s quite inconvenient.
Would it be possible to add an option to bypass change detection during interpolation to make the crate compatible with networking crates?
that'd break GlobalTransform and therefore rendering
#math-and-physics message
Hello, this is not a problem with avian itself but i'm stuck trying to make my car controller's traction work so i'm curious if anyone can help (since i'm using avian).
Ah, right 🤔
Maybe it's worth treating Transform as purely visual in those cases and just replicating another component(s), such as Position/Rotation from Avian.
So no changes needed to support this use case.
In networking, we also need interpolation between network ticks for clients. I can create my own backend that writes replicated values from history, but I also need a way to control the overstep value.
@vestal minnow, would you be open to extending the crate to support this use case, or would it be out of scope?
I would be open to this
I suppose it'd either be some OverstepFraction resource or alternatively some t value on the easing state components, and then there'd be some configuration option to update it automatically (using Time<Fixed>) or manually with your own logic
Great!
What your plans with this PR?
https://github.com/Jondolf/bevy_transform_interpolation/pull/10
Asking to avoid possible merge conflicts.
Not sure when I'll get back to that, it was mostly working in my testing but it caused some weird problems for someone who tried it, so I left it for now
So yeah you don't have to worry too much about conflicts there
Thanks, I'll start experimenting then!
bump, been stuck for days
How can I serialzie a collider at runtime?
I have a level editor where players can draw physics lines and save the file.
I see that a ColliderConstructor seems like a fit, however, as soon as it is spawned, it is deleted and replaced with a real Collider. I want to actually KEEP the ColliderConstructor so that when I serialize my scene, whoever loads the scene will get the collider
It feels like the only solution I have would be to implement a wrapper around ColliderConstructor, which feels like an ugly alternative.
Moving a kinematic body will convert it is transform to linear_velocity correct?
That means independently of what dynamic body type you have
You always gonna have the trajectory of where it is going, somewhat
That's my understanding
@zinc talon oi
okay
another queston does inserting a collider continously disable collisionlayers fillering?
In my case, I need to set the overstep fraction per entity, because it's possible to receive updates for some entities and miss updates for others. What if I add OverstepFraction component? If it's present, use its value. Otherwise, just take overstep_fraction from Time.
I also looked at the open issues. I agree with https://github.com/Jondolf/bevy_transform_interpolation/issues/13, but I think customization is also important. For example, this use case makes sense to me. I can also imagine situations where someone might want to interpolate position but apply rotation immediately.
What if we store booleans that configure this directly on Transform(Interpolation/Extrapolation)? We could create constants like TransformInterpolation::ALL and TransformInterpolation::NONE. This would allow initializing them like this:
TransformInterpolation {
x: true,
y: true,
..TransformInterpolation::NONE,
}
And I would Default it to transform + rotation without scale.
Another option is to use bitsets, but the name is a bit long, writing something like this would be a bit repetetive: TransformInterpolation::X | TransformInterpolation::Y. But if we rename the components into TransformInterp and TransformExtrap it might be fine. Bitsets also allow us to create a nice constants, like TransformInterp::TRANSLATION. This is probably my fav option.
Any of these ways would allow to keep flexibility (and even increase it, if you agree to split translation to x, y, and z), but reduce the amount of systems significantly.
Please, let me know what you think. If you like the second suggestion, I can PR it too.
BTW, your code is very clean, I like it 🙂
The bitset approach to what should be interpolated is a very good idea in my opinion
An OverstepFraction component could be fine. An optional component has the downside of adding branching to the loop, which may or may not impact vectorization. Might need profiling to check that.
For the axis bitmask, I'm also somewhat concerned by the added branching. I'd like interpolation to have very minimal overhead since people might run it for hundreds of thousands of entities, and it feels like something that should be heavily vectorizable. We could make it branchless and SIMD-accelerated if we used a BVec3A and Vec3A::select, which takes advantage of hardware intrinsics, but Transform translation uses Vec3, not Vec3A :/ Anyway, maybe it'd be negligible or get optimized by the compiler either way. Would again need some profiling to verify.
Aside from performance, I would mildly contest to the idea of supporting interpolation only for specific axes. So far, the only use case I'm aware of is y-sorting, where you want full control over the z coordinate and don't want it to be interpolated; are there any other realistic use cases? For the y-sorting problem, my ideal solution would just be "add Transform2d to Bevy, and handle interpolation for it separately". To me, it seems like the use cases for limiting interpolation to specific axes are primarily scoped to 2D, so I feel like we should implement that as a first-class citizen rather than special-casing 3D to work for 2D.
I think there could be cases where you want to teleport on X axis, but have smooth movement on Y axis 🤔
hmm, yeah that's valid
This are reasonable concerns, I agree.
I'll profile the end solution if you approve the idea 🙂
I think that would work with this PR, not 100% sure
https://github.com/Jondolf/bevy_transform_interpolation/pull/10
I.e. if you sort entities outside of the fixed update? Won't it reset the smoothing though? 🤔
Some people have been wanting to get bevy_transform_interpolation upstreamed in some form, so in general for questions like this I try to consider "would upstream Bevy accept this?"
Interpolating only specific axes feels somewhat niche to me, and I haven't seen it in other engines, which is part of why I'm kind of on the fence there
(also this feels like a #physics-dev discussion maybe?)
I have a small question, i'm currently trying to run some unit tests using avian. But with just Minimal plugins I run into some panics. Are there unit tests laying around somewhere of what pluggins to put to use avian ?
I don't get any errors when running my setup however and I'd like to avoid adding plugins or resources that should be added by Avian.
Here is a snippet of what I'm trying to run
#[test]
fn dies_on_impact() {
// Setup app
let mut app = App::new();
app.add_plugins(MinimalPlugins);
app.add_plugins(TransformPlugin);
app.insert_resource(bevy::scene::SceneSpawner::default());
app.add_plugins(PhysicsPlugins::default());
app.insert_resource(Gravity(Vec2::ZERO));
app.add_systems(Update, track_target);
let target = app
.world_mut()
.spawn((
Collider::circle(1.0),
RigidBody::Dynamic,
Transform::from_xyz(0.0, 0.0, 0.0),
))
.id();
let missile = app
.world_mut()
.spawn((
Collider::circle(1.0),
RigidBody::Dynamic,
Transform::from_xyz(0.0, 0.0, 0.0),
SimpleMissileAI {
target: Some(target),
previous_target_pos: Some(Vec2::new(0.0, 0.0)),
},
SubsystemEngine::default(),
Explodes::default(),
))
.id();
app.world_mut()
.resource_mut::<Time<Virtual>>()
.set_relative_speed(200.0);
while app.world().resource::<Time>().elapsed_secs() < 0.1 {
app.update();
}
assert!(app.world().get_entity(missile).is_err());
}
And I get
Encountered an error in system `avian2d::collision::broad_phase::collect_collision_pairs<()>`: Parameter `ResMut<CollisionDiagnostics>` failed validation: Resource does not exist
You should probably just store the points that make up the line, and then spawn the colliders on load
How much does Collider::compound do ? Does it optimize away redundant vertices and internal faces at all ? If the resulting geometry is concave, how well does that work ?
It's pretty much equivalent to just having separate colliders, except it has its own BVH acceleration structure to accelerate various queries
I see. is there anything in avian that I can use to simplify the geometry before turning it into a collider ? or do i need to rely on third party methods ?
If your shape is a mesh, you can use its convex hull or convex decomposition for the collider. Beyond that, not really; Avian currently uses Parry for its collision shape types, and I don't think it supports simplification like that
Does convex decomposition make an effort to simplify geometry ?
Oh and also trimeshes do support some preprocessing too, mainly to do stuff like remove duplicate vertices or fix internal edges. But that's just for trimeshes
The algorithm is VHACD which produces an approximate convex decomposition. There are some parameters to control the fidelity and quality
I dont really know what a trimesh is, can't think why it would be hollow either
I'm looking to make a game with a ton of bullets flying around, and I'd like to use Avian to handle collisions, but I'm not sure what the best way is to process the collisions. The docs seem to indicate that I should use events for batch processing
So, I have bullets with a collider and collision events enabled. (not sure if I should be using hooks or observers or something else.)
With my current code it feels weird having to check which entity is the bullet and which is the one being hit, so I feel I'm doing something wrong
btw i am working with avian2d if that changes aynthing
A triangle mesh made of triangles, like Bevy's Mesh. Triangles have no volume, they are just "infinitely thin" shapes. And yeah this is specific to 3D
Most of the same things apply in 2D too though, except there is no trimesh collider
Nvm yes there is, I'm actually not sure what that's like 🤔
my bad
But yeah I guess for 2D the main shapes for more complicated geometry would be polylines, convex hulls, convex decompositions, and maybe triangle meshes
I think polylines and trimeshes probably aren't simplified at all (by default at least)
Basically i have a tilemap of squares and triangles and stuff and i just want to combine that into a single collider lol. Was considering compound, but was concerned about how much redundant data would be held in that (redundant vertices and faces)
On the main branch there's a dedicated voxel collider shape that can be good for tilemap collisions like that
V-HACD seems like that is simpliying the geometry and would probably optimize away redundant data right ?
Yeah, kinda. It's not really intended for tilemap use cases though and is more for approximating detailed meshes with approximate convex parts. It may not approximate everything correctly or retain all your desired geometry, and it's also really expensive to run the decomposition algorithm, at least in 3D
I don't think I've tested it much in 2D
(V-HACD is from Parry, not Avian, we just expose APIs to create colliders with it)
vanishes to continue silksong
I can avoid the panic by adding the missing resources manually, but I am afraid that I might break things if the resources are not inserted in the way Avian expects it...
app.insert_resource(CollisionDiagnostics::default());
app.insert_resource(SolverDiagnostics::default());
app.insert_resource(SpatialQueryDiagnostics::default());
I ended up just using this, but I'm a bit confused as to why these are not there in unit test. Probably some #cfg or something
Is ExternalForce 3D only?
How can I have an entity (E) that has collision filters with only one other group (A), but as a trigger to another group (B)? As in, E will collide and bounce off A, and E will not physically interact with B. I want to know when E touches B. I tried a mix of CollisionLayers and Sensor on E but does not seem to trigger an event. Should I be looking at CollisionHooks for this scenario?
Hmm, how hard would it be to implement a collider (for shape casts specifically) that is a cone that uses a different radius for its X/Z and Y axes?
I need a (view) cone that is slim but tall
for floating charactes to go down ramps without hopping is it necessary intervation on our side or does avian deal with that by default?
Character controllers usually contain code for teleporting / snapping the character to a lower position on a ramp
Pretty sure you need that with Avian too, since "hopping" is the realistic response. In real life, you'd try to go down the ramp, but a character controller usually only tries to move horizontally, so it will lift off the ramp
how much worse would round_cuboid be compared to capsule for dynamic collisions?
of a player
#1124043933886976171 message
hi. how would one Pause the physics simulation? i need to wait till all my objects are loaded in before starting things up. and also for pause game...
pause Time<Virtual>
The clock representing physics time, following the Time clock used by the schedule that physics runs in.
@rigid cipher moved discussion here :)
I think instead of an example of a first-person character controller with networking, I would prefer separate minimal examples for a first-person character controller and for a networked scene. This way, the examples are more scoped and focused on a specific thing
For character controllers specifically, I'm also a bit wary of adding more examples for now, until we have an actually good one. The current examples are not very great, and especially the kinematic character should be updated to use something more like a collide-and-slide algorithm. We have a working group for this (link), though progress has stalled a bit / people are busy with other things right now
Like, an elliptical cone with minor and major radii for the base? I think it should be relatively straightforward to implement the support mapping for that and create it as a custom shape
Nope, 2D too
Exactly.
Cool! Is there an example for how to create custom shapes? (On mobile right now, will check myself later)
At uni rn but there's an example for Bevy's Ellipse here
https://github.com/Jondolf/avian/blob/3b711520c90541b84bce570241baafb54245e33a/src/collision/collider/parry/primitives2d.rs#L26-L37
Basically just derive Shape, SupportMap, RayCast, and PointQuery for the shape type, and then you can create a SharedShape from it and convert to a Collider
The support map allows GJK to be used for the ray cast and point query impls (and other queries) unless you want to come up with analytic solutions
The support map is a function that returns the point that maximizes the dot product with the given direction (a support point), i.e. the "farthest point in a given direction" for a convex shape
For a circular cone, it's like this
https://github.com/dimforge/parry/blob/7d81b18bc4820ef6e780a0c9e8baf19522afb1c3/src/shape/cone.rs#L79
Perfect, thanks!
I was planning on the analytic solution since this doesn’t sound too hard
Which trait do I impl for that?
Oh right specifically for shape casts, I... don't think there's a dedicated trait for that
For pair-wise queries, Parry uses the QueryDispatcher trait, and I don't think we support custom dispatchers in Avian right now 🤔
https://github.com/dimforge/parry/blob/master/src/query/query_dispatcher.rs#L53
If you implement SupportMap then it'll use that, but afaik custom implementations would require a custom dispatcher
well at the end of the day I want to ask "what is this NPC seeing" every n milliseconds (higher sampling rate when closer to the player)
I suppose that could also be done with a sensor that I toggle on for just one frame 
Tbh I would maybe recommend just approximating the elliptical cone with its convex hull rather than creating a custom shape, unless you really need it for something
Then it can do everything that convex polyhedra support
Or another possible approach could be to use aabb_intersections_with_aabb to get collider entities overlapping the given AABB region where the elliptical cone should be, and then you can manually run whatever checks you want on them, including a more accurate analytic elliptical cone intersection test
Or the (non-analytic) custom shape with a support map
is there any significant performace hit using ShapeCaster component over doing spatial queries?
Totally makes sense, mine may help improve, I think the amount of networking code would be very difficult for others to understand. So I’d focus on a controller that can easily be networked. Mine also improves on this because it doesn’t use delta time while moving the same distance given the same inputs. If this sounds good to you I can help improve the examples. I’m not sure how to do the collide and slide though
I would also think stubbing out a function where to put send inputs in the .chain() of kinematics would be nice because it needs to go after an accumulated inputs function. But obviously I don’t want to add stuff others deem unnecessary
added one more video showcasing this issue https://github.com/Jondolf/avian/issues/705
Ah, I didn’t think of that! So I manually create a convex hull for it by using one vertex for the tip of the cone and then sampling eg 16 verts on the ellipsis, right?
(I don’t need the cone to be super accurate)
could use a rectangular pyramid or frustrum
How do you do point colliders?
I don't think you can, but a very small circle/sphere could work
if you want to test if a point is contained within some shape, there are methods for that, but yeah you can't just have a collider that is only a point, the next best thing is a small circle/sphere
or a line maybe
I suppose it could maybe be possible to implement a point collider, though I haven't seen that anywhere and it'd be rather cursed
I've seen it in rapier
zero volume, no surface area at all...
inside object
wdym?
Can you link to this? Avian and Rapier both use Parry for their colliders so they are basically the same there
Parry doesn't really have a point shape
and technically you could give it a circle surface
since like a circle it has no sides
a point is just a position in space that has no size or shape at all
yeah
yeah allowing that would break so many sane assumptions 
what are you actually trying to do?
It sounds to me like you're trying to use the wrong tool for the job
Hmm might actually be worth trying if you can make a circle/sphere collider with a radius of 0.0 and whether that works at all
I think that technically works in some engines at least
grid plotting that dynamically allocates vertices to the hitbox of a "grid", based on which points are collided in 4 directions
those "directions" being points
they're attached to a fake cursor
Then it'd be the same as a point, since a point has no radius either
Point projection will either project a point on the closest collider of the scene (QueryPipeline::project_point),
yes in Avian that is basically the exact same, SpatialQuery::project_point
https://docs.rs/avian2d/latest/avian2d/spatial_query/struct.SpatialQuery.html#method.project_point
or alternatively just SpatialQuery::point_intersections
https://docs.rs/avian2d/latest/avian2d/spatial_query/struct.SpatialQuery.html#method.point_intersections
but again that's not a collider, that's just testing if a point is contained in some shape like I mentioned earlier ^
understood
Anyone wondering about this: I ended up using CollisionHooks
How do I put in a component into "with_excluded_entities" from SpatialQueryFilter?
You can't but if you iterate trough the results you could run a query on each hit to see if it has your component. Or alternatively make use of collision layers
"mismatched types
expected (), found bool"
let directions = ({
//filter out spellradiuses
for entity in spatial
.point_intersections(magic_mouse.translation.xy(), &SpatialQueryFilter::default())
{
if m_matrix.contains(entity) {
return true
}
}
false
},);
regarding return true
Hey! I have been planning to port my game to avian for a while now. Last time I tried it I remember having some issues with rigid bodies that had children with colliders. As that is not a use case explicitly shown in the examples (at least to my knowledge), is it something I can expect to work?
This code seems to work fine but I figured I'd ask before spending a bunch of time on it.
commands
.spawn((
RigidBody::Dynamic,
Transform::from_translation(Vec3::new(0.0, 10.0, 0.0)).with_rotation(Quat::from_euler(
EulerRot::XYZ,
0.5,
0.4,
-0.4,
)),
Visibility::Inherited,
))
.with_children(|parent| {
parent.spawn((
Mesh3d(cube_mesh.clone()),
MeshMaterial3d(materials.add(Color::srgb(0.2, 0.7, 0.9))),
Transform::from_translation(Vec3::splat(cube_size))
.with_scale(Vec3::splat(cube_size)),
Collider::cuboid(1.0, 1.0, 1.0),
));
parent.spawn((
Mesh3d(cube_mesh.clone()),
MeshMaterial3d(materials.add(Color::srgb(0.2, 0.7, 0.9))),
Transform::from_translation(Vec3::splat(-cube_size))
.with_scale(Vec3::splat(cube_size)),
Collider::cuboid(1.0, 1.0, 1.0),
));
});
that pattern should move to the children![] macro
otherwise no problem
if you're just looking for evidence that this pattern is supported by avian, it is documented with example code here: https://docs.rs/avian3d/latest/avian3d/collision/collider/struct.Collider.html#multiple-colliders
Neat! Thanks a lot
I'm having an issue with my physics, I have a capsule collider but it looks like it keeps jumping when it hits an edge
RigidBody::Dynamic,
PlayerMarker,
Name::new("PlayerControlledObject (Avian2D physics)"),
Collider::capsule(4., 4.),
CollisionLayers::new(GameLayer::Player, [
GameLayer::Ground
]),
Friction::ZERO.with_combine_rule(CoefficientCombine::Min),
Restitution::ZERO.with_combine_rule(CoefficientCombine::Min),
GravityScale(GRAVITY_SCALE),
RayCaster::new(Vector::ZERO, Dir2::NEG_Y).with_ignore_self(true),
LockedAxes::new().lock_rotation(),
Transform::from_xyz(50., -50., 0.),
));```
let left = keyboard_input.any_pressed([KeyCode::KeyA, KeyCode::ArrowLeft]);
let right = keyboard_input.any_pressed([KeyCode::KeyD, KeyCode::ArrowRight]);
let horizontal = right as i8 - left as i8;
rb_vel.x = horizontal as Scalar * MOVE_SPEED * time.delta_secs();```
doing anything to apply vertical forces (eg tnua)?
no I don't think so
what's the geometry of the platforms? (debug gizmos may help)
the map physics are being generated by bevy_ecs_tiled
how do I enable those?
A plugin that renders physics objects and properties for debugging purposes. It is not enabled by default and must be added manually.
also probably shouldn't be multiplying your velocity by the dt
if you angle the raycaster does it change
gravity
do you have any code using the raycaster data? like for grounded check or jump input
yeah but i'm not doing anything with it
still work in progress
I can check if the player is grounded, near an edge, etc. but I don't know why being near an edge causes it to jump ?
these gifs are destroying my client
sorry
most people are not on a pixel 2
probably fine
anyway try replacing the level with a single hardcoded rectangle
using a rectangle collider instead seems to have fixed the issue
Is that a polyline collider? Afaik our collision detection library Parry doesn't fix internal edges for those
So you can get ghost collisions
https://box2d.org/posts/2020/06/ghost-collisions/
We need something like Box2D's chain shape, but Parry doesn't have that yet
Assuming rb_vel is an Avian velocity and not something custom, it’s meant to be in m/s, so don’t multiply it by dt
The switch is done and was super straight forward. Thanks for the great API and docs!
Just one small hiccup: I forgot to add RigidBody to the terrain colliders and that exploded the frame time. Not sure why that happened, but here's a trace of what that looked like.
Collision detection isn't done between static rigid bodies, but if they don't have RigidBody, they (currently) will compute contacts between each other
so you probably had a ton of unnecessary contacts being computed
this will most likely change in the near-ish future
avian's docs really are something else, may well be the best I've seen in a crate
Has anyone done pressure plates in avian? I tried but they spaz between pressed/released every frame
CollidingEntities alternates between detecting and not detecting my player entity every single frame/physics tick, causing my pressure plate to rapidly toggle on/off. I've tried sensors, FixedUpdate schedule, and various debouncing approaches but the underlying collision detection is still unstable
have you tried the OnCollisionStart/End triggers?
Yeah 😅
🤔 what does the spawn code for the pressure plate look like?
Oh ok, any current plans to handle ghost collisions?
BTW, regarding Aiden's issue, I have been fighting this same issue for weeks now in my own project. It seems that e.g. using a capsule shape for a player controller collides with different bits of world colliders in each frame, leading to this repeated start/end collision toggling.
It seems like the (unreleased) "contact pruning" commit in avian/main (0aadef0c5267952197d76a51d328fa23ccf8e597) might resolve this. But currently I'm loath to use the branch from git since it's unreleased, and Cargo.toml still claims 0.3.0 so I can't use it with bevy_trenchbroom which pulls in 0.3.1 and conflicts. (And I don't feel like maintaining a fork just to fix the version 😉
Until then, I'm using a "debouncing" layer to consume OnCollisionStart/End events and only emit them to the rest of my app after the moving collider has actually moved more than 0.01 units.
search for "ghost collision" on this discord, there are some tips to avoid them to be found 🙂
capsule collisions are rather imprecise in parry, can confirm 
A floating character controller can help with this
since it's never colliding anyways
Well, I did already work around even that by using a cuboid as the "real" collider (while using the capsule as the static/world collider), but even it falls over (since Avian randomly selects one of the two points to collide). I guess I can make it super-narrow?
thanks, it seems like setting default_speculative_margin to 0.0 might be a solution as long as I don't have any fast moving objects ?
?
Thanks for the insight! I tried denounce as well but was having issues even with that. I'll have another look or try the latest from GitHub
question about cross platform determinism. I see code like this that uses cos
fn mass_properties(&self, density: Scalar) -> MassProperties {
let volume = self.area().adjust_precision();
let mass = volume * density;
let half_external_angle = PI / self.sides as Scalar;
let angular_inertia = mass * self.circumradius().adjust_precision().powi(2) / 6.0
* (1.0 + 2.0 * half_external_angle.cos().powi(2)); // here
MassProperties::new(Point2::origin(), mass, angular_inertia)
}
Does using the enhanced-determinism feature somehow change the implementation of the cos?
yep, exactly
it uses a slower implementation that is guaranteed to work the same on all platforms
how is it changing the implementation? I looked and Scalar seems to just be type Scalar = f64
oh you're right, in that context it cannot change the impl 
Or I guess a trait that is implemented for f32 could be used there?
Not sure honestly
clearly it's linker shenanigans
it may just be a determinism hole?...
in at least one other location libm::cos is used explicitly when the enhanced-determinism feature is set
https://github.com/Jondolf/avian/blob/3b711520c90541b84bce570241baafb54245e33a/src/physics_transform/transform.rs#L244
Yeah that’s what I would have expected 
that was just missed I think, needs to be fixed to use the libm version for cross-platform determinism
It'd be nice to have something like Nalgebra's ComplexField trait
Trait shared by all complex fields and its subfields (like real numbers).
Both for generic math code and for automatically choosing between the std and libm versions based on features
i have a ShapeCaster that is a child of the controller, and the ShapeCaster trails behind the controller
i already have another ShapeCaster on the controller itself
and it follows the controller 1:1
is there a way to have the ShapeCaster on the child follow the parent 1:1?
@vestal minnow do you need help with the migration? 🙂
I have almost everything done except migrating to the new Parry BVH stuff for the spatial query pipeline
@visual sparrow take a look at https://github.com/Jondolf/avian/issues/705 then
Hello, for those that remember, I've been having trouble getting the traction working for my avian physics based car controller for more than a week now, if anyone is interested, you can find the repo and more info in this message:
#math-and-physics message
I'll see if I have time to look at this tonight 👍 (but also if anyone else wants to take a look def feel free)
Oof I don’t know the domain well enough to help with that, sorry :/
So we'll need to change our collision events a bit to work with the event rework. I was thinking that perhaps it'd be best to just combine them into CollisionStart and CollisionEnd events that are used for both the observer API and MessageReader API.
For example, the CollisionStart event would be like this:
#[derive(EntityEvent, Message, Clone, Copy, Debug, PartialEq)]
pub struct CollisionStart {
#[event_target]
pub collider1: Entity,
pub collider2: Entity,
pub body1: Option<Entity>,
pub body2: Option<Entity>,
// flags: CollisionStartFlags, TODO
}
If used with observers as an EntityEvent, collider1 is the event target, while collider2 is the "other" collider. And if used as a Message, it's basically arbitrary which entity is which, like in Avian 0.3.
We could also keep the EntityEvent type and Message type separate, like CollisionStart and CollisionStarted, but uhh.. that naming isn't ideal, and I think it makes sense to combine them
(also in the future I'll most likely force colliders to be attached to bodies to have collision detection work for them, which would remove the Options here)
Especially considering that Cart says one should avoid Event and Message suffixes, it seems impossible to split them with good naming
I am using avian3d when an object is set to Kinematic it passes through the floor if set to Dynamic it stops. I don't see anything in docs about this. To my knowledge Kinematic bodies should respect collisions but not be effected by forces. What could be wrong?
I am using linear velocity to move
Yeah, you do need to manually detect Colliders for a kinematic body. I think it's summed up in this sentence of the doc: Kinematic bodies are bodies that are not affected by any *external forces or collisions*.
"External" means, the world, unfortunately 🙂
kinematic means you are fully in control of its position
so you can put it inside the floor if you want
That is annoying
then dont use kinematic, just use dynamic and use impulses
That is odd. I think every other framework or engine kinematic respects collisions
not really, afaik
I really can't think of any
unity for example
The way they are used collisions are respected. Maybe under the hood they don't and additional logic is provide so that they do
physx you mean
are you sure of that? I also believe that Unreal works the same
yeah this is pretty standard
// Let animation control the rigidbody and ignore collisions.
void DisableRagdoll()
{
rb.isKinematic = true;
rb.detectCollisions = false;
}
detectCollisions is manually turned off
so it can't be Kinematic and respect collisiosn
but all of this doesn't matter
thats for other things colliding against the kinematic rigidbody
kinematic rigidbodies still generate collisions against other things, they just arent affected by them
Does this mean you can get [On]CollisionStarted/Ended events for kinematic bodies interacting with the world, but you have to apply them to the position yourself?
if you want them to solve that collision somehow, yes
But you can also let them not be affected and force the dynamic rigid bodies out of the collision instead
@ArticNative Are you making a character controller? There are some crates to assist with this (e.g. bevy-tnua, bevy_fps_controller which are recently updated)
bevy tuna is not well documented
I need some hand holding here
I would prefer not to use external crates
I don't see it listed but is there a way to freeze rotations on an axis?
I am assuming I could set MaXAngularSpeed to 0
and make mass infinite so that is behaves as if it is kinematic
while respecting collisions
I should take my own suggestions since I am using a dynamic body and not these crates. I use ```
LockedAxes::new()
.lock_rotation_x()
.lock_rotation_y()
.lock_rotation_z(),
Do you set that at spawn?
Yeah, on the RigidBody entity.
That gives me exactly what I am looking for thank you
If I wanted to prevent other forces from acting on them how would you suggest I do that
I think the mass could have problems down the road
You can set the Dominance to a higher value (default is zero)
Dominance allows dynamic rigid bodies to dominate each other during physical interactions.
It will act as if it had infinite mass from the POV of other dynamic bodies colliding with it, but it will still collide with kinematic and static bodies
The bevy-0.17 branch now has the migration to 0.17.0-rc
I still need to update a lot of examples and docs, but it seems to compile at least
(cc @visual sparrow)
I should also rename our system sets to follow the FooSystems convention, though maybe in a follow-up
thanks for the ping!
This means I can port avian_pickup later 
And then rerecast
Good news: migration works!
Bad news: I'm getting this warning:
WARN bevy_app::plugin_group: You are replacing plugin 'avian3d::dynamics::solver::schedule::SolverSchedulePlugin' that was not disabled.
I don't think I actually am doing anything disallowed with that plugin? To my knowledge, my crate internals never add any Avian plugins, and my examples just add PhysicsPlugins
Hmm my Cargo.lock also exploded in size for some reason (+ 600 lines)
ran cargo duplicated-deps and... what?!
yes, I ran a cargo update before. I didn't check how it was in 0.16, but something looks mighty wrong here just at the first glance 
use the force, luke
@vestal minnow what do I use instead of GlobalAngularInertia now?
Just AngularInertia?
Or I guess ComputedCenterOfMass?
This is the context (I'm migrating tnua)
#[allow(clippy::type_complexity)]
fn apply_motors_system(
mut query: Query<(
&TnuaMotor,
&mut LinearVelocity,
&mut AngularVelocity,
&ComputedMass,
&GlobalAngularInertia,
&mut ConstantForce,
&mut ConstantTorque,
Option<&TnuaToggle>,
Option<&TnuaGravity>,
)>,
) {
for (
motor,
mut linare_velocity,
mut angular_velocity,
mass,
inertia,
mut external_force,
mut external_torque,
tnua_toggle,
tnua_gravity,
) in query.iter_mut()
{
match tnua_toggle.copied().unwrap_or_default() {
TnuaToggle::Disabled | TnuaToggle::SenseOnly => {
*external_force = Default::default();
return;
}
TnuaToggle::Enabled => {}
}
if motor.lin.boost.is_finite() {
linare_velocity.0 += motor.lin.boost;
}
if motor.lin.acceleration.is_finite() {
external_force.0 = motor.lin.acceleration * mass.value();
}
if motor.ang.boost.is_finite() {
angular_velocity.0 += motor.ang.boost;
}
if motor.ang.acceleration.is_finite() {
external_torque.0 =
// NOTE: I did not actually verify that this is the correct formula. Nothing uses
// angular acceleration yet - only angular impulses.
inertia.value() * motor.ang.acceleration;
}
if let Some(gravity) = tnua_gravity {
external_force.0 += gravity.0 * mass.value();
}
}
}
Also, ExternalForce is now ConstantForce
am I correct in the assumption that ExternalForce used to be on every RigidBody, but ConstantForce isn't?
FYI this block used ExternalForce and ExternalTorque before and I don't think I'm supposed to use ConstantForce 
Otherwise it looks to me like the gravity just explodes?
ComputedAngularInertia, and get the world-space version by calling .rotated(global_rotation)
However you can actually use ConstantLinearAcceleration/ConstantAngularAcceleration if you want to apply mass-independent "forces"
You can also try the Forces API
That one doesn't require manually adding components, and forces or accelerations get automatically cleared
Thing is, I'm not entire entirely sure what this code does 😄
I'm just trying to port it
and in 2D?
In 2D, angular inertia is just a scalar value and doesn't change under rotation. So just ComputedAngularInertia
thx
does forces get cleared in-between fixed updates?
makes sense
Alright, let's see if I can get tnua running
I wish we had an Avian KCC
so I didn't have to port this haha
If no one tackles it before me, I'll have to work on that Avian KCC eventually
Since I need some features beyond Tnua and I'm definitely not patching that
I wait for the day when I can work on fun stuff like that instead of the mess that is all the simulation island and contact graph stuff 
Bevy Jam 0.18 👀
perchance
ah, just in case it's not implicit
I'd be delighted to team up again if you have time 
but also, no pressure, feel free to join another team then if you want 🙂
(or not at all if you don't have time lol)
of course, it's always fun to jam with you 😄 we'll see how busy things are when it's jam time again
yeah 5 months is a long time to plan ahead haha
@vestal minnow just to confirm:
apply_acceleration(a) and apply_linear_impulse(a * mass) are the same, right?
And instead of querying &mut LinearVelocity and Forces in the same system (which gives me a conflict), I should use forces.linear_velocity_mut(), right?
asking because something clearly went wrong here 
forces.apply_linear_acceleration(a) is roughly the same as forces.apply_force(a * mass)
"roughly"?
accelerations and forces: applied continuously across the time step
impulses: applied immediately directly to the velocity
Context: before:
#[allow(clippy::type_complexity)]
fn apply_motors_system(
mut query: Query<(
&TnuaMotor,
&mut LinearVelocity,
&mut AngularVelocity,
&ComputedMass,
&GlobalAngularInertia,
&mut ExternalForce,
&mut ExternalTorque,
Option<&TnuaToggle>,
Option<&TnuaGravity>,
)>,
) {
for (
motor,
mut linare_velocity,
mut angular_velocity,
mass,
inertia,
mut external_force,
mut external_torque,
tnua_toggle,
tnua_gravity,
) in query.iter_mut()
{
match tnua_toggle.copied().unwrap_or_default() {
TnuaToggle::Disabled | TnuaToggle::SenseOnly => {
*external_force = Default::default();
return;
}
TnuaToggle::Enabled => {}
}
if motor.lin.boost.is_finite() {
linare_velocity.0 += motor.lin.boost;
}
if motor.lin.acceleration.is_finite() {
external_force.set_force(motor.lin.acceleration * mass.value());
}
if motor.ang.boost.is_finite() {
angular_velocity.0 += motor.ang.boost;
}
if motor.ang.acceleration.is_finite() {
external_torque.set_torque(
// NOTE: I did not actually verify that this is the correct formula. Nothing uses
// angular acceleration yet - only angular impulses.
inertia.value() * motor.ang.acceleration,
);
}
if let Some(gravity) = tnua_gravity {
external_force.apply_force(gravity.0 * mass.value());
}
}
}
after:
#[allow(clippy::type_complexity)]
fn apply_motors_system(
mut query: Query<(
&TnuaMotor,
&ComputedAngularInertia,
&Rotation,
Forces,
Option<&TnuaToggle>,
Option<&TnuaGravity>,
)>,
) {
for (motor, inertia, rotation, mut forces, tnua_toggle, tnua_gravity) in query.iter_mut() {
match tnua_toggle.copied().unwrap_or_default() {
TnuaToggle::Disabled | TnuaToggle::SenseOnly => {
return;
}
TnuaToggle::Enabled => {}
}
if motor.lin.boost.is_finite() {
*forces.linear_velocity_mut() += motor.lin.boost;
}
if motor.lin.acceleration.is_finite() {
forces.apply_linear_acceleration(motor.lin.acceleration);
}
if motor.ang.boost.is_finite() {
*forces.angular_velocity_mut() += motor.ang.boost;
}
if motor.ang.acceleration.is_finite() {
forces.apply_torque(
// NOTE: I did not actually verify that this is the correct formula. Nothing uses
// angular acceleration yet - only angular impulses.
inertia.rotated(rotation.0).value() * motor.ang.acceleration,
);
}
if let Some(gravity) = tnua_gravity {
forces.apply_linear_acceleration(gravity.0);
}
}
}
oh so it would change behavior if I user the acceleration
lemme revert that
wait it used to be a force
so the acceleration should behave the same now, right?
Hmm I guess it could be expecting a constant force
AFAICT that was how this piece of code worked before
this intentional?
oh I need to deref it, silly me
Yeah I think that looks equivalent to the old code
I guess the main difference is that the old code overwrites the force and torque, while the new one adds to it. But that only matters if there were existing forces that should be cleared for whatever reason, it gets cleared at the end of the time step anyway
Or yeah those two are actually exactly the same in this case
just, more performant to add acceleration directly
internally it turns it into acceleration anyway, so it's kinda pointless to convert an acceleration to a force only to have it converted back again
makes sense, that's what I thought
I also tried a version with constant forces, just in case:
#[allow(clippy::type_complexity)]
fn apply_motors_system(
mut query: Query<(
&TnuaMotor,
&mut LinearVelocity,
&mut AngularVelocity,
&ComputedAngularInertia,
&Mass,
&Rotation,
&mut ConstantForce,
&mut ConstantTorque,
Option<&TnuaToggle>,
Option<&TnuaGravity>,
)>,
) {
for (
motor,
mut linare_velocity,
mut angular_velocity,
inertia,
mass,
rotation,
mut external_force,
mut external_torque,
tnua_toggle,
tnua_gravity,
) in query.iter_mut()
{
match tnua_toggle.copied().unwrap_or_default() {
TnuaToggle::Disabled | TnuaToggle::SenseOnly => {
*external_force = Default::default();
return;
}
TnuaToggle::Enabled => {}
}
if motor.lin.boost.is_finite() {
linare_velocity.0 += motor.lin.boost;
}
if motor.lin.acceleration.is_finite() {
**external_force = motor.lin.acceleration * mass.0;
}
if motor.ang.boost.is_finite() {
angular_velocity.0 += motor.ang.boost;
}
if motor.ang.acceleration.is_finite() {
**external_torque =
// NOTE: I did not actually verify that this is the correct formula. Nothing uses
// angular acceleration yet - only angular impulses.
inertia.rotated(rotation.0).value() * motor.ang.acceleration;
}
if let Some(gravity) = tnua_gravity {
**external_force += gravity.0 * mass.0;
}
}
}
but this one is bogus:
The screen shake here looks like a typical artifact of interpolation not working
but the sliding here is weird
OOOH
On Tnua main that platform is supposed to move
Now I wonder if my migration of the crate is correct and the test playground is just borked
let me try in another project
We really need some builtin solution. Collide and slide or something.
This would help to test Avain before release and help users a lot.
well there was a working group that got pretty far
someone just needs to pick up the bits and pieces
well, that looks fine to me
I blame the playground app then
but not fixing that
HOWEVER
I do get this one here too:
WARN bevy_app::plugin_group: You are replacing plugin 'avian3d::dynamics::solver::schedule::SolverSchedulePlugin' that was not disabled.
and sometimes, but not always, these here when the crates on the right spawn 
2025-09-16T17:41:58.565993Z WARN avian3d::dynamics::rigid_body::mass_properties: Dynamic rigid body 89v0 has no mass or inertia. This can cause NaN values. Consider adding a `MassPropertiesBundle` or a `Collider` with mass.
2025-09-16T17:41:58.566006Z WARN avian3d::dynamics::rigid_body::mass_properties: Dynamic rigid body 88v0 has no mass or inertia. This can cause NaN values. Consider adding a `MassPropertiesBundle` or a `Collider` with mass.
2025-09-16T17:41:58.566010Z WARN avian3d::dynamics::rigid_body::mass_properties: Dynamic rigid body 87v0 has no mass or inertia. This can cause NaN values. Consider adding a `MassPropertiesBundle` or a `Collider` with mass.
2025-09-16T17:41:58.566012Z WARN avian3d::dynamics::rigid_body::mass_properties: Dynamic rigid body 86v0 has no mass or inertia. This can cause NaN values. Consider adding a `MassPropertiesBundle` or a `Collider` with mass.
It's just this:
fn spawn_crate(trigger: Trigger<OnAdd, Crate>, mut commands: Commands, assets: Res<AssetServer>) {
let model_path = Crate::CLASS_INFO.model_path().unwrap().to_string();
let scene_path = GltfAssetLabel::Scene(0).from_asset(model_path);
commands.entity(trigger.entity).insert((
SceneRoot(assets.load(scene_path)),
RigidBody::Dynamic,
ColliderConstructorHierarchy::new(ColliderConstructor::ConvexHullFromMesh)
.with_default_density(ColliderDensity(100.0)),
));
}
which IMO looks correct to me?
so I blame Avian for that warning 😛
yeah I'm not sure why this happens, I've also gotten it randomly sometimes
should be fixed now if you cargo update?
Uuuuh I blame that one on Avian too haha
sure, sec
yep that warning's gone now 🙂
I suspect this doesn't happen when that warning is not present, let me try
nvm
wat
collision handling with the player also seems a bit explosive (note that I did not jump at the end), but I blame Tnua for that
In case you want to play around with it, it's here: https://github.com/janhohenheim/how-i-make-3d-games/tree/bevy-0.17.0-rc
How would you get the ContactManifold for CollisionStarted?
(Since it has less information than ContactPair in Collisions)
Asking because I'm trying to find a way to detect the exact point of collider intersection from a CollisionStarted event
Get the ContactPair from Collisions based on the colliders involved
(via Collisions::get)
Is there going to be a release before 0.17?
I have code that relies on the main branch to work, I am unlikely to be ready to migrate before Avian, should I just use latest hash before main breaks 0.16?
Most likely no release before 0.17
I think I'm going to keep main on 0.16 at least until I've sorted out some of the contact graph bugs and simulation island stuff, and keep the 0.17 migration on the bevy-0.17 branch for now
Thanks!
Also, tangentially related: I've been thinking that I might change some of our "release processes" moving forward, to have things progress at a nicer cadence and to reduce the stress and time drain involved with each release
Namely, smaller releases, more often (maybe aim for 2 per cycle), and also consider finally moving migration guides and release notes to be stored in-repo similar to Bevy
pretty please?
I would like to do RC releases, but that's blocked by Avian
It's fine if it's buggy
Historically I've done just one big release per Bevy version, and tried to squeeze everything I wanted to get done into those releases because big fancy releases look more impressive
but frankly that's hella stressful and I always have way too much work at the end of each cycle lol
Yeah I made the same experience
Nowadays I like to get a release out that is just "old version + migration"
that way the real next release can cook however long it wants
Maybe, we'll see
I really want to get the simulation island stuff fully done and working but Nise's networking problems with it are killing me 
I spent some time today learning more about the basics of game networking to at least understand the core concepts of what's happening better lol
Yeah this just kinda requires doing the migration twice, once for the old version and once for current main
Which in the case of e.g. Avian can often differ quite a lot
oof I believe that
Thank you!
I've made this to extract the intersection locations:
let mut contact_points = Vec::new();
for manifold in &contact_data.manifolds {
for point in &manifold.points {
contact_points.push(point.local_point1);
}
}
contact_points
}```
but it's unclear (to me) from the docs:
1. Why should it matter whether I use `local_point1` vs `local_point2`
2. Are these locations global? Are they relative to the collision entity's transform?
they're relative to, respectively, entity1 and entity2
I see
Thanks
Why do joints have damping set to 1.0 by default? Seems to be a bit annoying and surprising design.
Currently bolting two bodies together with a FixedJoint will slow their movement down.
are you sure? that doesn't sound like what damping should be doing
That's not the case on the main branch, there the damping is zero by default and controlled by the JointDamping component
It should also only dampen the relative velocity of the bodies, so it's a bit weird if it meaningfully slows down the bodies for a fixed joint 🤔
Hello, what is the easiest way to make a ColliderConstructorHierarchy not affect children ? Only making a collider for the scene root contained on the same entity
use ColliderConstructor instead probably
does that have a mesh component option? thought it'd need an observer at least
There’s an system in Avian that reacts to ColliderConstructor and will use its FromMesh options as soon as the mesh on that entity is available 🙂
Is there a recommened way to get LinearVelocity from a child Entity that doesn't have it but has a parent with it (and rigid body) somewhere in the hierarchy?
If that child is a collider, you can query its ColliderOf
Not a collider
You can manually compute the velocity at a point using lin_vel + ang_vel.cross(offset), where offset is a vector from the rigid body's center of mass to the desired point, in this case the child's position
I was cooking this:
fn component_from_ancestor<'a, T: Component>(
start: Entity,
parents: &'a Query<&'a ChildOf>,
components: &'a Query<&'a T>,
) -> Option<QueryItem<'a, &'a T>> {
if let Ok(component) = components.get(start) {
return Some(component);
}
for ancestor in parents.iter_ancestors(start) {
if let Ok(component) = components.get(ancestor) {
return Some(component);
}
}
None
}
that's some cook right there, was what i was writing
nit: iter::once(start).chain(parents.iter_ancestors(start).find_map(|c| components.get(c).ok())
i stole this from jan
If you're just asking for how to get the rigid body's LinearVelocity, and not strictly the velocity of the child (if it is offset) then yeah something like that'd work
fn component_from_ancestor<'a, T: Component>(
start: Entity,
parents: &'a Query<&'a ChildOf>,
components: &'a Query<&'a T>,
) -> Option<QueryItem<'a, &'a T>> {
iter::once(start)
.chain(parents.iter_ancestors(start))
.find(|e| components.get(e))
}
oh hey there it is
Ideally it would be the offset velocity, but that might be good enough in this case
does fixedupdate run before or after update?
before
The schedule that contains the app logic that is evaluated each tick of App::update().
yeah :( I was hoping it was wrong lol
There's no way to tell when colliders have generated is there?
like if you're doing a convex hull or trimesh or whatnot in a ColliderConstructor?
IIRC no one bothered writing an event for it, but I would be in favor of that existing
it doesn't come up that often, but I think that's because people are working around it by basically sleep(frames)ing
Since I preload my models, the colliders are spawned just one frame after the level is spawned. Never needed to sleep.
I have a loading state that checks every frame to make sure all the colliders are loaded
unrelated, but I dropped a PR that seems to get the 0.17 PR into a working state: https://github.com/Jondolf/avian/pull/819
nerd
I can't seem to despawn bullets without it crashing when they collide with something in the 0.17 version. Should I be despawning them some other way?
🤔 I kinda already think despawning can be a bit of a footgun and this might be an indication of an underlying issue in avian, but I personally despawn by adding a marker component (I just call it Despawn) and then I have a system that despawns entities with that component in FixedPostUpdate (with .after(TransformSystem::TransformPropagate) but I honestly haven't checked if that's necessary)
also, there's no 0.17 version published, so it would be useful to specify what branch you're using 😅
avian2d = { git = "https://github.com/ChristopherBiscardi/avian.git", branch = "bevy-0.17-temporaries", features = ["serialize", "simd", "parallel"] }
Cheers! I figured I was doing something wrong. I'll give it a shot after I get home from work. Curiously, it did work in 0.16.
what I wrote is an approach to avoid the issue, but not sure how typical it is. Iirc, a crash can occur if an entity is in the collision graph but has been despawned and it might be a debug assert that causes it.. I've heard good arguments for and against panics caused by things like this.. I don't really know what the general consensus is
It should hopefully be fixed on a local branch of mine, I just still need to properly figure out why/how Nise's networked game crashes
As for why these things panic instead of e.g. emitting warnings, a lot of these bugs can leave the internal structures in invalid states that could completely break collisions and cause things to phase through each other, report non-existent contacts, or otherwise mess things up in a game-breaking way. They're invariants that should never be broken
And to be clear there should pretty much never be crashes, they're just bugs that need to be fixed
I think that's kinda where I'm unsure.. is it a bug if a collision is detected and then one of the colliders gets despawned and then avian starts using the collision graph? is the collision graph supposed to be updated immediately when a despawn happens?
Does that mean onadd collider happens when there is no collider yet built?
No, that works as you'd expect. Chris is asking about something like SceneInstanceReady, i.e. something that says "all colliders for these scene were done building"
(When using ColliderConstructorHierarchy)
Yeah I was actually thinking of it for multiple uses of colliderconstructor too
Ah yes my maps have an event like that
I haven't looked into it at all yet but it's on my list for .. some day I guess lmao
Finally got around to trying this, but it still panics unfortunately. (Same version that I mentioned prior)
For some reason the debug plugin doesn't seem to work properly for me; I'm using
app.add_plugins(PhysicsDebugPlugin::default())
.insert_gizmo_config(
PhysicsGizmos {
aabb_color: Some(Color::WHITE),
collider_color: Some(BLUE.into()),
raycast_color: Some(GREEN.into()),
raycast_point_color: Some(RED.into()),
hide_meshes: true,
..default()
},
GizmoConfig::default(),
);
Is there anything else I need to do?
what do you mean by it not working properly?
Actually I think i didn't have a collider on my entity.
But for example I don't see the raycast_point_color ; is it possible to show a dot at the raycast point of impact?
wd
is there any utility that just gets the min distance between 2 colliders?
Also wondering this FWIW. I know I can hack it by shapecasting one collider sized up and iterating the contact points, but a utility would be nicer
Oooh that’s great, thanks!
In 2D, is there a provided way to triangulate a polygon for convex_decomposition ? I don't see anything obvious
sorry i cant remove the embed
Put < and > around the link 🙂
<https://some_link.com>
Is there any point in removing holes from my geometry ? or will it be fine with a collider with holes produced by convex_decomposition ?
it doesn't care if there are holes, pretty sure it's (at least equivalent to) just taking the hull of all vertices
Also it's parameterized to take edges, rather than vertex indices ? a bit confusing
pretty sure (again) that's basically just an optimization
there's a param struct that makes it possible to have concavity, so that's not a complete picture
regardless the result of a convex decomp is a compound of convex polyhedra
I forgot, what do you call the thing you do to preserve color?
@vestal minnow hella specific scenarion that i got erroring https://github.com/Jondolf/avian/issues/821
I don't understand... convex_decomposition seems to be messing with the triangulation I gave it, generating what is effectively a convex hull of my input. All the holes are getting removed (even though my index buffer should specify how to construct the triangles such that the holes are preserved) ??
Maybe I can just use triangle + compound to get my desired result ?
what are you trying to do? sounds like you just want a mesh collider
what if you randomize the rotation, but leave angvel at zero?
or otherwise check various still states
when two colliders touch, i want to get where they are touching. ive looked at the docs but couldnt find something similar
This. Doing the triangle >> compound method gave me the desired result
the triangles are quite scuffed though
Should add some Steiner points, but i don't know how to get them
do a trimesh instead, there's some kind of internal corner detection
where are you getting the mesh?
wdym
it looks tile-based, so there's something turning tiles to triangles
im generating them with i_overlay and i_triangle
from where?
from the tiled map that I parsed (I use https://github.com/cmorrison82z/tiled_import)
no but lemme explain you more detailed. i have a player collider with kinematic rigidbody and wall with static rigidbody. since i want to do my own player movement physics i need to know if my player is touching a collider and if it does, where is the contact point
see also the module-level docs explaining different methods of reading collisions to see if any of them work better for you https://docs.rs/avian3d/latest/avian3d/collision/index.html
damn thanks
and also avian's kinematic character controller example for similar code https://github.com/Jondolf/avian/blob/main/crates/avian3d/examples/kinematic_character_3d/plugin.rs
When will avian be compatible with 0.17?
Currently getting error hell from avian components
Version is the newest from the github's main branch:
avian3d = { git = "https://github.com/Jondolf/avian" }
there is this branch https://github.com/Jondolf/avian/tree/bevy-0.17
Hmm...
After updating:
avian3d = { git = "https://github.com/Jondolf/avian", branch = "bevy-0.17" }
I get a lot of avian internal errors. E.g.
you probably have multiple versions of bevy installed
try cargo tree -i bevy
I've been using that branch successfully since I made the temporaries patch, which is still the latest commit
is it possible to wake a sleeping body with a sensor?
commands.queue(WakeUpBody(entity))
A Command that wakes up a rigid body by removing the Sleeping component and resetting the TimeSleeping to zero.
hmm, I'm wondering if there's a way to do that with a sensor.. actually not even wake up, just get a collision event. I have a sensor that represents a force field and it expands by modifying it's scale.. but if it hits a sleeping rigid body it doesn't detect that as a collision
I'm wondering if that's an intentional commission or maybe I'm doing something wrong 🤔
since the issue is glam it is best if you do cargo tree -i glam
Hmm
does kinematic bodies use ExternalForces or is it trully only LinearVelocity and AngularVelocity?
Kinematic bodies and static bodies have effectively infinite mass, so forces cannot produce any acceleration for them. The movement of kinematic bodies is entirely controlled by user code, by manipulating their velocity and/or position
I feel like someone asked about something similar recently... creating a collider that is a sensor and scaling it.. specifically to just track what it collides with. If it hits something that is sleeping... is there any way to get what entity that is?
or is this not the right way to approach this problem?
If I have two rigid bodies and I want them in an arbitrary (programmatic) relative position and orientation with a bit of springiness- how do I do that?
The FixedJoint can set an anchor position, but not an anchor rotation - is this an oversight or do I not understand how it's supposed to be used?
On the main branch it supports a full local frame, i.e. anchor point and basis orientation
It was just something that wasn't implemented before
If it's not detecting the collision with a sleeping body then that seems like a bug 🤔 I can test it later today
Hmm it seems in my simple test scene that it does trigger CollisionStarted, but it never detects the collision ending when they no longer overlap 🤔 this happens just for sensors
that's interesting... hmm. Is your test scene like... just altering the scale of a sensor?
Nah it's just the 2D sensor example from the repo, but moving the sensor instead of the character, and having the character sleep
I can try scaling too
same thing when changing scale
oh btw I'm using main for this, are you on the simulation island branch?
hmm, ok, that's good to know. I must be setting up something incorrectly, but I should be able to reference that example. I only really care about the collisionstarted event
yeah I'm using the simulation island branch because it felt more tropical to me
hmmm interestingly everything seems to work correctly on that branch
in my scene
even fixing the bug on main
hah, ok. interesting, hmm. I'll re-check and compare against the example. Sorry about that
No worries, it's very possible there's still something weird going on there so it's good to test things
could also try the sensor with/without a RigidBody, and see if the type of rigid body affects anything
(if it's static then iirc it won't detect other static bodies at the moment)
once we have the BVH broad phase stuff setup, I'll very likely split out sensors to have their dedicated logic separate from "normal" colliders, which should both significantly simplify some internals and also improve sensor perf
post-force-rework, should i prefer accessing e.g. LinearVelocity thru the component itself or via Forces::linear_velocity?
Through the component itself, unless you have conflicting Forces in the same system. The velocity getters on Forces exist just to work around possible conflicts with your system and the Forces param both accessing them
does avian work well having the collider as a child so that the parent entities position is at the ground?
In general, you should consider setting the error handler to log an error instead of panicking
And despawning things in a dedicated despawning system set
That’s not Avian specific though
iirc, Jade had tried that here 🤔
Oh I see
Then yeah, change the error handler to not panic until you figure out something better
It seems like I found a bug? Not sure if it's already known or an error on my side.
Basically, when I put a collider with a sensor as the child of a moving entity and give it a Rigidbody component (important!) then the collider seems to not be affected by the Transform of the child. Any rotation or translation of the child gets reset to 0.0 even if the visible mesh is in the correctly translated place (my usecase is a hitbox for an attack and I use the mesh for debugging, took me a while to understand that the collider isn't aligned with the mesh).
It works fine without the Rigidbody component but then it starts lagging badly the moment it collides with anything so that is not an option.
Here is a picture, the blue box is the correctly translated hitbox visualized by a mesh. But when I put the Rigidbody component on it, the actual collider is exactly on the player character and not translated to the right like the mesh.
I am using Tnua… could that cause some sort of desync between the physics position and the transform?
Will investigate further when I have time
do you have locked axis?
No
But why i need this?
I want my car rotating
but your wheel should only rotate on 2 of 3 axis
?
Im in 2d
If i add locked axis car seems normL
But
I want rotating car
on the wheel rigid body
On the car
I commented line
ok, what do you mean by this then?
They moving left-right
Really
You can run code and thee what they moving left-right and car not moving
?
What do you men
since it is 2d, you want to see the wheels pitch, right? but they are rolling or yawing?
They rotating only one axis
I mean they moving
Like i set torque
And when transform changes
Friction then?
I maybe recorda video
hmm, the joints are very springy
They really moving left right as i sayed
Yes but i wanr spring jointa
I set stiffness like in normal car
And wheels in my car not moving left right
yeah, i've never used joints so i don't know how to set the proper constraints
Maybe creator of physica plugin can help me?
#1124043933886976171 message
ah, no embed on mobile lol
@vestal minnow
If you want a wheel that can rotate, and can only move up and down with some springiness, I think you'd maybe want a combination of a PrismaticJoint (to restrict translation to the local vertical axis), DistanceJoint (to emulate the suspension), and RevoluteJoint (to pin the wheel to a point it can rotate around).
This approach will just need two bodies for each wheel:
- An "axle" body that is attached to the frame of the car with a
PrismaticJoint, and maybe also aDistanceJointfor the suspension. This body does not rotate relative to the car frame, it just moves up and down. - The actual wheel body that is attached to the axle body with a
RevoluteJoint.
Since the axle body exists just to make the joint setup work, it probably doesn't have a collider, so you'll need to specify its Mass and AngularInertia manually
In the future, we might have some dedicated joints to make this sort of thing easier. For example Box2D has a wheel joint for exactly this
https://box2d.org/documentation/md_simulation.html#autotoc_md112
Thanks! Looks like i fixed it
But yeah
Will be cool, if avian have wheel joint
Yeah, there's still a lot of improvements to be made to our joint stuff. It'd also be cool to have some official examples for cars and other vehicles in the repo
On another note, a quick update: Since I've still been struggling to get the persistent simulation island PR working properly with (Nise's) networking, and 0.17 is looming around the corner, I just spent yesterday making it so that you can simply disable the IslandPlugin if it's causing problems. I think I'm going to merge that PR today, iterate on further improvements or alternative approaches later, and switch gears to polish + release prep
Now another problema: if i make suspension too strong wheels can go through ground. For fix i can add collider for axle, but is this good solution?
If collider is normal -> ok
Without collider like 0.2 car always go through ground
If it works with a collider for the axle, then that's fine yeah
I'm guessing it goes through the ground because our current joints can kinda overpower contacts sometimes
When I have the newer impulse-based joint solver working eventually, it hopefully shouldn't do that 🤔
If I add an transform to an entity that has position and rotation, will it inherti the transform? Meaning will it convert position rotation to transform?
AFAIK it should
you wouldnt lie to me would you jan
well, I'm not sure of the facts 😄
I wouldn't bet money on it
well maybe
like uuh
CHF 2.-
I'm like
65% sure it's the case
does that answer it? 
Is it a lie if my sincere belief turned out to be wrong? No, I say 
I bet your favorite pokemon was ratatouille
-# ||Actually it was Blastoise||
||gengar is clearly the best pokemon||
at some point one day, I'd be down to take a stab at something like that
or try to assist at least
yeah I haven't looked into how vehicle controllers work at all, I just know that
- Box2D has a wheel joint and a car sample
- Jolt has many built-in vehicle controllers and samples (car, motorcycle, tank, and more)
- Rapier has a
DynamicRayCastVehicleController
@vestal minnow I need to do some raycasts to nearby lights to get a CPU estimate of the illumination, and I thought I could do that by first doing a sphere or AABB check to gather the lights that are close enough to even be considered. Do you have a tip on how this should be done? I guess I could use the point collider hack we recently discussed to add colliders and collision layers to each PointLight and co. and then do SpatialQuery::shape_intersections with a sphere and the light source collision layer filter.
Would that be a sensible approach, assuming point colliders even work?
If i increase physics substep falling through ground will be smaller
Sounds reasonable
If a "point collider" with a radius of zero doesn't work, you can just try a tiny sphere
@vestal minnow idk if you've seen this 🙂https://graphics.cs.utah.edu/research/projects/ogc/
yeah I'm aware, it was around the same time as AVBD
I've updated the bevy-0.17 branch to latest main (includes simulation islands!), updated docs, removed manual type registrations, and renamed our system sets to the new FooSystems naming convention. That branch is now more or less "ready" for the 0.17 release :)
https://github.com/Jondolf/avian/pull/815
I noticed a bad perf regression for debug builds after the simulation island PR, but I discovered that it's just because it runs some rather expensive correctness validation if debug_assertions are enabled. I just opened #826 to fix that with a new validate feature flag
Will try later! This should fix the boxes morphing into each other, right?
uhh not sure, didn't test that yet
if it was somehow related to sleeping, then probably yeah
Alright, compiling now
Good news: it's fixed!
Bad news: I still get this
yeah that isn't fixed still
Ah alright
When you're touching that part anyways, mind using NameOrEntity in that warn message?
Yeah good idea, there's probably some other places where we could do that too
Interested in some Foxtrot benches?
Sure! Though it's probably not the heaviest thing in terms of physics
definitely not, but I'd say fairly representative of a simple realistic scene
true
though I would love to see how this influences Chainboom with max body parts hehe
simulation islands may help a lot of larger scenes by letting more dynamic bodies sleep properly
yeah I can imagine that it would help all the gibs laying around on the other end of the map
the next big thing would probably be the BVH broad phase, which I'll try to finally get done after the release
hmm I wonder if I could "speak" to the BVH directly for my light query thing
Probably still easier to just have point colliders
@vestal minnow there ya go
some lovely frame times!
Also, the sleeping looks much more stable than last time I checked
You can see that there are two bugged instances though
It's a little bit confusing how non-sleeping dynamic bodies have the same color as static bodies though
because it feels like "strong color = doing computation"
(this is in release mode ofc)
the lamp standing still and sleeping after wiggling around is something I distinctly remember not being possible last time I checked 😄
So it's cool that that works now!
Weird that the comparatively simple cuboid crate doesn't seem to sleep on the flat table
Yeah it's jittering a bit too much. Hopefully I can improve the stability more there, with Peck or otherwise
You can also increase the SleepThreshold to allow them to sleep easier
Can't make it too large though, or you will have stuff like rolling objects stopping abruptly when they should keep rolling
Yup I want to have different colors for dynamic/kinematic/static at some point, and for sensors
In birds, sleep consists of "periods of eye closure interrupted by short periods of eye-opening." During the short periods of eye-opening, electroencephalographic (EEG) studies indicate that the birds are still sleeping; the voltage level in the brain is identical. Birds restore their arousal thresholds during sleep. During their short eye-open ...
JK. Since there are no docs yet for the newest avian, where can I find the SleepThreshold?
Is that on a plugin?
I'd also like to add optional support for rendering colliders as solid meshes, that way you could render the whole physics representation of the world better instead of just seeing overlapping wireframes everywhere
I did exactly that for rerecast's debug visualization if you need some inspiration
It uses a translucent Mesh3d and retained gizmos
oh I see it's a component
I suppose it goes on the collider?
That will fit right into this observer I have anyways 
fn enable_interpolation(
add: On<Add, RigidBody>,
rigid_body: Query<&RigidBody>,
mut commands: Commands,
) {
let Ok(rigid_body) = rigid_body.get(add.entity) else {
return;
};
if rigid_body.is_dynamic() {
commands.entity(add.entity).insert(TransformInterpolation);
}
}
Avian sleep shares two similarities with that of mammals: rapid eye movement (REM) and slow-wave sleep (SWS).
ah I missed that in the docs, remind me to add it
Looked into it some more and yes, when I add a Rigidbody component, the Position component seems to be relative to parent and when I remove it, it seems to (correctly?) reflect the GlobalTransform.
Also something else, when I dont have a Rigidbody component on there it correctly syncs with the globaltransform and thus the sensor collission detection works. But… it starts lagging baad the moment any collission is detected (on 0.3.1 btw)
setting it to 0.45 seems to do the trick, more or less. You can see that it still jitters, but it stops after a moment
is there an intuitive meaning behind that number?
like, does 0.45 have a physical meaning like "0.45 newtons are treated as 0"?
oh it says in the docs
it's velocity
so 45 cm per second are treated as sleeping?
that... doesn't sound right
from eyeballing, this sliding looks like half a meter per second
