#Avian Physics
1 messages Β· Page 15 of 1
OK, well I can always try to figure that out, but I expect I'll just not let it get to that point.
Yea you probably don't really run into this problem with an RTS, you'd need some heavy physics-based gameplay for it to happen
The boxes almost look like they are soft bodies π
I want to make a whole game 1,000,000 units from the origin to get these visual artifacts, but with functional physics
np!
that shouldn't be that hard right?
Just set the transform to 1000000 + position
yep, it'd be super easy
Is this example at 1m? π
I thought you only needed to go like 10k from the origin to get artifacts π
I don't remember how far away this was, it was like over half a year ago lol
Yea for 32 bit floats I would say 1000000 is abour where you start getting errors on 0.1 or more per operation
I'm trying to get a basic physics simulation with buoyancy working for a large "age of sail" style ship. I've managed to make some decent progress, but I'm struggling a bit with CenterOfMass. I think the proper way to do things is by setting ColliderDensity, but I'm generating a collider trimesh from my Ship's mesh (bevy components crate), and I feel like I really need to be able to set the COM really low in the ship towards the keel. If I add a CenterOfMass component on my entity it seems to just be reset I'm guessing by the physics engine at runtime. If I try to manipulate ColliderDensity then the COM is too high up.
Really looking for some advice on how to handle this problem. Using bevy inspector I can manipulate the COM to a lower point on the ship and it seems to float pretty well, but I can't for the life of me figure out how I should be approaching this because it seems like COM isn't intended to be manually adjusted like this.
I think I may be on to a good direction. Looked at the example and I can add a child entity with another collider and set a higher density on that one. It seems like that affects the parent so may work out. Will post back.
when iterating over collisions.collisions_with_entity(entity) can entity show up as entity_1 or entity_2?
Yes, it's one of the two. The order is essentially random at the moment
Gotcha, i worded it crazily but that's basically what i was asking haha
Yeah no worries π
also how's the rebrand/rework going?
Pretty well, I'll probably start making actual PRs soon for all the stuff I've been working on. I still have a few more things related to joints that I need to work on, and I also want to compare the contact solver to other engines a bit more. Then I can focus more on updating docs and examples and doing release prep
I'm aiming for having things ready on the main branch in a couple of weeks when Bevy starts the release candidate phase (a new thing we'll likely try for this release) so that people can try out the new solver and stuff, and then I'll release the new crate once Bevy 0.14 is released
I'll probably do one more release for bevy_xpbd that doesn't have all of the new stuff, and is mostly just a 0.14 update to help people migrate. And the new crate (whatever it'll be called) will have the new stuff
Awesome, really great work btw, after using rapier for a few years I was surprised how much more ergonomic working with xbpd is, it's so nice to have everything take place within the normal ECS world and not have to constantly access a context resource for everything
Same. The only reason I went with this crate is because it's so tightly integrated with bevy, even if it's way less mature than rapier.
It just feels good to use.
It's mature in a different way ... xpbd has better docs and is a lot more ergonomic, afaik it's also more deterministic and it's just generally easier to use if you do anything weird (like rollback networking) ... Sure it might have lower performance and less features, tho even those could be argued to be untrue because rapier just has different performance issues and a different feature set π€
I for one would rather use the library that allows me to have my own collider type than the one that has all the obscure joint types I'll never use π
(next release will technically have more joint types than Rapier lol)
For performance, one of the next big steps would probably be (parallel) simulation islands, but that'll probably be a bit tricky with the current implementation... We probably can't just iterate through and solve all joints for a given island when there are multiple different types of joints, or at least not as easily. This might be why Rapier uses GenericJoint for everything
Having sleeping logic that's not broken and speculative CCD might help with performance too tho 
speculative CCD is done, I still need to find why the sleeping doesn't work tho
the sleeping is sub-optimal anyways since per-body sleeping is typically not recommended
The new solver also generally ran better than xpbd right?
Not sure about the solver but performance is typically better since the narrow phase is only run once per frame
I guess for simulation islands we might have to add a joint enum and do something like this unless we want a bunch of dynamic dispatch...
pub enum JointKind {
Fixed(FixedJoint),
Prismatic(PrismaticJoint),
Revolute(RevoluteJoint),
Spherical(SphericalJoint),
Generic(GenericJoint),
}
pub struct Joint {
pub entity1: Entity,
pub entity2: Entity,
pub kind: JointKind,
}
Rapier had something similar before it switched to using GenericJoint for everything
It just doesn't feel very ECS-ey from an implementation perspective
I have to do that anyways if I want any kind of meta interaction with joints. That's one pain point of everything being ECS.
So this crate doing the enum would be a convenience up for me :^)
It would make this system spam redundant at least
solve_xpbd_constraint::<FixedJoint, 2>,
solve_xpbd_constraint::<RevoluteJoint, 2>,
#[cfg(feature = "3d")]
solve_xpbd_constraint::<SphericalJoint, 2>,
solve_xpbd_constraint::<PrismaticJoint, 2>,
solve_xpbd_constraint::<DistanceJoint, 2>,
everything could just query for Joint
Just make a system with a Query<AnyOf<&FixedJoint, &PrismaticJoint, &RevoluteJoin, &SphericalJoint, &GenericJoint>> π
Hey thanks, never knew about this param.
I was spamming options like a caveman.
I keep forgetting that exists
You're still living in bevy 0.6 I see π
doesn't help with the island / constraint graph issue tho
I started reading changelongs sometime after 0.8 lol
And this pattern is pretty rare.
I believe I started following Bevy around 0.5 or something
Since we're on offtopic anyways, can we talk about the crazy shit happening in the rendering dev for bevy.
Can't believe these wizards.
0.5 release post:
Expect to see progress in the following areas soon:
- "Pipelined" rendering and other renderer optimizations
- Bevy UI redesign
- Animation: component animation and 3d skeletal animation
- ECS: relationships/indexing, async systems, archetype invariants, "stageless" system schedules
- 3D Lighting Features: shadows, more light types
- More Bevy Scene features and usability improvements
archetype invariants
What are those?
My understanding is that they allow you to specify constraints to what components can or cannot be used together, like an entity with X cannot have Y
That would be convenient.
Due to the overhead of verifying these rules against the World's archetypes, this is likely best done only during debug mode,
Poor debug mode is struggling as it is π¦
True ... I only remember AnyOf when I get to my third Option π
third?
colliders: &Query<(
Ref<Position>,
Option<&AccumulatedTranslation>,
Ref<Rotation>,
Option<&LinearVelocity>,
Option<&ColliderParent>,
Has<Sensor>,
Has<RigidBody>,
Option<&ContactSkin>,
Option<&SpeculativeMargin>,
&C,
)>,
Hey at least those are spaced appart so that there's never 3 in a row 
Another one I like is Option<(&A, &B)>, which has a subtly different meaning
You can do that??
Yes
This smells.
Oh here's a good one
mut query: Query<
(
Entity,
Option<&mut Transform>,
Option<&GlobalTransform>,
Option<&Position>,
Option<&PreSolveAccumulatedTranslation>,
Option<&Rotation>,
Option<&PreviousRotation>,
Option<&Parent>,
Has<C>,
),
Added<C>,
>,
parents: Query<
(
Option<&Position>,
Option<&Rotation>,
Option<&GlobalTransform>,
),
With<Children>,
>,
wait this query is wrong, hol' up
Why Has and Added on the same query?
I mean at least those might still all be optional 
I rarely have queries where each component is individually optional tho, either it's just one, there's a whole group that needs to either exist or not, or I want at least one of them
I'm increasingly confused... the variable for Has<C> is also named is_rb even though C is a collider 
Which would map to Option<&A>, Option<(&A, &B)> and AnyOf<(&A, &B)>
But if you're confused ... Then who wrote this? 
Nah can't be me, surely not
my god this is the ugliest system I have ever seen, I always feel like throwing up looking at this
and it's annoyingly not that easy to do in a much nicer way
Wait is this the collider transform propagation thing?
no, init_transforms
Oof, and here I was hoping this wasn't actually ran in my project π
It's the price we pay for being able to add any arbitrary physics components and have everything just work.
Actually wait ... init transforms ... Is that in PreparePlugin or SyncPlugin? 
xpbd slaps on most of the missing ones ... Would be nice if we have required components to deal with that tho
yeah it'd be nice for some components, but some probably need manual initialization anyway
also if conditional requires aren't supported then it might be annoying
like we might only want to add force and velocity components for non-static bodies
If they are conditional they aren't really required now are they?
Maybe that would just signify that it's time to split RigidBody into three markers π
Oh wait but then we need archetype invariants to prevent people from making a static kinematic dynamic body π
#[require_if(without(Static), require(LinearVelocity, AngularVelocity))]
struct RigidBody;
Once we get the Static marker for Bevy I'd like to
the enum yeah
It'd just be a RigidBody which is dynamic by default but you can add Static to make it static
And then for kinematic bodies, I guess a separate component
Hmm, maybe it's just a CharacterBody which is kinematic by default but adding a RigidBody makes it a dynamic character π€ idk that might just be weird
What are some ways to "run physics multiple times" in the same "game loop" on subsets of all entities? I'm thinking this would help me with two scenarios:
- Multiple floating origins: let's say there are two "rooms" containing interacting objects; each room's size is on the order of magnitude of 1 x 1 x 1, but they are 10^9 apart, so that I want to simulate each room separately, each with their own origins. I would probably do this by "running xpbd" separately for each room (since they don't interact at this time).
- Rollback: for a networked game, the client side might receive updates from the server about a state a few steps in the past, and it would run a few steps forward again to catch up to the current client time, all within the same "game loop".
My only thought is using separate worlds for physics and copying transforms around. Sounds miserable, but I think this functionality would need first party support from the crate.
Man how in tarnation can i make this colliders stop bouncing
Simulating groups of entities separately is difficult since they share the same world and bevy_xpbd simulates entities using normal Bevy systems. It might be possible to have different ECS worlds and to simulate them separately, but I haven't tried it and I imagine it'd be pretty painful.
But for those two scenarios:
- This would likely require first-party support for floating origins. This is something I plan on experimenting with. The engine could simulate all of the bodies together, but essentially just ignore interactions between bodies that belong to different chunks/origins.
- There are several people already using bevy_xpbd with networking. They are probably more knowledgeable on how it works than I am. But for running simulation steps on-demand, it's possible to make custom physics runners; you can just run the
PhysicsSchedulemanually and advance theTime<Physics>clock by the desired amount.
Thank you both for the pointers! I'll need to look into custom runners / schedules in Bevy.
I'm also looking into how big_space (https://docs.rs/big_space/) does floating origin, I suspect there is only one floating origin for the whole world / one chunk.
This bevy plugin makes it possible to build high-precision worlds that exceed the size of the observable universe, with no added dependencies, while remaining largely compatible with the rest of the Bevy ecosystem.
I see a usecase for entity disabling, I should add this to my RFC π
Sorry for the necro-response, but multiplayer support is one of my goals with the crate. The floating origin rendering is non-destructive - the high precision coordinates can be shared between clients and the floating origin system handles crushing that down to f32 for rendering.
I also want to support physics, but that would probably live in a sibling crate. Not sure how feasible that will be with bevy_xpbd because I'll probably need to manage my own physics contexts as well as component syncing.
Syncing of what components?
Syncing the physics state with the entity positions, essentially.
I think the main thing I would need is the ability to have independent, non-overlapping physics contexts, and the abililty to ignore the value of Transform.
Because all entities will be inside a say, 2km cube, if you are only looking at the Transform.
It should be straightforward to make a custom sync plugin for physics-position-to-transform syncing at least. There's already a fork integrating big_space with bevy_xpbd
How does that work with Transform?
Does xpbd have its own internal representation of position seperate from the transform?
Yes, Position and Rotation
there are several reasons for it, including custom sync setups like this
Cool!
I would probably (?) split this off onto a server, to have it handle all physics calcs, so I suppose it will have it's own view of the physics world anyway.
Any idea where that is, not finding it.
Could you elaborate on what you'd need in terms of "non-overlapping physics contexts"? Being able to have actually separate simulation worlds would probably be challenging, but from the physics side I would imagine that just the broad phase and spatial queries would need to be modified to support multiple floating origins
I'll try to find it
The idea is that for physics in large worlds, you want to group objects (island detection), and position the origin at the center of each merged group. From the perspective of the physics simulation, each of these sets of objects would need to be simulated separately, even though they are all near their local physics origin.
But, tbh, if this ends up being over the network anyway, then it might be a non-issue. Each physics island could be running in a separate physics instance.
For local prediction, you probably only need to care about physics relative to the player, and won't need to care about multiple physics islands.
I'm currently working on supporting multiple reference frame hierarchies, to allow you to render multiple viewports, each with their own floating origin. So, not sure when (if ever) I will get to the physics. π
This is pretty old, but here
https://github.com/austincummings/big_space/blob/xpbd-compat/src/bevy_xpbd/floating_origin_sync.rs
Cool, thanks!
I was trying to find a good video of it working but this is the best I found, doesn't really show the physics though
#general message
By islands, I'm guessing you don't mean actual simulation islands but rather just grouping objects based on proximity or something? Because simulation islands aren't really a large-world thing necessarily, they're mostly an optimization and for sleeping/waking
Same idea, different purpose
Islands don't interact, so you can use that to run each island with a local origin for physics.
yeah, makes sense, although I'm still not sure why you'd need to simulate each island separately other than making sure that objects from different islands don't interact by filtering them in the broad phase
Iirc that's how space engineers works.
So you can keep the physics origin close to the objects
So it doesn't matter if you are on the other side of the galaxy, if you are only interacting with objects in your vicinity, then the physics simulation only needs to be relative to that group of objects.
Yes, but you can still simulate all bodies simultaneously. The solver only cares about the constraints given to it (or generated based on contacts), and the broad phase can make sure objects from different islands don't interact
I think we're saying the same thing?
As long as the sets do not interact, that's all you need
Yeah we probably are, I just thought you meant running separate simulations like "simulate island 1, simulate island 2", and I'm just saying we can run everything together but make sure the sets don't intersects in terms of what constraints are generated
so everything except the broad phase and spatial query pipeline should be able to remain basically unchanged, unless I'm missing something
Either way, I'm interested in experimenting with built-in support for floating origins some time after the upcoming bevy_xpbd release, and I'd be happy to try supporting big_space, probably behind a feature flag
Yup! I'm on the same page as you. π
Is it a good idea to run physics (& probably game logic too) on a different schedule that tries to stick to a "physics tick rate" as opposed to the render schedule? So slowdowns in rendering don't affect the physics, and rendering just takes whatever state the world is in at the start of the render frame. What are some issues with this? (e.g. I'd probably need to interpolate the positions that actually get rendered? Or issues with physics changing the world while rendering is happening?)
You mean like FixedUpdate? Using FixedUpdate is a good idea yes ... There's still some issues with bevy that make this more painful than it should (especially when it comes to input), and you would indeed want to look into some interpolation, at least for the more noticable components like position and rotation
Oh haha, that's what FixedUpdate is for. I never really understood what it was for until now (all my gameplay logic is in the Main schedule and it seemed like it was all fine)
Hi, first of all thanks for this crate! I just started using it recently and it's very well documented! π I have a question regarding turning off collision detection between 2 entities. E.g. in a skeleton's bones I'd like to ignore collision between adjoinig bones. The CollisionLayers don't seem to be a good fit for this as I'd need to use a unique bit for each bone. Am I missing something obvious? If not, I'd be happy to try to contribute a solution for this
No good way to do this currently.
I believe Jondolf is looking to add this functionality in the next few releases.
Hi again, I found a little bug in prepare/init_transforms so I opened a PR to fix it (https://github.com/Jondolf/bevy_xpbd/pull/360), then I added a test and found some more. Any reviews are much appreciated! Also, I'll be using this crate for my project extensively and if you're looking for some help with maintenance of this crate I'd be down for it.
I'm sure it's not anywhere near as succinct as what you're looking for, but you can get access to the whole list of collisions from the Collisions resource and use the retain associated function to remove collisions. There's an example here that uses it: https://github.com/Jondolf/bevy_xpbd/blob/434be4595ea6b4efa0c16ff22f906ba527c1386d/crates/bevy_xpbd_2d/examples/one_way_platform_2d.rs
You'll be able to at least use that for now to tide you over
The example is using it to allow dropping through platforms, but you'd be able to do it with something like this:
#[derive(Resource, Deref)]
pub struct PairsToIgnore(HashSet<(Entity, Entity)>); // store lowest index of the pair in .0
fn ignore_collisions(mut collisions: ResMut<Collisions>, pairs_to_ignore: Res<PairsToIgnore>) {
collisions.retain(|collision| {
let (a, b) = if collision.entity1.index() < collision.entity2.index() {
(collision.entity1, collision.entity2)
} else {
(collision.entity2, collision.entity1)
};
!pairs_to_ignore.contains(&(a, b))
});
}
Thatβs very helpful, thank you!
so i'm possibly using the library in an unintended way, but essentially i have
- character that is a dynamic rigid body with mass
- camera that is a dynamic rigid body with a VERY tiny mass
- DistanceJoint between the two with a max length
i want the character to pull the camera along, and have it lag slightly behind
the issue i'm having is that when the character stops, the camera pulls the character back
is there a way to have a one-way force? so the character only applies force to the camera, and not vice-versa?
or would i have to implement a one-way joint perhaps?
Mass(PLAYER_MASS / 100000.0),
this is the mass i'm trying for the camera, to limit how much force it can apply to the character, but it doesn't seem to work too well, camera still moves the character a visible amount
PLAYER_MASS = 1.0
ooh reducing the linear damping on the camera may have helped
There is a Dominance component that could be used for this. The caveat is that if you for example gave the character a higher dominance than the default, it wouldn't affect just the jointed camera, but also all other interactions like collisions. You could probably give the camera a negative dominance and keep the character as default though
Dominance allows dynamic rigid bodies to dominate each other during physical interactions.
ooh! i'll look into that, thanks!
absolutely perfect, does exactly what i want
π lots of docs to read through, i'm sure i would have found it eventually, but you saved me a lot of time!
Nice! Yeah there's a lot of docs haha, I'm planning on reworking them a bit to make them easier to browse
Hmm, I'm not sure if I should make the crappy per-body sleeping "work" again, or leave it broken/disabled for this release and do it properly when we implement simulation islands later π€
I technically have it working again, but the per-body approach is just buggy and can cause weird jumpiness/jitter when bodies wake up. This was already kinda happening with the old solver, but it seems even worse now because of scheduling and narrow phase changes
I'd rather instability be avoided at the cost of performance, but I'm sure there are others who would prefer otherwise.
Yeah, I think that's better especially since this is a major solver rework, wouldn't be a good first impression if there are random mini explosions and other weirdness whenever bodies wake up
although it's mostly for piles of objects
I'll see if I can at least fix the instability issues even if it's buggy in other ways, but otherwise I'll probably leave sleeping out for now (sry @cinder summit)
I'd imagine fixing per-body sleeping would be a nightmare in general, especially since any bit of Changed<T> can break it, because that's how it's broken now
I changed the way component changes trigger wake-ups so that it ignores changes that happened during physics
uses somewhat cursed change tick tracking
If we want good sleeping later it'll probably need to make sure to only catch non-physics changes in and check that the new values are non-zero π€
ah yea I should check for non-zero too, good call
my current issue is that sleeping bodies very randomly start sinking into the ground (without velocity??) but I think I might know why
For now, I might actually do a scuffed version of sleeping where bodies can only sleep if they're not in contact with dynamic objects. This way, random dynamic objects lying on the ground can still sleep, but piles of dynamic objects won't
Yeah, this seems like a decent compromise until we have simulation islands. Should give a performance boost for larger worlds with dynamic objects that are just lying on the ground for example, without causing any instability issues
Hey I was using this and for some reason the children of the object don't get attached to it and just stay put any idea why this is happening?
Do they have both Transform and GlobalTransform? Bevy requires both for transform propagation
Oh so I have to add those components I see! thank you!
GlobalTransform is required for an object to be rendered, Transform is not, on the other hand, lots of things use Transform and anything with both will have Transform propagated to GlobalTransform relative to its parents
Dang, we sure have a lot of plugins lol
Reworking and flattening the module structure further. Before and after:
In the first one:
componentsjust contains a bunch of components with no clear separation of concerns, and some components are still stored elsewhere so it's not even comprehensive at allresourceshas the same issue; no separation of concerns, and it's pretty random which resources are there vs. elsewhere- Why is
constraintsa top-level module? It's mainly a solver implementation detail pluginsis weird, because it has sub-folders with sub-plugins, and really it's just a folder for basically all functionality in the engine
New structure:
plugins,components, andresources, flatten structure- Organize everything by logical concerns
- Add
dynamicsmodule for encapsulating rigid body dynamics (solver, sleeping, rigid body components, etc.), which also gives a nice place for more high-level docs
(I still need to update the module docs to have a more consistent and clear summary in the first paragraph though)
"organize by logical concerns" has 100% worked better for me in the past π
I wonder if the opposite (group by type of thing) ever worked for anyone π€
bevy_transform is like that, but it might be slightly more acceptable there since it's so small and contained
Sounds more like bevy_transform is just tech debt tho π€
Not sure where else hierarchy stuff would be handled
doesn't really make sense in bevy_math (except maybe the Transform itself)
Wait bevy_hierarchy is its own crate π€
And it also has a "group by type of thing" structure
I feel like we could probably merge bevy_transform and bevy_hierarchy, and maybe make Transform just a general transformation type in bevy_math
I left a review on this, thanks for the PR! (and sorry for the late response) There are mostly just CI errors related to wrong precision types with the f64 feature, and a few other nits
Honestly, I feel like we should get rid of f64 support once we have proper floating origins for large worlds, since supporting both f32 and f64 through feature flags makes a lot of code more annoying or confusing, frequently trips up contributors, and also means that we need to copy any Bevy types we might want to use to work with f64...
And then it's also just generally more efficient to use f32 and only use f64 in places where the extra precision is really needed
"proper floating origins for large worlds" as in support for big_space? π€
yes, with physics ideally working even for multiple floating origins (i.e. multiplayer support)
As for maintenance, did you have something specific in mind? I would of course appreciate help fixing issues and such, and I'm happy to give guidance on things as needed in case you're interested.
I'm still working on the big rework and rebrand (see #346, although it's somewhat outdated by now) so I haven't had as much time to do "general maintenance" lately, like properly responding to issues and fixing them. A part of this is also that some things are just blocked on me finishing the rework, and I don't want me or others to spend too much time working on things that will soon be replaced or fixed by the new solver anyway.
After the release, I plan on doing a quick organizational pass: improve the issue labels (maybe Bevy-style labels), write up some kind of contribution guide, go through all the issues and respond to them / fix trivial issues, and also open a bunch of my own issues for missing features, performance work, and so on. I think we need to keep a better track of work, make it easier for people to contribute (including learning resources for physics simulation), and in general have a bit more structure.
Does xpbd integrate ExternalForce with kinematic bodies?
I get that kinematic is "excluding forces" but yeah, just wonderin since I'm going to re-add that functionality with a controller
It doesn't
Gotcha ty! 
Np!
Nice, thanks for the thorough review and no rush! I'd be happy to help with anything like fixing issues, testing, refactors and features (within my capabilities - I'm still learning more about the internals) and it also helps me to learn more about the project. I probably won't have a consistent time availability to dedicate to it tbh and I don't mind waiting till you're finished with the rework before doing any more stuff
hi, i'm trying to shapecast a circle in 2d just to get colliders within a certain range of the player each frame and i'm not sure what i should set the SpatialQuery properties to. direction and max_time_of_impact don't really make sense for this application.
or is there a better alternative aside from manually checking distances to transforms?
A system parameter for performing spatial queries.
This doesn't return the distances though
thanks, i should have read the docs a bit more carefully
But if you just need the entities intersecting the circle, it should be enough
you probably should get distance to closest point and not transform, otherwise large objects would get weird
that would be useful to have in the future, but calculating manually for only those entities that are in range shouldn't be that costly anyway
yeah
that's if you need exact distance and not just everything within range
for distances to closest points, you could just do point projection for the entities that are in range
i was just doing extra raycasts since i needed that for obstructions anyway
finally got to try this - the order of the entities is not guaranteed, but something like this works
pub fn ignore_collisions(
mut collisions: ResMut<Collisions>,
pairs_to_ignore: Res<IgnoreCollisions>,
) {
collisions.retain(|contacts| {
let (a, b) = (contacts.entity1, contacts.entity2);
!(pairs_to_ignore.contains(&(a, b))
|| pairs_to_ignore.contains(&(b, a)))
});
}
Yeah, that should work. A more efficient version would do this filtering in the broad phase already so that it wouldn't unnecessarily compute the contacts in the narrow phase for the pairs you want to ignore
This will be a built-in feature for joints later, but right now there isn't a very clean or performant way to do it, especially because each joint type is its own component type
Or I could just add an IgnoreCollisionsWith component for now I guess... that'd be very easy and pretty efficient
Iβm in no rush as the workaround unblocks me but I can try to impl this. It sounds easy to do
Yep thatβll work π
Thereβs a comment in what I originally wrote about storing them in entity index order to avoid the second hash/lookup but itβs probably negligible since Entity is a small type.
Tangentially related: Youβll find that because the order is not guaranteed youβll want to be doing something similar in collision events, too. The way I see folks handling that is doing this: for ((a, b)) in [(entity1, entity2), (entity2, entity1)] { β¦ }
Ah, it is the contactβs pairs that donβt have a defined order
Yeah I've been considering ordering the entities in collision pairs by the entity ID, not sure how useful it'd be though
Currently it's ordered by the X-extents afaik because of the broad phase implementation
not sure if it would be overkill but could do something like struct UnorderedPair(Entity, Entity) and manually impl PartialEq for it that ignores their order
@vestal minnow is it possible to get the aabb of a collider (2d)?
You can either use the collider's aabb method to compute it (takes the position and rotation) or query for the ColliderAabb component directly.
Note that the ColliderAabb is the AABB in global space, and it's expanded based on the body's velocity for collision purposes, so it often doesn't match the actual extents of the collider, except for stationary objects
A trait that generalizes over colliders. Implementing this trait allows colliders to be used with the physics engine.
ah alr thx
np!
Hey, I'm having some trouble with a SphericalJoint and with_swing_limits . When combined with non-zero gravity, the swing limits don't seem to be respected and they get broken by gravity. I am using with_compliance(0.). I tried digging into what's going on, but no luck so far
I'm trying to place objects in the game close to each other, but it seems like the collision is being detected without actual contact.
Is this a rounding error?
Both objects are kinematic bodies.
probably the safety margin prediction_distance
prediction_distance: 0.0,
})```
Thank you a lot!
it worked?
should hopefully be fixed for the upcoming release, but that ^ should work for now
Hah, I was just about to ask if that would get fixed in the next release π
Yes!
People have run into that so many times it's kinda crazy it didn't have a fix yet
Is this a bug? I thought it's a default config.
it's a buggy fix to another bug iirc
It's somewhere between a bug and a design flaw I guess ... Prediction distance really shouldn't be a concern of end users beyond some stability/ccd type of stuff π€
At least I think I've already fixed it locally on accident with the narrow phase scheduling changes, but collision events have other issues rn. I'm working on fixing that stuff now though
and yes it has been an issue for way too long lmao
related issue: https://github.com/Jondolf/bevy_xpbd/issues/224
Now my future kitchen can be placed perfectly:
nice, I hope your future house will have more than just a kitchen
With the new solver stuff I'm calling this default_speculative_margin since it's for speculative contacts
can be set per-entity with SpeculativeMargin
same as Rapier's "soft CCD", I just dislike that name a lot and haven't seen it anywhere else
it doesn't feel that speculative though
Bepu and Box2D call it speculative collision, Unity also calls it speculative CCD afaik
it is
something behind the scenes? the result was a consistent margin for me
The contact is speculative, the margin (i.e. max distance for speculative contacts) is derived from the velocity and clamped by the maximum bound
It just speculates a rough estimate of where the contact could be based on the closest points, it's not an actually accurate prediction
which is fine typically, but can cause ghost collisions in edge cases
oh, that's very different from what it currently does
yes
currently it's just for stability
with XPBD, it was especially important for stability to have a bit of wiggle room for the distance at which collisions are accepted
it's not quite as important with the new solver, but still helps; it's more-so to avoid tunneling now though
Why kinematic bodies tho? That seems like a bit of an odd choice for static objects and a non-existant instance of a static object π€
Player can move them, If I use static objects, collision stops being detected.
Maybe I can make them static after placement... I.e. currently placing object will be kinematic, but already placed could be static π€
huh, it doesn't detect collisions?
If it's just position that changes a sensor would also work for the version that is being placed I think
Yea like Static-Static would get skipped
ah yea that gets skipped ofc
An intersection test via SpatialQuery could also work for this probably
If I slap Sensor and RigidBody::Static (both, placing and already placed), I still have no collisions...
Sorry, I misread.
Will try sensor for placing. Will need to rework the logic a bit to handle them differently.
Could also use just a collider initially, and only add the rigid body when placing
Thanks!
This behaves the same as Sensor right? π€
yes, but it might still skip static-static contacts atm
so if you want those to be detected, it can't have a RigidBody::Static
Yea, it would need to be Sensor without RigidBody
and at that point slapping a Sensor on top doesn't add much
I still find Collider without either reporting collision events weird tbh π
Like, it's weird that static-static is just skipped?
Or that it's weird that a collider without a rigid body or a sensor component still sends collision events
This one ... And I guess it's also a bit weird that every collider gets thrown into the bvh by default π€
Luckily it doesn't matter for most usecases, and I don't think many people have had serious performance issues because of it, so collision layers are an okay workaround for now I guess
Yeah I'm open to reworking this, but I feel like it'd also be a bit weird if a Collider just did nothing on its own
It makes more sense if you consider Collider equal to CollisionShape in Godot ... Either way probably not the most important issue to fix right now, but if there's ever a time to reorganize the components in a breaking way it might be good to look into some alternative designs ... Which I guess would be when required components and/or construct lands π€
yeah, I'm definitely not entirely happy with the current design in terms of the relationships between colliders, sensors, static bodies, and collision events, so I'd be happy to make changes if there's a better / more logical approach
Maybe observers can also make the collision events situation less painful
and I'm definitely open to any breaking changes for the foreseeable future :P as long as they don't cause entirely unnecessary churn
"entirely unnecessary churn" ... You mean like when you introduce a Direction3d type then rename it to Dir3? 
well back then people preferred the longer name before the type was actually used :P
I kinda treat bevy_xpbd as a way of freely experimenting with things to hopefully find what would be best for bevy_physics
so I'm open to experimental stuff and breaking changes, it's better to try as many things as possible and explore designs in 3rd party than 1st party
I think bevy_eventlistener could be hype for a lot of collision event handling patterns
https://github.com/Jondolf/bevy_xpbd/issues/361
Maybe we could even do something where collision events are only sent for entities that have an event listener to avoid sending unnecessary events and cloning a bunch of data
Another nice bonus here is the event bubbling, rigid bodies could listen to collision events of their child colliders too, which avoids having to query for the ColliderParent etc.
For querying for all collisions, you could still use the Collisions resource
@vestal minnow sry, any idea whatβs happening here? The joint is connecting a static and dynamic body. When I add gravity motion of the dynamic body breaks out of the angle limits of the joint. From what I see the motion applied from gravity is added to AccumulatedTranslation which is taken into consideration in the constraints solver, so Iβm still confused about whatβs happening
Do you have a minimal repro? This seems to be working fine
// Kinematic rotating "anchor" object
let anchor = commands
.spawn((
PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::CYAN),
..default()
},
RigidBody::Kinematic,
AngularVelocity(Vector::Z * 1.5),
))
.id();
// Dynamic object rotating around anchor
let object = commands
.spawn((
PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::CYAN),
transform: Transform::from_xyz(0.0, -2.0, 0.0),
..default()
},
RigidBody::Dynamic,
Collider::cuboid(1.0, 1.0, 1.0),
))
.id();
// Connect anchor and dynamic object
commands.spawn(
SphericalJoint::new(anchor, object)
.with_local_anchor_2(Vector::Y * 2.0)
.with_swing_limits(-1.0, 1.0),
);
(using a rotating kinematic body so that you can actually see the limit working)
Thx, I will check it tmrw and if I still have issues I will make a minimal repro π
hi i might be misunderstanding but i'm trying to use raycasts from the character and the rays are hitting the player collider despite the parent entity being ignored like ```rust
.with_query_filter(SpatialQueryFilter::from_excluded_entities([
parent.parent_entity()
]))
sorry won't be able to respond to answers immediately i'm going to bed
same haha
I would probably double-check that the entity you're excluding is the entity with that collider, but it's a bit hard to say what the issue could be
here's the spawning code
commands
.spawn((
Player,
SpatialBundle {
transform: Transform::from_translation(Vec3::new(0.0, 5.0, 0.0)),
..default()
},
input_manager(),
RigidBody::Dynamic,
collider,
ShapeCaster::new(cast, Vec3::ZERO, Quat::IDENTITY, Direction3d::NEG_Y)
.with_max_time_of_impact(0.2),
LockedAxes::ROTATION_LOCKED,
Controller::default(),
Friction::ZERO.with_combine_rule(CoefficientCombine::Min),
Restitution::ZERO.with_combine_rule(CoefficientCombine::Min),
GravityScale(0.0),
))
.with_children(|parent| {
parent
.with_children(|parent| {
parent.spawn((
Front,
RayCaster::new(Vec3::Z, Direction3d::NEG_Y).with_max_time_of_impact(2.0),
));
parent.spawn((
Belly,
RayCaster::new(Vec3::new(0.0, 1.5, 0.4), Direction3d::Z)
.with_query_filter(SpatialQueryFilter::from_excluded_entities([
parent.parent_entity()
]))
.with_max_time_of_impact(1.0),
));
parent.spawn((
Foot,
RayCaster::new(Vec3::new(0.0, 0.4, 0.4), Direction3d::Z)
.with_query_filter(SpatialQueryFilter::from_excluded_entities([
parent.parent_entity()
]))
.with_max_time_of_impact(1.0),
));
});
})
.with_children(camera::spawn);
another work-around would be to make a collision layer for the character and ignore that for the ray cast, but it might get annoying if you have a bunch of characters
hmm okay, thanks; I'll test tomorrow but need to go to bed too now
btw this doesn't compile
.with_children(|parent| {
parent.with_children(|parent| {
// ...
});
})
so this code seems to just be wrong. I assume you meant to have all the with_children calls on the root entity and not double-nested like this?
(and yea now I'm actually going to bed lol, goobmight)
yeah oh you're so right i nested it that's probably the problem
yup that did the trick
sorry π
np, glad that you got it working :)
also I love this gif so much it's so cuteee
Hey, I did some more experiments and here's a minimal example where it seems to break (unless I'm doing something wrong): https://github.com/exoexo-dev/bevy_xpbd/blob/joint-and-gravity-example/crates/bevy_xpbd_3d/examples/joint_and_gravity_3d.rs. You can run it with e.g. cargo run --example joint_and_gravity_3d --no-default-features --features "3d f64 parry-f64 debug-plugin use-debug-plugin" (it's based on this PR https://github.com/Jondolf/bevy_xpbd/pull/364 as I'm using it to ignore collisions between the anchor and the object, but even with e.g. CollisionLayers it's the same). I've set the gravity on a toggle by G key - it's off on startup
so i have a fps controller with kinematic body.
when i move, everything is fine
when i turn my head, everything is fine
but when i both move and turn my head, there is a jitter. and yes i use
app.add_systems(
PostUpdate,
camera_follow_player
.after(PhysicsSet::Sync)
.before(TransformSystem::TransformPropagate),
);
``` for camera follow.
i always moved my player with directly changing its linear velocity
```rs
linear_velocity.x = wishdir.x * 5.0;
linear_velocity.z = wishdir.z * 5.0;
but when i removed this code and added position update the jitter is gone
player_transform.translation.x += wishdir.x * 0.03;
player_transform.translation.z += wishdir.z * 0.03;
i guess changing linear velocity directly is wrong. should i add acceleration to linear velocity?
Setting linear velocity should be fine if instant acceleration/deceleration is acceptable ... Shouldn't introduce any jitter at least ... How is wishdir calculated, and where does this system run?
What's the standard way to just "turn off" physics? I was thinking I could slap a run condition on the integrate set, which would probably get the job done but be heavy-handed
On second thought, that doesn't seem to work π€
I think you can call pause() on ResMut<Time<Physics>>
I'll test this later today, thanks
just based on a quick look, setting the minimum and maximum swing angle to be equal seems a bit odd, since it means that there is no allowed swing at all
if you wanted equal swing in both directions, the minimum bound should be negative (I should probably make this clearer in docs)
but that should still constrain the angle to the specified value, so if it's not working then there probably is some issue
much appreciate it, thx! I do want to lock the joint at the current angle as I'll be changing the limits dynamically
yeah, makes sense
What would you recommend for simulating wall collision for a kinematic body like a player?
There currently is no particularly nice approach, but the kinematic_character_3d example shows one way to manually handle collisions for kinematic bodies.
System:
https://github.com/Jondolf/bevy_xpbd/blob/5a10b6168a96eac057251dcee244fda4d5ba870e/crates/bevy_xpbd_3d/examples/kinematic_character_3d/plugin.rs#L291
Where to put the system:
https://github.com/Jondolf/bevy_xpbd/blob/5a10b6168a96eac057251dcee244fda4d5ba870e/crates/bevy_xpbd_3d/examples/kinematic_character_3d/plugin.rs#L21-L25
I'll most likely add some kind of built-in collide_and_slide functionality in the future
originally I was thinking that character controllers should be third party, but it'd probably be valuable to have a built-in solution too (even if it was in its own crate)
- I just want to try making a proper character controller lol
gotcha - guess i'll wait for that and for now have dynamic with 0 gravity scale, friction and restitution so i can control it myself
Contribute to HasChad/bevy-shooting-range development by creating an account on GitHub.
everything you need are in this folder
they are pretty short and readable enough i believe
What immediately stands out to me is:
These two systems handle input, but PreUpdate is also where inputs get generated, so they won't run consistently unless you add an .after(InputSystem)
.add_systems(PreUpdate, movement_input_changer)
.add_systems(PreUpdate, player_look)
``` and there's this `.after` referring to a system in another schedule:
```rust
player_move
.after(player_look)
so i added .after(InputSystem) to those two input systems and removed .after(player_look) on player_look but its still jittery
Could also be that it's just jitter from the 60Hz physics schedule not running smoothly, but then it would probably only happen sometimes (unless your FPS isn't stable or it's some weird number that's only slightly off from 60 like 75)
well, my fps jumps around 300 to 200
Wait now that I think about it ... It might just be that the camera updates at a different rate than the physics ... Even if it's a smooth 60 physics steps per second, if the camera moves 300 times per second and only jumps in position 60 times that's not gonna look smooth ... Could use variable delta for that, or just add a big of smoothing to the position the camera tracks
Oh and setting the player's velocity should also come before physics rather than after it, tho that one frame delay isn't related to the jitter
yeah it actually make sense. so uh, how am i gonna smooth that? an example would be nice
after limiting game fps to 60, its just smooth af. now i need to smooth that camera for higher fps
The way I do it in my game is saving the target position of the camera, and lerping from the target position to the new position, using that as the new target position and the point the camera follows
Tho in my game I only do this for height atm π€
so for 60fps camera movement, i should save camera position at every 16.6 miliseconds and lerp it to new position, right?
If you want to interpolate it perfectly yea. You can also go for more general smoothing which can come in various forms
well im open to any idea
I think a fairly minimal camera smoothing approach would be something like this:
let new_pos = positions.get(player);
let (target_pos, speed) = camera_props.get(camera);
let Ok((dir, length)) = Diration3d::new_and_length(new_pos - target_pos) else { **speed = 0.; continue;};
**speed = (length * time.delta_seconds()).max(**speed);
if speed > length {
*target_pos = *new_pos;
**speed = 0.;
} else {
*target_pos += dir * speed;
}
You just move the camera at some speed to make sure it reaches the target_pos in clearly defined maximum amount of time (1s in this case because length * time.delta_seconds(), could just multiple that by say 4 to get 0.25s), make sure to take the maximum speed between the current speed and last speed, and if it would ever overshoot the target reset the speed and set target to the new pos (this means we've reached the target) .. You then move the camera based on that target_pos instead of the player's position
There's a few minor edgecases where it might be suboptimal tho. Specifically if you move fast, then move slower it will hit the target pos, stop for 1 frame, then go to the new speed ... It might make sense to slowly lower the speed if it's close enough to the player
The downside is of course that any camera smoothing can lag behind the player ... The upside is that often you already don't follow the player but some point in front of them (in many 2D games) or next to them (with a 3D third person camera), and such an approach could be shared with the smoothing for physics-related jitter
welp, anything for smooth player controller
Legend has it a lot of games known for their good controls have had their controls worked on for months with dedicated playtests just for that ... Something about wanting movement to be fun even if it's just in a test level with just a few cubes
It doesnt need to be "fun". Im fine as long as there is no jitter
Ended up not having too much time to look into this today, but it seems to be a matter of the joint just using the wrong swing and twist axes for this configuration. If I use Y and Z for swing and X for twist, it constrains the angle:
The axis properties are public but there aren't any helper methods currently. The upcoming release will support local frames (anchor + reference orientation) for this though
ah, it makes sense to me now, thank you for checking!
does xpbd cache anything related to compound colliders?
like is it a bad idea to update the relative position of 1 of the colliders frequently?
If they're real compound colliders it might cause some issues because things that teleport aren't usually stable, but afaik there's no real caching π€
Compound as in multiple colliders as separate entities attached to a rigid body as child colliders? Or compound as in Collider::compound
In either case I don't think there's really caching though
except maybe mass properties, since moving the colliders around affects the center of mass of the body, assuming the colliders have non-zero density
@vestal minnow Would bevy_xpbd be able to solve displacement of struts, given some weight and elastic modulus? Something like world of goo, or bridge constructor?
You could build bridge-like structures with joints and access the forces exerted by those joints if that's enough
the stiffness of joints can also be configured
I'm not sure how those types of games handle it though, might have some more custom solution
I wrote a solver following some papers but it only works for a fully constrained systems. A βdanglyβ strut will just not converge. I guess worst case scenario is I can use my solver for all constrained struts and xpbd for dangly one just for an effect
Okay more contact updates for the xpbd rework:
- Both contact computation and contact constraint generation are handled by the narrow phase. This way, we only need to iterate over everything once, and don't have to duplicate queries or other computations. Constraint generation can also be multithreaded.
- The narrow phase logic has been extracted into a
NarrowPhasesystem parameter. Users could in theory manage it manually. - Speculative contacts use an unbounded speculative margin by default, similarly to Box2D V3 and Bepu. This means that there should be no tunneling for any objects by default, other than maybe for extremely quickly spinning objects or bodies overlapping due to contact softness. And for those cases, swept CCD can be used. Speculative contacts are very cheap as well, so this doesn't really hurt performance.
So basically
tunneling:
*
performance and code quality: π
This is using 6 substeps, but I now have 4 as the default since it's enough for the vast majority of cases with TGS soft
Which means default performance π further
(the old default was 12, which is kinda excessive)
(and it was still less stable for a lot of cases)
I don't seem to get collision contacts for a child collider of a kinematic rigid body
is this intentional?
Like, it doesn't detect collisions for it at all? That sounds like a bug
for what it's worth I am setting the position of the secondary one after SubstepSet::ApplyTranslation
but yeah it doesnt
the box is dynamic and that moving collider is a child to a kinematic rigid body
the parent one fell through the ground somehow lol
Yeah that's strange, child colliders work for at least static and dynamic bodies (that environment is technically child colliders) so I don't see why it would work for kinematic too
*wouldn't
The child collider should have a ColliderTransform component, does that get updated when you move it around?
nope
@vestal minnow I had a question about trying to do collide and slide inside of the physics substep right now we are trying to calculate the final position and the final velocity but are running into a bit of a issue with a invalid query for position and spatial query (as seen here)
pub(crate) fn kinematic_controller_collisions(
collisions: Res<Collisions>,
collider_parents: Query<&ColliderParent, Without<Sensor>>,
spatial_query: SpatialQuery,
mut character_controllers: Query<
(&RigidBody, &Collider, &mut Position, &Rotation, &mut LinearVelocity),
With<Player>,
>,
) {
and was wondering if there was another way to do this as spatial_query and Position seem to be incompatible to use in this way in the ecs.
error
error[B0001]: Query<(&bevy_xpbd_3d::components::RigidBody, &bevy_xpbd_3d::plugins::collision::collider::parry::Collider, &mut bevy_xpbd_3d::components::Position, &bevy_xpbd_3d::components::rotation::Rotation, &mut bevy_xpbd_3d::components::LinearVelocity), bevy_ecs::query::filter::With<test_game::player::Player>> in system test_game::player::player_physics::kinematic_controller_collisions accesses component(s) bevy_xpbd_3d::components::Position in a way that conflicts with a previous system parameter. Consider using `Without<T>` to create disjoint Queries or merging conflicting Queries into a `ParamSet`.
You can use Res<SpatialQueryPipeline> instead of the SpatialQuery system parameter
I might deprecate the system param in favour of just the resource at some point, not sure yet
U the realest G
thanks :)
This narrows it down at least, if it's not updating the collider transform properly
I gotta go to bed in a bit but I can take a better look tomorrow
'kay I now seem to have all the collision event stuff working properly with the new solver, better than earlier releases. The "Collision events are sent when not actually in contact" issue is also finally fixed
I'll look into this now
This is working at least (but collisions are a bit strong maybe)
cylinder is a child collider of the capsule kinematic rigid body
I'm guessing it's related to the scheduling then
it also works after SubstepSet::ApplyTranslation (and is more stable)
@vestal minnow hey I am still working on that collide and slide algo from yesterday but I was wondering what would be the best way to get delta time during the physics substep.
Just Res<Time<Substeps>> and then .delta_seconds() should work
Nice thanks
in the SubstepSchedule the default Time resource also uses the substep time, similarly to how Time in FixedUpdate is actually Time<Fixed>
Thanks ill keep that in mind
have you played with making a collide and slide algo for the engine?
Not yet, but I want to
the repo has a few character controller examples but they're not quite collide and slide
Im trying to play with making one do you think it is something that should be done in the physics substep or just in the normal update loop?
I'd say in the substepping loop, but the spatial query pipeline is currently updated just once per frame so ray casts and shape casts wouldn't have the latest state at each substep
So maybe something where the movement and collisions use substeps, but environment checks via spatial queries would only be done once per frame
I haven't looked too deeply at how collide and slide works yet
or hmm, you probably don't need substeps since you know how much the character can move before hitting something (I think)
since you cast beforehand
Yea I beleve so I was worryed about the pos changing between calls to collide and slide but ig it dose not matter as the it is a look ahead algo.
yeah afaik Rapier also just casts the shape and moves the character by the amount it is allowed to move, either freely if there are no obstacles, or to the time of impact
and then has some logic for applying collision impulses
the only thing I would be worried about is the case where the collide and slide ends and then the engine pushes the player into a wall between frames and then collide and slide would get confused but ig that could be mitigated by just setting the pos and manageing the vel vec ourselfs.
Why would the engine push the player into a wall? If it's a kinematic body
Me setting the lin vel and then the engine moveing it into a wall during the substep but that might be a missunderstand on my part
Yeah if you set lin vel then the engine will move it
but with collide and slide I imagine you can just set the position directly
Yea thats kinda what I was saying.
I've been abusing bevy_eventlistener pretty heavily in a project, and I suddenly had this crazy urge to use it for sensor collision detection
I'm not sure whether it can be done as a third-party solution though, would a PR be accepted? It would obv be feature gated
are there any plans for [bevy_xpbd new name here] to be upstreamed in the future? that would be so boss
It's been discussed. Bevy would like a first-party physics solution, but it's blocked on a number of things, and <officialAnswer>bevy_xpbd's next iteration may become a suitable solution, but isn't necessarily the solution we'll go with.</officialAnswer>
I personally think it's a shoe-in, it's more ECS-ey than any other solution and it's based on an incredibly capable solver and is generally well-written and could be maintained fairly easily if Jondolf decides to get hit by a bus or just stop maintaining it. I wouldn't be surprised if it got upstreamed. And I might be a bit surprised if something else got upstreamed.
That's what I'm saying, no shade to the maintainers of bevy_rapier, but xpbd feels far more ergonomic
There's an issue for bevy_eventlistener entity event support. I think it'd be pretty hype to support it and it'd make a lot of patterns much nicer. Afaik the plan for Bevy is to upstream bevy_eventlistener as a part of upstreaming bevy_mod_picking (see https://discord.com/channels/691052431525675048/1236111180624297984), and that's very likely to happen during the next release cycle, so I'd probably wait for that
And yeah JoshValjosh's answer is pretty accurate. My personal goal is of course to get it upstreamed down the road, but there's still a few blockers and things we need to work on.
- Some pretty fundamental physics engine things like simulation islands are missing (I plan on implementing this after the upcoming release though)
- There's a ton of optimization we can do, the current performance just isn't good enough
- There are still relatively major features that haven't been implemented, like joint motors (and a character controller if we want it first-party)
- Ideally we don't want Nalgebra in our dependency tree since duplicate math libraries are confusing and add complexity; this is much trickier for Rapier, but we also depend on Parry currently
- bevy_xpbd still uses XPBD, which has some legal ambiguities, although we did get an "I believe it should be okay" from one of the inventors. The next version replaces XPBD for contacts with another solver, but joints still use XPBD for now (might get replaced later on as well)
- Bevy probably doesn't want an f64 feature flag, but we need some solution for large worlds. I plan on experimenting with built-in floating origin support for this.
- I'm not sure if Bevy would like the way both Rapier and bevy_xpbd handle the 2D/3D split with a somewhat questionable crate structure. I think alternatives are worth trying out.
bevy_rapier is currently more advanced in terms of performance and its feature set, but I feel like it just won't be able to get to the same level of nativeness and check all the marks, especially without compromising other consumers of Rapier itself. I think we have a better shot at that, but we'll just have to wait and see :P Rapier is also working on improving their docs and ergonomics
shapes/volumes and casts were added without upstreaming, right? maybe it'll be possible to build on top of that in smaller chunks
as in, build on top of Bevy's shapes and casting stuff to eventually replace Parry?
Bevy's casts don't return normals yet and are just for the bounding volumes currently, but that's my plan yea
yeah, everything has a feature creep just in case it's needed, but the core that's commonly used by everyone isn't really that big
for collisions we do need a ton of things, especially if we want to keep trimesh colliders and convex polyhedra (and convex decomp) which are pretty important for 3D
we don't need everything Parry has, but most of it we do unless we want to remove existing functionality in bevy_xpbd and drop support for some shapes
Even if you got normals from bounding volumes they would be pretty useless π
Yeah for bounding volumes it wouldn't be very useful, but we probably want proper ray casting and shape casting for the primitives eventually
Can't wait to implement collider support for extruded shapes π₯²
I feel like it shouldn't be too bad tbh
The implementation for SDF collisions is trivial at least, I just check for the 2d plane and the height separately π€
Some should be pretty trivial to do at least with support mapping, like extruded capsules and ellipses, but a "proper" solution would probably do polygonal feature mapping for a lot of the shapes (identify the intersecting features and compute the contact(s) for them)
for extruded rectangles and circles you could of course reuse cuboid and cylinder stuff
Makes sense! I did want to pick your brain on something... eventlistener wants to send two events per collision, but right now xpbd only sends one for a pair. After trying a few things, my favorite solution was to just create a new event type, say EntityCollisionStarted, and impl EntityEvent for that. That way we can send CollisionStarted in the same way without breaking existing usages. Does that sound reasonable?
Yeah, something like that sounds reasonable. I've also been considering just removing the per-pair collision events since you could technically use the Collisions resource for that, but it'd probably be a bit more expensive to do from the user side so I'm not sure yet
I don't really like that we're currently sending events for every collision, since it leads to copying a ton of data unnecessarily
What's the solution for that? Requesting specific collision notifications or something?
If we keep the per-pair collision events, we could add a component like ActiveCollisionEvents for enabling them for an entity (iirc Rapier has something like that), and for entity events we could potentially send events only for entities that have a listener in the hierarchy
I'm running into some weird joint issues if anyone has time to take a look https://github.com/spooky-th-ghost/tripwire I'm essentially trying to make a physical chain out of a bunch of linked distance joints here
Contribute to spooky-th-ghost/tripwire development by creating an account on GitHub.
the main thing I'm seeing is that with certain values I haven't pinned down yet, the player and all of the joints have their transforms all set to infinity
Without testing, my guess would be that the joint anchors don't match
That seems like a solid guess, here is the loop where I'm spawning the chain segments and anchors:
for i in 0..chain_iterations {
let previous_entity = next_entity;
let translation = segment_translation(i);
next_entity = commands
.spawn((
PbrBundle {
mesh: meshes.add(Capsule3d {
radius: 0.125,
half_length: 0.125,
}),
material: materials.add(Color::BLUE),
transform: Transform::from_translation(translation),
..default()
},
RigidBody::Dynamic,
Collider::capsule(0.5, 0.25),
chain_layers,
Name::from("Link"),
))
.id();
commands.spawn(
DistanceJoint::new(previous_entity, next_entity)
.with_limits(0.01, 0.05)
.with_local_anchor_1(Vec3::Y)
.with_local_anchor_2(Vec3::NEG_Y),
);
}
It's a bit annoying to tune but basically you want to make sure that position1 + rotation1 * local_anchor1 == position2 + rotation2 * local_anchor2 in the initial state
ahh, so the issue is likely with my initial rotations?
If the bodies aren't rotated then it doesn't matter, you just need to ensure that the global positions of the anchors match
I'll clone that repo real quick and test things
thanks, I'm trying to tweak it now as well, setup() is essentially the only relevant system at the moment
Btw @thin hare you switched from Rapier, right? Rapier uses half-extents for cuboid colliders and things like capsule height, but xpbd uses full extents to match Bevy's shape constructors
so that could be related
yeah, I'm still going through and making sure to correct some of those mismatches
also setting the joint compliance higher like .with_compliance(0.01) makes it less stiff so it doesn't immediately explode and you can see what's going on
the chain parts also use capsule colliders almost the size of the player (just thinner), not sure if that's expected, and the anchors are Y and NEG_Y even though the chain goes sideways
I was just being lazy on that front and assuming the colliders would rotate, and yeah I increased the segment size was because I was using the debug renderer at first and it seemed to panic if the colliders were too small
hm, interesting that it panics, I'll have to look into that at some point
it didn't look like it was an issue with bevy_xpbd itself, i believe the issue was in dims
i can check now actually
thread 'Compute Task Pool (0)' panicked at /home/spooky/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_math-0.13.2/src/primitives/dim3.rs:40:9:
assertion failed: value.is_normalized()
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `bevy_xpbd_3d::plugins::debug::debug_render_axes`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
ah yea I think that should be fixed once Bevy 0.14 is released, it's related to unnormalized values causing crashes for sphere gizmos iirc
for the joint anchors are they relative to the colliders size, or just universal vectors
like if i have a cube with a width of 4, does Vec3::X translate to (2.0,0,0) or (1.0,0,0)
the latter
they're just offsets for the attachment point in the local space of the given body
relative to the center of the body
Cool, thanks!
Any idea what could be causing the ray hit to be way at the bottom of the shape I am colliding with (the yellow arrow is the hit normal)
@vestal minnow Iβm not really sure what is causing the raycast result to end up so far away from where the cast originates as the max length should be capped as the max velocity.
How are you getting the point?
here is the full algo
let mut snap_to_surface = dir * (hit.time_of_impact - 0.001);
gizmos.arrow(origin + snap_to_surface + hit.point2, origin + snap_to_surface + hit.point2 + floor_normal, Color::YELLOW);
That looks fine to me... I'm on mobile rn so it's a bit hard to read the code properly, but I'll check in a bit when I get back to my computer
One thing to note is that the points and normals are in local space, but if the shapes aren't rotated then it shouldn't matter
yea the cast are hard coded to Quat::default()
Yeah I'm not seeing anything wrong here. Does it still produce wrong results if you remove the + hit.point2?
of course it won't be exactly correct but at least the point shouldn't be far away like that
I mean it makes it right in the center of the player but it is still wrong
is the time of impact large there then? could log the values to check
I don't see how the point would otherwise be so far away
It'd just mean that the velocity is large too for whatever reason
Time of inpact is 0
okay... is the origin wrong?
and when the arrow is moving around that is me trying to move the char
I'll try to repro this
I went ahead and dmed you my repo if you want to use it to repro
Thanks! I'll try that
Anyone able to point me in the right direction for making this chain less elastic? I need it to impede movement if the player goes to far but:
- Stiffer, less stretching of the chain
- Get rid of the snap back behavior
I know a single distance joint will do that pretty reliably, but I want to be able to have the chain links have collision for wrapping around objects,
Joint code below
commands.spawn(
DistanceJoint::new(previous_entity, next_entity)
.with_limits(0.01, 0.1)
.with_local_anchor_1(Vec3::Y * 0.5)
.with_local_anchor_2(Vec3::NEG_Y * 0.5)
.with_compliance(0.001)
.with_linear_velocity_damping(50.0)
.with_angular_velocity_damping(10.0)
.with_rest_length(0.05),
);
Also should this be a spherical joint? the docs mention those being good for chains so I'm trying to tweak that now
A distance joint is fine, a spherical joint would mainly allow the swing angle to be limited
Making the compliance (inverse of stiffness) smaller should make the joints more rigid and less springy. It's strange that the snap-back effect is so strong though, maybe the player is too light relative to the chain segments? Could try increasing its mass or making the chain lighter (with ColliderDensity for example)
Hmm, making the chain lighter makes things more elastic, going to try making the player heavier now
Heavier player is a little better but the chain is still very elastic
Lowering the compliance past 0.001 makes everything fly off with infinite values
I've been working with ldtk, and previously hand-rolled my movement/collision. I was able to mashup the kinematic_character_2d example to get decent results, but I notice I can jump and stick to the walls π€£
Effectively, the player character is the same as in the example (minus the max slope angle, which I omitted). Each tile from the LDtk level that's tagged a certain way got a rect collider and static rigid body attached.
Hoping there's some concept I can use to avoid this. Sticking to the walls is cute, but not desirable π₯Ή
Not sure what the options might be. Maybe there's some sort of repulsion force I can put on the tiles to avoid penetration? Idk.
Now that I am here explaining the problem, I wonder if part of this is because the character is being π€ Negative. Grounded when the shape caster hits the top side of any of the lower tiles making up the wall.Grounded is not present when sticking to the wall.
Okay, unsurprisingly when I put the max slope angle back in, everything works as expected. Seems like I was incorrectly resetting the Y velocity in the collision system. I just set the max angle to something small and this works-ish. There's still a little stick, but not enough to be a concern.
Now I have one more issue to smoke out re: the Z values not working like they did for moving this between tileset layers. No clue how that broke. Possibly something with the Position/Transform syncing? Not sure.
I'd like to use bevy_xpbd for pixel-perfect collision on a very large bitmap. Wondering if it makes the most sense to just impl AnyCollider instead of trying to compute a precise polyline/trimesh? It's for a worms-like game, so being able to quickly modify the bitmap every frame without needing to re-compute collider shapes would be ideal.
I suppose with AnyCollider you can only compute collisions with Self, so I would need my own top-level Collider wrapper if I wanted to have the bitmap and parry shape colliders interact?
There is https://github.com/bevyengine/bevy/pull/13346 which adds Aabb support for them. That still needs reviews though π
1k <3
It's also possible to create custom shapes for Parry but I'm not sure how easy it'd be for a bitmap like this.
There's a couple of examples of custom collider shapes here though (like the ellipse)
https://github.com/Jondolf/bevy_xpbd/blob/main/src%2Fplugins%2Fcollision%2Fcollider%2Fparry%2Fprimitives2d.rs
Hi all, I have just started learning bevy and have been messing around with bevy_xpbd. Huge thanks to @vestal minnow for the awesome crate!
That said, I have a super beginner question.
I am attempting to make a game with ball collisions roughly similar to the game of pool/snooker, but I can't quite seem to get the physics right.
I have a minimal example where I have 1 ball which hits another ball with some backspin.
When the ball collides with the other ball I would like it to grip the plane it's on and spin back.
I am not sure if my physics setup is incorrect, or if this isn't really possible to achieve using sphere and cuboid colliders (since obviously in real life the balls aren't perfectly spherical).
If someone could point me in the right direction that would be greatly appreciated.
I have attached a GIF and the code I am using.
Aha - if I set the restitution to 1.0 for the balls then it behaves much more like I'd expect!
Darn I was just about to suggest more bounciness
Has anyone tried messing around with SoftBody physics in xpbd?
Hi, any plans to support bigspace?
Yep, I have plans to experiment with built-in big_space support soon-ish
There's already a fork with basic support, but afaik it doesn't work if you have multiple origins (like for multiplayer)
FYI: multiple floating origins on the same client has an open PR: https://github.com/aevyrie/big_space/pull/22
For server side, you don't need the floating origin at all, that is purely for rendering.
(also side note for y'all: I'm on a vacation in Rome until Sunday so I can't code and might not respond like normal)
I needed to upgrade to bevy track and alongside had to hack xpbd to work with bevy track. Biggest problem rn is deps - need a not yet merged branch of nalgebra and need parry to update to it. Otherwise needed fixes mostly to colors. Should I send a PR to the branch that you used for bevy track?
so it compiles locally with patch.crates-io, but also needs that for any consumers ofc.
also can't upgrade to latest parry, works with v13 tops
or like, one can, but I don't know enough physics for that
how do i prevent explosive behavior? i already have restitution at 0, so that shouldnt be the issue
Depends on whats causing the explosive behavior
overlapping of objects
maybe restricting max lin vel could work
but that doesnt seem like really optimal
You stop explosions from overlapping by not overlapping them ... I've heard mentions that explosions should be less bad with the new solver (which we hopefully get soon) tho
Question what can make a collider sometimes not work? I am pretty sure I am not movin it via transform
Man this is some bologni
This guy be like not working but then when I videotape him he starts workibng
What do you mean by "not work"?
He doesnt collider
like i move him via velocity he colliders
but via forces he bugs out idk
OHHHH
i figured it out it has something to do with adding forces
If it's related to forces it could have something to do with the physics running on a different clock than Update?
You are probable right I guess the force system runs after update perhaps
Need to check xpbd systems
By default xpbd runs a 60Hz loop in PostUpdate. This means that if your FPS is lower than 60, it runs multiple physics updates per frame sometimes, if it's higher than 60 it doesn't run any physics updates some frames, and if it's roughly the same it can go either way, or remain perfectly stable for a while
oh i see
I should probably utilize fixed step in this case then no, specially since i am using a pid controller for my hitboxes and boio there are a lot of them
FixedUpdate (or well all schedules in FixedMain I guess) is generally the way to go. I'd really like to see the remaining footguns removed and for it to become the standard approach. It hasn't been moving along super fast tho since it's mostly just networking people pushing for fixed step stuff
They somehow do that on their own, shrug (whenever a lot of them are colliding at a short distance of each other)
Also why does that even happen? Cant i just disable that specific mechanism or scale it down?
If its not restitution what else might be responsible for this?
It's the penetration constraint that's doing them ... It just yeets things away from eachother to stop them from overlapping ... There might be various bugs in other systems involved that cause it
Jondolf fixed a whole bunch of issues on the new solver iirc, some of those could definitely cause overlaps in the right circumstances π€
Man this bug is hella annoying it doesnt even occur in high fps how in tarnation i fix this
It even detects the collision but just doesnt handle it
so then cant i limit the velocity objects can gain from the penetration constraint?
should be a fairly easy fix i feel like

In theory yes, but it could have other side effects, like overlap not being resolved or things that should go fast not going fast
In general, physics engines have to resolve overlap to have functioning contacts. Otherwise bodies could just sink into each other. The thing that is different is the approach used for solving the overlap.
XPBD solves contacts at the position level by moving overlapping bodies apart, and then updates the velocity based on the magnitude of the positional correction. Then it applies a velocity correction to account for restitution.
An impulse-based solver (like the upcoming one) applies an impulse to prevent further overlap, and also (typically) boosts that impulse based on the current penetration depth to solve the overlap.
The new solver should have less explosiveness and solve the overlap more smoothly. I might also expose more configuration options, like a maximum bound for the magnitude of the correction impulse.
so until the new solver is ready, wouldnt it be possible to resolve this by not having the object accelerate but instead keep a constant velocity while resolving penetrations?
It might be possible yes, but you'd need to plug into a pretty specific part of the solver to make it work properly
(brb in 5 to 10 minutes)
is there any way to filter collision events by the components that the two entities have? currently, the way im handling this is by doing queries of the components that i want and checking if the entities within the collision are part of that query, but because theres no order for the entities in a collision, i also have to check both ways. this seems a little hacky and i was wondering if there was a more idiomatic way of doing this
totally reasonable. Im guessing its prob the most reasonable to directly modify the penetration constraint itself?
Also the new solver should hopefully be ready in tandem with the 0.14 release
You could use CollidingEntities maybe?
New solver tomorrow?? π
not the rc
i actually did try doing that, but i want to only have code be executed at the start of a collision
and colliding entities made it so that every single frame two entities were colliding, the code was executed
as an example, heres what a version of my code looks like right now:
pub fn normal_damage(
mut collision_reader: EventReader<CollisionStarted>,
damage: Query<&Damage>,
mut health: Query<&mut Health>,
) {
for CollisionStarted(entity1, entity2) in collision_reader.read() {
for (entity1, entity2) in [(entity1, entity2), (entity2, entity1)] {
if let (Ok(damage), Ok(health)) = (damage.get(*entity1), health.get(*entity2)) {
health.value -= damage.value;
}
}
}
}
and here's something along the lines of what i want to do:
pub fn normal_damage(
mut collision_reader: EventReader<CollisionStarted<Damage, Health>>,
damage: Query<&Damage>,
mut health: Query<&mut Health>,
) {
for CollisionStarted(damage_entity, health_entity) in collision_reader.read() {
let damage = damage.get(damage_entity).unwrap();
let health = health.get(health_entity).unwrap();
health.value -= damage.value;
}
}
You can query for a marker component unique to that entity
lol funny enough thats actually exactly what i had before trying to change it around a little bit, heres the part of the code:
#[derive(Event)]
pub struct HitHurtCollision {
hitbox: Entity,
hurtbox: Entity,
}
pub fn get_hit_hurt_collisions(
mut collision_reader: EventReader<CollisionStarted>,
mut hit_hurt_collision_writer: EventWriter<HitHurtCollision>,
hitboxes: Query<&Hitbox>,
hurtboxes: Query<&Hurtbox>,
) {
for CollisionStarted(entity1, entity2) in collision_reader.read() {
// #1124043933886976171 message
for (hitbox, hurtbox) in [(*entity1, *entity2), (*entity2, *entity1)] {
if hitboxes.contains(hitbox) && hurtboxes.contains(hurtbox) {
hit_hurt_collision_writer.send(HitHurtCollision { hitbox, hurtbox });
}
}
}
}
pub fn normal_damage(
mut hit_hurt_collision_reader: EventReader<HitHurtCollision>,
hitboxes: Query<&Damage, With<Hitbox>>,
mut hurtboxes: Query<&mut Health, With<Hurtbox>>,
) {
for HitHurtCollision { hitbox, hurtbox } in hit_hurt_collision_reader.read() {
if let (Ok(damage), Ok(health)) = (hitboxes.get(*hitbox), hitboxes.get(*hurtbox)) {
health.value -= damage.value
}
}
}
i just thought it wouldnt be super convenient to have to attach the hitbox and hurtbox components all the time
Another way is to create a resource
Easier to acess multiple time in my opinion
Something like a hashmap with a name pointing to your entity
#[derive(Resource)]
pub struct HitboxAcessor(pub HashMap<String, Entity>);
I'm not aware of a much nicer pattern right now, no. I'm not really sure how we could nicely (and efficiently) add query filters for collisions like the API you proposed, although I would be interested if someone figures out a nice solution.
Something that we might add in the future though is entity events for collisions with something like bevy_eventlistener, which would allow you to listen for collisions for specific entities by just attaching event listeners for them
It even makes sense if the damage could work both ways
yeah that sounds interesting
This would probably require you to fork the crate since a lot of the solver systems depend on the existing penetration constraint type. Or I guess you could maybe copy just the solver and make your own modified plugin, but that might be a pain
in my case tho the damage only goes one way
so maybe it would actually make more sense to always have the Hitbox and Hurtbox components
maybe a method like this?
pub fn damage(
mut collision_reader: EventReader<CollisionStarted>,
hitboxes: Query<&Damage>,
mut hurtboxes: Query<&mut Health>,
) {
for CollisionStarted(damage, health) in collision_reader.read().filter_components(Damage, Health) {
// ...
}
}
The velocity correction part is in update_lin_vel (and the ang vel version) you could potentially clamp the velocity there
i think another thing that bothers me a little is that the collisions don't really have an order, so you always have to do some type of workaround such as for (entity1, entity2) in [(entity1, entity2), (entity2, entity1)]
Tho wouldnt it be better to instead clamp directly in the constraint impl?
so it doesnt affect the other constraints

I'm probably changing this so that the entity with the lower entity ID is always first in the collision data
But I probably still wouldn't recommend relying on a specific order
in case it's changed later on
The penetration constraint itself doesn't touch velocity since the overlap is resolved at a position-level. But it does still apply positional impulses (meaning just a change in position) so you could also clamp that to limit the correction done within a single frame/substep
also bumping this ^
I'm happy to answer things in the evenings but I literally don't have access to a computer so I'm a bit limited in what I can do currently :P
im having an issue where a collision seems to send two CollisionStarted events, is this intentional?
prob fired from both perspectives of the collision pair
after a bit more testing tho now it seems to be sometimes firing once and sometimes firing twice βΉοΈ
ugh ok
heres the code im using to test this btw
pub fn test_collisions(
mut collision_reader: EventReader<CollisionStarted>
) {
for _ in collision_reader.read() {
println!("thing happened");
}
}
running in update, and only two entities have collider components
That is usually caused by the type of collider you have
For example if you are utilizing a trimesh collider that can occur. Because of the proximity of two vertices
Do you also get CollisionEnded events in between or is it just two CollisionStarted events for the same pair of entities in a row?
And are the entities in the same order in both events
Physics also runs at a fixed 60 Hz by default so it can sometimes run multiple times per frame, which in Update could look like it's firing twice (assuming the entities do actually stop and start colliding in between the physics frames)
Oh yeah that is something i meant to ask how can I make my schedule run at the same fixed rate as the physical engine?
BEcause fixeupdate in bevy is 64 hz
Should i just set it to 60?
You can either add your systems to the actual PhysicsSchedule or configure physics to run in FixedUpdate and just use that
it's also possible to configure the physics time step
I'll pull up docs real quick
Oh man I would personally love you if you did so
Eh, there's not as much documentation for this as I thought but here's some
Running physics in custom schedules:
https://docs.rs/bevy_xpbd_3d/latest/bevy_xpbd_3d/plugins/struct.PhysicsPlugins.html#custom-schedule
Physics timestep configuration:
https://docs.rs/bevy_xpbd_3d/latest/bevy_xpbd_3d/plugins/setup/struct.Physics.html#
Running in PhysicsSchedule might be fiddly since you need to order your systems relative to actual physics systems or system sets to avoid conflicting queries or system ordering issues, so I'd probably run physics in FixedUpdate. That'll most likely also become the default at some point, at least once some of the remaining caveats are fixed
So just set it to 60 hz and chabam?
You can keep it at 64 Hz too, physics doesn't have to be 60 Hz
One weirder thing that you might need is to configure Time::new_with(Physics::fixed_once_hz(64.0)) when running physics in FixedUpdate since you might get issues with two separate fixed timesteps (FixedUpdate and the engine's own default fixed timestep)
I'll most likely try to make it Just Workβ’ in FixedUpdate for next release though
since needing to use the fixed_once_hz thing is kinda footgunny/weird
it is weird
My colliders go shabalabingbomm when the rates differ, but with higher fpss they dont. Hard to understand what is happening
i believe it's just two CollisionStarted for the same two entities, and the entities are in different orders. printed lines are:
started: 3v1, 4v1
started: 4v1, 3v1
ended: 3v1, 4v1
ended: 4v1, 3v1
started: 3v1, 5v1
started: 5v1, 3v1
ended: 3v1, 5v1
ended: 5v1, 3v1
code to test:
pub fn test_collisions(
mut collision_reader: EventReader<CollisionStarted>,
mut collision_reader2: EventReader<CollisionEnded>
) {
for CollisionStarted(entity1, entity2) in collision_reader.read() {
println!("started: {:?}, {:?}", entity1, entity2);
}
for CollisionEnded(entity1, entity2) in collision_reader2.read() {
println!("ended: {:?}, {:?}", entity1, entity2);
}
}
With the implementation in 0.4, I believe the entity order is based on the relative positions of the X extents of the bodies, and that can change when the bodies move relative to each other. The different order is treated as a different collision pair even though really it is still the same two entities.
This might(?) be fixed in the upcoming release since the entity order is always the same with my current implementation (lower ID always first).
i see
is there any way for me to temporarily handle this in my code?
it does somewhat consistently fire two collision events, but occasionally it also fires only one :(
How do i get velocity before collision?
ps. Found the bug. I was using same entity and was confused why vectors the same after collision
@vestal minnow if you have time, could you tell me if its possible to make something like a broad phase check if we are colliding with anything before spawning? i wanna have randomized spawning but idrk how i would do that without actually spawning the entity first
Other people have done this using spatial queries I think π€
decided to investigate this bug a little bit more, and in this test project i made, i noticed that the collision is only triggered twice when the projectile is moving towards the left. i also noticed that when shooting exactly left, the second collision event occurs when the two colliders touch internally, but the further up/down i shot the projectile, the closer the event was triggered when the two colliders were touching externally.
not really sure if this is helpful info but hope its of aid somehow π
Anyone have any ideas for what I can do to make this chain stop going wild? (it is a chain of colliders connected by distance joints)
Can't quite tell what is making it jump like this at the low FPS ... Is the player moving around rapidly or is this the chain pulling back the player
If the player moves back towards the anchor the chain flies around unpredictably, and on occasion this will cause the app to crash
Do the colliders in the chain have any mass? What are the properties of your distance joints?
// Chain Segment
let new_primary = commands
.spawn((
PbrBundle {
mesh: meshes.add(Capsule3d {
radius: 0.125,
half_length: 0.25,
}),
material: materials.add(Color::BLUE),
transform: Transform::from_translation(spawn_translation)
.with_rotation(Quat::from_axis_angle(Vec3::Z, 90.0_f32.to_radians())),
..default()
},
ChainPrimary,
RigidBody::Dynamic,
Collider::capsule(0.5, 0.125),
Friction::new(1.0),
CollisionLayers::new(
ColLayer::PlayerWidget,
[ColLayer::Terrain, ColLayer::Object],
),
Segment,
Name::from("Link"),
))
.id();
// Joint
let new_final_joint_entity = commands
.spawn((
DistanceJoint::new(new_primary, target_entity)
.with_limits(0.0, 0.6)
.with_local_anchor_1(Vec3::Y * 0.5)
.with_local_anchor_2(Vec3::NEG_Y * 0.5)
.with_linear_velocity_damping(1.0)
.with_compliance(0.0),
FinalJoint,
))
.id();
@vestal minnow this might have come up before, but with the rebrand coming up, how should I go about naming crates based on XPBD? Should I name them xpbd_foo and then rebrand them as well or already go for something like avian_foo?
Also: do you have a Kofi or something set up? I couldnβt find anything and would like to chime in something small as a thank you for your work π
Second this, I would love to contribute to a kofi/patreon/github sponsor
Hello. I want to react to collisions before collided entity started moving;
I move fast, collide into enemy, get collision event - my velocity expected to be big vector, but target is full speed too after collision.
I want to capture moment when i have big velocity vector, but target velocity close to zero. How i can do that?
i wish parry had support for regular polygons :x
it would be way better serialization wise instead of having to serialize all the points
wonder if its possible to do this yourself :v
You could contruct the colliders based on bevy_math's primitives, then serialize those, there's a impl IntoCollider<Collider> for RegularPolygon
yep, but that uses ConvexPolygon::from_convex_hull under the hood
would have to impl a custom parry shape i guess
oh i guess you are suggesting not serializing the collider at all
misunderstood lol
yea thats an option, did that before but you end up having to sync those then
which is more annoying that wasting that bit of space lol
Yea, just load it from a different component if that exists, and only fall back to storing the points if you have no clue what shape it is
actually might not be as hard to do as i thought
they already kinda have support for this
i remember xpbd makes a custom shape for ellipses too or smth
could also get away with converting the collider into a convex polygon on the fly
oki I'm back from my vacation trip now, easing back into dev mode
For new crates, I'd probably just wait for the Avian release and name based on that. For existing crates, I would recommend rebranding as well, but I'll probably do one more bevy_xpbd release that is mostly just a version bump for 0.14 to ease migration, so there could also be one more xpbd_foo release for crates that want that
I should probably ping all the 3rd party xpbd crate authors when I do the actual rebrand π€ and post a follow-up about the current state in the original rebrand issue
@visual sparrow @thin hare I don't have that yet, but I'll try to get GitHub sponsors set up before the release π and thank you, I appreciate it!
Yup, ellipses have a custom shape since Parry doesn't have built-in support for them. A custom regular polygon collider should be pretty straightforward to implement too. It should be very similar to a convex polygon collider, but the fact that it's a regular polygon might allow some small optimizations and simplifications
I'll try to implement it now actually
Let me know if you run into any issues or have questions about it π
yo, would it be possible to use a joint as a way to keep the camera close to the player?
for third person
@vestal minnow do you know how i could make a collider for stellations? i feel like it would be necessary to create a compound shape by splitting off the triangles from the center polygon.. should i make a polyline or a trimesh from the vertices and then decompose?
(also im only really interested in doing that in 2d)
Objective
Currently, regular polygons don't have their own collider shape. Instead, the From<RegularPolygon> implementation computes the convex hull and creates a convex polygon from that...
Yeah, you'd need a compound collider, either by just manually composing a bunch of triangles or by using convex decomposition. I'm not sure how accurately convex decomp can handle very spikey and dense geometry though, I haven't tested
i mean it shouldnt be hard to compute a trimesh from a stellation, its just a bunch of triangles and a regular polygon which should be fairly easy to convert too
but ur saying that making a trimesh would be more optimal right?
No not necessarily, I'd probably make a compound collider from triangles and/or other polygons (not the same thing as an actual trimesh)
right
yea that makes sense
hmm I wonder if we should add built-in stellations for Bevy's regular polygon primitive
if u do that you would prob need to do that for 3d polyhedra too
which is a pain iirc
yeah we don't have a RegularPolyhedron either, might be worth adding
or ConvexRegularPolyhedron, i.e. just the platonic solids
hmm yea
there would also be the question of formalization for stellated regular polygons; do you include depth or do you use a constant factor for that
actually i might be totally off, seems like they arent actually defined by two circles but their number of vertices and the step size (according to wikipedia)
for 2D, it could be roughly like this
pub struct Star {
pub circumcircle: Circle,
pub vertices: usize,
pub density: usize, // >= 2
}
where vertices and density are p and q of the SchlΓ€fli symbol respectively and share no factors (enforced on construction probably)
hmm yea
didnt really think this through
https://en.wikipedia.org/wiki/File:Enneagon_stellations.svg
wasnt aware that they could overlap
always thought you could define them with two circles and the number of vertices which would get rid of the overlap issue
but apparently not
i guess as a simplification it would best to just represent them as regular polygons during collision and then render them correctly for now
FYI y'all, I made a bevy-0.14 branch targeting =0.14.0-rc.2 (and actual 0.14 once it's released)
pretty sure it's blocked on Parry getting updated to support Nalgebra with Glam 0.27 though
so it has a local crate path for now
oh and it's just the 0.14 update, doesn't have the rebrand/rework stuff yet
I'm now finally trying to replace the god-awful ColliderStorageMap thing with component lifecycle hooks, I've been waiting for this :P
Doesn't the = force it to be only that exact release? π€
You can specify 0.14.0-rc or 0.14.0-rc.2 and it should work. It's important to include the .0 tho, since the rcs are for 0.14.0, not 0.14
okay that works yea
once can use it with [patch], there is nalgebra branch with glam 27
so you could have a branch available with a disclaimer
seems like it should work soon
how's moving from parry looking?
is it still in plans?
I already have Nalgebra patched with that branch, but it doesn't fix Parry's Nalgebra version to match unless I'm just doing it wrong
it did for me, I didn't have to fork parry.
lemme check when I get back to pc
you should have same version of nalgerba in your deps
but then have patches override
if you depend on different nalgebra directly then it'll only override yours iirc
well I have this
[dependencies]
parry2d = { version = "0.15", optional = true }
parry2d-f64 = { version = "0.15", optional = true }
nalgebra = { version = "0.32", features = ["convert-glam025"], optional = true }
[patch.crates-io]
nalgebra = { git = "https://github.com/waywardmonkeys/nalgebra.git", branch = "support-glam-027", features = [
"convert-glam027",
], optional = true }
and it's not working. I also tried using the same git override for Nalgebra in the dependencies
I think patch only works at the binary level, not within libraries
Yeah I plan to work on it more and see where it ends up. I'll probably approach it more from the perspective of upstreaming geometric queries like ray casts, point queries, and so on to Bevy itself since that's wanted for Bevy anyway, and then the remaining stuff that is more controversial for upstreaming can maybe live in its own crate
It has been on the backburner for a while due to the xpbd rework, but I want to get back to working on it after 0.14 releases
doesnt bevy still use an old version of glam anyways?
It does work at the library level if you run examples, but it only applies on the final level
it uses 0.27 which that branch adds support for
The features should be in the [dependencies] block and not in the patch one tho I'm pretty sure π€
but Glam 0.28 was just released yesterday too :P
But the old version in [dependencies] doesn't have that feature
That's not quite how the patch.crates-io thing works tho ... It just modifies how crates are fetched instead of using crates.io
The version needs to match what you're pulling in in dependencies too
okay confusing phrasing, as examples are also binaries
Tests also work, same thing for things like cargo check/clippy, etc
it's better to say it only works in the top level Cargo.toml
Yea, it would be an absolute trainwreck if every level could do this π
Okay the patch works, but only if I make my own version of it targetting Nalgebra 0.32.5. The existing PR targets 0.32.3, because that's what Nalgebra's main branch uses, but they've already released 0.32.5 on a separate branch, and Parry uses that
the joy of dependencies
would be great to have bevy_math include what parry does indeed
is there rfc for it already?
Not really, and it's probably something better handled by a working group and implemented incrementally
yeah
Like maybe a "geometric query" working group that implements all the standard queries, like contact queries, intersection tests, distance queries, closest point queries, point projection, ray casts, and shape casts
is it really controversial tho? bevy already has rudimentary ray/shape casts
It's not controversial in the sense that I think there's reasonable consensus that we want these, but some of the details might be more controversial, like how we handle code duplication between 2D and 3D for GJK, Circle/Sphere, Rectangle/Cuboid, Triangle2d/Triangle3d, Segment2d/Segment3d, and so on
A lot of these queries can also be somewhat related and we basically need e.g. GJK and support mapping for some queries and shapes
So some kind of cohesive vision would be useful
And a working group could help with reviews and getting the implementation details right
Then for collision purposes we would also need support for things like convex polyhedra, a specialized triangle mesh representation, SAT helpers, a convex hull computation algorithm, convex decomposition, maybe voxelization...
And for the spatial query pipeline we need a good BVH
But these may be more controversial for upstreaming, at least until Bevy gets first-party physics (assuming it some day will)
how expensive is it to switch rigid body types between dynamic and kinematic?
Changing the rigid body type shouldn't have any extra cost afaik
Got this done after some pain with queries not being very usable in hooks. Now we can
the extra copy of all colliders and their transforms π
Looks like we can use observers to implement entity events for collisions pretty nicely, no bevy_eventlistener needed π
commands.spawn((
RigidBody::Dynamic,
Collider::cuboid(1.0, 1.0, 1.0),
Observer::new(
|trigger: Trigger<CollisionStarted>, mut query: Query<&mut LinearVelocity>| {
let entity = trigger.entity();
if let Ok(mut lin_vel) = query.get_mut(entity) {
// Do something idk
lin_vel.y = 100.0;
println!("Entity {:?} started colliding.", entity);
}
},
),
// ...
));
Doesn't have event bubbling of course but I don't necessarily want that for collision events anyway
Thatβs pretty exciting
Not sure I like that naming collision with βtrigger collidersβ in Unity
Though in this case I guess it works out lol
ah wait this doesn't quite work like I thought yet since it's a general observer and doesn't target just itself
you'd need to add .with_entity(entity) too I think
yeah this would need to be written like this...
let entity = commands
.spawn((
PbrBundle {
mesh: cube_mesh.clone(),
material: materials.add(Color::srgb(0.2, 0.7, 0.9)),
transform: Transform::from_xyz(0.0, 20.0, 0.0)
.with_scale(Vec3::splat(cube_size as f32)),
..default()
},
RigidBody::Dynamic,
Collider::cuboid(1.0, 1.0, 1.0),
))
.id();
commands.spawn(
Observer::new(
|trigger: Trigger<CollisionStarted>, mut query: Query<&mut LinearVelocity>| {
let entity = trigger.entity();
if let Ok(mut lin_vel) = query.get_mut(entity) {
// Do something idk
lin_vel.y = 2.0;
println!("Entity {:?} started colliding.", entity);
}
},
)
.with_entity(entity),
);
not sure if I like that observer components default to global observers
imo by default it should observe the entity it was added to since it's a component and components typically describe a single entity, not global behavior
of course observers added via app.observe() or world.observe() would be global by default though
we could probably add an intermediate abstraction for this, but having the component be global by default feels footgunny to me
Not sure if this answers your question(?) but what Iβve worked on in Unity/Unreal (consumer titles) generally uses a mix of systems. Event-based stuff like βwhen the player reaches this pointβ is OnTriggerEnter in almost all cases, but things that need more detailed responses generally ends up being sweeps + some kind of priority sorting.
What you had written looked great right up until you realised it was a global event. No idea how Trigger is implemented internally, but my gut reaction is that even if you could filter it seems like it wouldnβt be viable past a few hundred objects?
Iβll see if I can find anything detailing similar systems. None of the stuff Iβve worked on has any public info.
Iβm general, though, itβs βshape cast, register the collision with some manager + metadata, manager processes them in the proper orderβ where βproper orderβ is e.g. βthereβs a shield between the origin and this collision, so ignore itβ
(Iβd be willing to bet, though, that the majority of games donβt need to worry about it too much, fwiw)
You got any concrete examples? Iβll have a think. Even in ECS sometimes youβve just gotta bite the bullet and process things serially
In between the two of those I guess: what youβve got now and something you think will probably cause problems once you add it
A concrete example of a problem that we had and how we fixed it:
Shields would originally destroy projectiles (via OnTriggerEnter), which broke down for very fast projectiles that could overlap the player and the shield on the same frame
We changed it so that the shield was βjust another defence colliderβ and had the projectiles shapecast to be able to get ordered collisions
Ah, perfectly in line with the example I gave hehe
You can probably do the same with xpbdβs collision events as-is. I think it includes the toi? If it does youβd gather the relevant events, sort by toi, and then process them in order from there
there's the penetration depth but collisions have no toi in that sense
Jondolf can probably chime in here but I just looked and the events are only entity pairs. Maybe you can get the penetration amounts from collisions resource?
Ty π
Penetration depth doesnβt quite equal toi, but for simple shapes itβs probably close enough
For a sufficiently complex system youβre probably going to need a way to order the collisions in time (or as close as you can get to it; thereβs always odd outliers like things falling down onto horizontally moving projectiles) and some way to register processors for those collisions so that they can be executed in order for each collision. I canβt off the top of my head think of how to do that in an βECS-yβ way tbh. Maybe you can do something with one-shot systems or manually running schedules?
A coworker recommended I tell you to look at the Smash Brothers videos. He wasnβt specific but said theyβve got a lot of good information including stuff on collisions
Sec, googling the channel now. Sakurai puts out videos where he talks in great detail about how he thinks about games
Join Masahiro Sakurai, director of several Kirby games and the Super Smash Bros. series, as he reflects on his work in the games industry and offers insightful and easy-to-understand advice about game development.
The goal? To try and help make games around the world a little more fun!
- All Nintendo-related development materials and ROMs feat...
Yes I think itβs that one. Sorry, on a train atm and donβt have very fast internet
Will do
Yes thatβs the channel. One of the directors I primarily work with looooves to link those videos to people lol
The vast majority of stuff I work on is so heavily tied down with NDAs that we just canβt publish anything unfortunately π¦
Depends on the NDA. Sometimes they have βknow-howβ clauses too which would cover inner working even without code
Thereβs so much cool tech that goes into modern games and Iβm sure the vast majority of programmers want to share with anyone whoβll listen
The collision filtering/βdrop throughβ thing I made a PR for bevy_xpbd a while back was borne of me not being satisfied with the solution we used in one of our recent games and wanting to do it βrightβ haha
I need to send in a PR to rename that example, actually: itβs a two-way platform, but the file is named one-way oof
I guess so. I think that itβs a platform saves it. Would probably be good to separate it out into two so that anyone who just wants a one-way e.g. door doesnβt have to filter out the drop-through toggling code as well
Iβd probably use a collider in the target area and make sure that all players are present to do something like that
You mean soft platforms?
Or one-way pathways?
Iβm trying to think of what you mean but I donβt think Iβve actually played that many top-down games 0.o
Oh right right sorry
Right itβs 9pm and my train is finally arriving at my home station so time for me to collapse soon. Have yourselves good days/evenings/nights
Iβll have a look and poke some more coworkers to see if theyβve got any links etc I can share with you
hey everyone. regarding the collision started/ended eventreaders, i'm confused about the behaviour of when my player entity enters a sensor collider from the left side like in the video example. am i implementing it incorrectly?
source code: https://github.com/bngshk/collision_test
I'm wondering if it's possible for SpatialQuery::project_point to not project on to sub-colliders of a compound collider? In this video, the circle is the projected point where solid=false. It turns red when is_inside, otherwise it's green. My desired behavior is for the circle to always be on the edge between gray and black here.
@vestal minnow What exactly is the plan for 0.14 releases? Will we get one release with lots of changes, or a 0.13 -> 0.14 release with few changes, and then the whole rework? π€
Most likely
- Release
bevy_xpbd0.5, which is essentially the currentbevy-0.14branch, not many changes - Release
avian0.1 that has the whole rework
In terms of the rework, I just made an avian branch based on the bevy-0.14 branch. I'll make branches (and PRs) for the new stuff targeting that branch, and then at the end I'll merge all of that to main
Already made a rework-structure branch that has most of the new module structure and some other stuff
After that's merged to avian I'll try to somehow work the new solver, CCD, and so on into logical mergeable chunks
unless I just... make one mega PR lol
I don't think that's really possible, at least with SpatialQuery. Parry represents the compound collider as just a Vec with all the sub-shapes (and some acceleration structures), To project onto a specific one, you'd have to manually get that shape and do the projection onto it yourself.
What you could do (if possible) is something where you have a completely separate collider for the shape you want to project onto, maybe as a child collider
Hmm, or in this specific case you could maybe also do point projection onto just the AABBs of the colliders, assuming that the collider is axis-aligned. But IIRC we don't have a SpatialQuery method for that yet
avian is new name for the lib?
That's the current top candidate and very likely final name, yes
The logo/banner looks like this (might still get minor tweaks)
fancy lines depicting water ripples courtesy of @cinder summit :P
Ah okay bummer, but that makes sense, thank you. I may then revert to using a polyline that just wraps the terrain.
Tell me I'm reading too much into this or I'm getting fluid dynamics hints π
Kinda true but also not π Fluid dynamics is not something I have concrete plans for, but I did already implement a very basic but somewhat functional integration with Salva one weekend
#off-topic message
Wrote up a pretty lengthy status update for the original rebrand issue
https://github.com/Jondolf/bevy_xpbd/issues/346#issuecomment-2168141785
Thought it'd be good to have a coherent overview there as well, not just in bits and pieces on this Discord :P
After generating a collider with an AsyncCollider is there a way to get the size of it? like if i generate a collider for a cuboid of an arbitrary size am I able to fetch the extents of that computed collider?
Perfect!
the position you give doesn't matter if you're interested in just the size
No I think this is exactly what I needed
another follow up question, If I generate a collider for a simple shape, like a cuboid, i'm assuming there is no performance implication? Like it would functionally be the same as manually adding a Collider::cuboid
Like, if you gave an entity a mesh with a Cuboid shape and then used AsyncCollider to generate a collider for it?
Yeah
That isn't quite the same thing functionally, because the mesh created from the Cuboid doesn't technically know it is a cuboid, it just becomes a triangle mesh (Mesh) formed by vertices and indices. And similarly when a collider is generated from this Mesh, it doesn't actually know that it resembles a primitive shape based on the input, so it becomes a triangle mesh collider
(or it uses convex decomposition depending on your configuration)
A triangle mesh collider is less efficient than primitive shapes like cuboids, and it also has no real volume because the triangles are effectively infinitely thin, which is more prone to stability issues
So for a simple cube would a convex hull be more performant?
Collider::cuboid would be best, but yes a convex hull is also better
Question let say I want to make a collider that follow along an animation, should I make it a child of the bone or is better to point out his global transform and move it kinematically?
I dont know how inherited transforms are handled in the physics system
I'm not too familiar with bone setups and how this is typically handled, but child colliders do currently move with their parents, like how transforms normally work in Bevy
Rigid bodies as children of other entities are more cursed and I generally don't recommend using them
But yes for colliders, transform propagation should work properly
What I did was create multiple dynamic bodies, and move their velocities according to the global transforms. But it feels a little heavy.
I was between that and kinematicbodies.
Dont know which one to chose
with kinematic bodies you'd at least need to handle collisions manually, and the built-in joints wouldn't really work
depends on what you need
Just read through it. Great writeup, thanks π
I really really like the name Avian πͺ½
@vestal minnow til that bevy is a real word
and is bird related
and I pronounced it right heh
yeah haha
tho I do want to pronounce it beview
it is mentioned in the quick start guide
https://bevyengine.org/learn/quick-start/introduction/
i never read that lol
How can I do a manual intersection test between two colliders? Check if AnyCollider::contact_manifolds is empty?
There's a somewhat obscure intersection_test function
Thanks π
np!
Hey, I finally managed to set up this GitHub Sponsors thing :P
Does this look alright?
https://github.com/sponsors/Jondolf
Really lovely π
Are you okay if I promote this?
Also you should add this to Github Sponsors π
err, add this to Bevy People
Words are hard
I'm not exactly sure what to do for the tiers and goals though, I guess I could also add the bronze, silver, and gold tiers for companies, maybe with the "I'll add your company's logo to the README of bevy_xpbd" or something
Sure! And thanks :)
Yeah, I wouldn't worry too much about the tiers π
IME that's not why folks donate
yup
I also don't really have any tangible goals like "I can work on this full time!" since I'll be in university for several years anyway :P
One thing I do need to figure out though is whether other Finnish people can legally sponsor me
or if I need a money collecting permit or something
See the last paragraph of this
https://poliisi.fi/en/crowdfunding-and-money-collection-campaigns
Not sure if allowing Finnish people to donate is considered as "appealing to the Finnish public" even if I'm not specifically targeting them in particular
I've seen a couple of profiles do this "Do NOT donate to me if you are from Finland!!" thing but it feels weird
#bevy's local #physics whiz kid @[email protected] now has a Github Sponsor page to help support his #opensource work. Fresh out of highschool, I've been consistently impressed by how helpful, diligent and brilliant his work is. It's rare enough to find young contributors at that technical level but the attention to docs, API design and co...
cc @visual sparrow @thin hare since you asked about it <3
Gotta love how annoying crowdfunding can be with all sorts of regulation ... If I ever want to accomplish my goal of my game being a crowd funded project I'd basically need to go trough the same steps as if I were starting a business 
Sponsored β
If I cancel at some point, know that it is because I'm also a student haha
Wow, thank you so much! The first money I've made from doing this in my eight-ish years of hobbyist dev haha β€οΈ
Noted π
I really appreciate your work. After years of using rapier (and nphysics, back in the day), your physics stuff was such a breath of fresh air. My day-to-day experience with Bevy wouldnβt be what it is today without your work, and I thank you for that β€οΈ
As a tier 1 reward, I request the situation of "what can collide with what?" when using different permutations of Collider, Sensor, and RigidBody variants to be more clear π
Well that's simple ... Only colliders can collide with colliders 
If it has no collider it can't collide π§
But the more serious answer is that Sensor (or neither sensor nor rigid body) can't collide with anything (but can be found in spatial queries iirc) but do report collisions, while all rigid bodies can collide with eachother, except static-static doesn't do anything and kinematic doesn't have collision responses
I think anyway π€
Looks like I hadn't added myself to the list at all yet π Made a PR
https://github.com/bevyengine/bevy-community/pull/78
the fastest merge in the west
Why is your discord username (and that of many others) in the old format? 
the template and all the other ones use that so I followed suit π
Thanks, that helped a bit! Could you expand on when I have to add a Sensor? I'm asking because in my code, I have some hitboxes and hurtboxes with Collider but without any RigidBody and they seem to report collisions the same way no matter if they have a Sensor.
Is it correct if I assume that a Sensor modifies the behavior of whatever it is attached to to "report collisions as you normally would, but do not try to solve the resulting penetration"?
Side note @vestal minnow, is it intentional that a Collider with no RigidBody and no Sensor is not drawn by the debug gizmos, but a Collider with Sensor is?
Afaik Sensor vs no Sensor and no RigidBody is identical ... It's kind of strange behavior tho, just like how afaik you can't have a rigid body that doesn't show up in spatial queries
sponsored! tysm for all your hard work π
there were some articles about it somewhere, I'll ask on irc
I'd be careful
@vestal minnow eg EFF having their donation bank accounts available on website was classified as money collection
i'd at very least remove any mention of you being in Finland from github
@vestal minnow if you open an entity outside Finland (eg Estonia) you could do that freely tho
but ircs opinion was that being resident of Finland and having github sponsor is illegal
me and them are all not lawyers ofc lol
Hey @vestal minnow, what did you use for the speculative collision?
Or do you know any resources on implementing it?
My understanding is that it is only illegal to get sponsored by other Finnish residents
(see e.g. this, although they are not lawyers either)
I don't know if it would be enough if I just added that warning like "Do not donate to me if you are Finnish"
With that, I would consider myself to be "clearly limiting my appeal outside of Finland", but of course ultimately I cannot prevent people from donating
As for removing mentions that I'm Finnish, that just seems kinda shady and like I'm just hiding something
Unless I guess you count the mention that I'm Finnish as "appealing to the Finnish public"
you never know with Vero
fwiw tons of people do that, but also might be that they are just lucky
For now I just added that warning, my interpretation is that it should be enough. The Finnish wording translates more closely to:
You must have a money collection permit if the collection is directed towards Finland. The money collection is directed towards Finland if donations are intended to be received from the residents of Finland.
and I am explicitly stating that I don't want to receive donations from Finnish people. But yeah, all of this is hella ambiguous, so I'll probably look into it more still
I really wish we had a lawyer funded by the Bevy Foundation 
Wish I had a "perkele" emoji to react with. This is so silly π
that'd have to be a Finnish lawyer tbf
there is little overlap between us law and finnish law
if you are in union you could ask union lawyer
this is employment related in some way
My main reference is Box2D V3 (Box2c), and to a lesser extent Bepu and Rapier.
-
The speculative margin is the maximum distance at which a collision pair generates speculative contacts. This is unbounded for every rigid body by default, which eliminates almost all tunneling.
-
Each AABB is expanded in the movement direction based on the body's velocity, clamped by the speculative margin if it is bounded. (Box2D might have a way to avoid this expansion, but I haven't looked into it yet)
-
The effective speculative margin is the actual margin used for contact computation, and it is clamped based on the velocities.
// Compute the effective speculative margin, clamping it based on velocities and the maximum bound.
let effective_speculative_margin = {
let speculative_margin1 =
speculative_margin1.unwrap_or(*self.default_speculative_margin);
let speculative_margin2 =
speculative_margin2.unwrap_or(*self.default_speculative_margin);
let inv_delta_secs = delta_secs.recip();
// Clamp velocities to the maximum speculative margins.
if speculative_margin1 < Scalar::MAX {
lin_vel1 = lin_vel1.clamp_length_max(speculative_margin1 * inv_delta_secs);
}
if speculative_margin2 < Scalar::MAX {
lin_vel2 = lin_vel2.clamp_length_max(speculative_margin2 * inv_delta_secs);
}
// TODO: Check if AABBs intersect?
// Compute the effective margin based on how much the bodies
// are expected to move relative to each other.
delta_secs * (lin_vel1 - lin_vel2).length()
};
- Use that as the prediction distance (max distance) for the contact computation.
let contacts = self.compute_contacts(
&collider1,
&collider2,
effective_speculative_margin,
// Only match contacts if warm starting is enabled.
warm_start,
)?;
- Now, when you're actually solving the contact (normal part, no friction), use the softness parameters only if the contact is penetrating. Otherwise it is speculative, and we bias the impulse to cancel out the velocity that would cause penetration.
pub fn solve_impulse(
&mut self,
separation: Scalar,
relative_velocity: Vector,
normal: Vector,
use_bias: bool,
max_overlap_solve_velocity: Scalar,
delta_secs: Scalar,
) -> Scalar {
// Compute the relative velocity along the normal.
let normal_speed = relative_velocity.dot(normal);
// Compute the incremental normal impulse.
let mut impulse = if separation > 0.0 {
// Speculative contact: Push back the part of the velocity that would cause penetration.
-self.effective_mass * (normal_speed + separation / delta_secs)
} else if use_bias {
// Contact using bias: Incorporate softness parameters.
//
// 1. Velocity bias: Allows the constraint to solve overlap by boosting
// the constraint response a bit, taking into account the current overlap.
// This is known as Baumgarte stabilization.
//
// 2. Mass coefficient: Scales the effective mass "seen" by the constraint.
//
// 3. Impulse coefficient: Scales the accumulated impulse that is subtracted
// from the total impulse to prevent the total impulse from becoming too large.
//
// See the `softness_parameters` module for more details and references.
let bias = (self.softness.bias * separation).max(-max_overlap_solve_velocity);
let scaled_mass = self.softness.mass_scale * self.effective_mass;
let scaled_impulse = self.softness.impulse_scale * self.impulse;
-scaled_mass * (normal_speed + bias) - scaled_impulse
} else {
// This is useful for a "relaxation" phase which helps get rid of overshoot.
-self.effective_mass * normal_speed
};
// Clamp the accumulated impulse.
let new_impulse = (self.impulse + impulse).max(0.0);
impulse = new_impulse - self.impulse;
self.impulse = new_impulse;
// Return the clamped incremental normal impulse.
impulse
}
- Restitution is currently applied after constraint solving in a separate phase. The important thing here is that you store the relative speed along the normal from before contact solving (like when generating the constraints), and also check that the maximum applied impulse is non-zero to account for speculative contacts. See Box2c's restitution implementation.
I hope I didn't miss anything important π I did have to remove a couple of comments and small unrelated details
Oh and self.effective_mass here is what Box2c calls normalMass, it's the inverse of K, which mathematically is derived from the Jacobian using K = J * M^-1 * J^T where M is a mass matrix and ^T denotes a transpose. You don't need to worry about that implementation-wise though, Box2c has the formula for K
Oh wow this is way more than I was expecting, thanks
No problem π
@vestal minnow hello. im trying to get collision event right after it happend but before collided entity started moving.
What i mean (dont pay attention to logic, just telling whats going on):
body(A) moves towards body(B)
body(A) crashes into body(B). Body(B) flies away
I apply damage calculated from impact power and if body(A) velocity ~ 100 and body(B) velocity == 0 then body(B) gets huge damage while body(A) gets minimal damage from impact;
But:
when i react to Collision event, body(B) already have velocity close to -100 but i expect it to be 0;
How i can workaround this problem?
One way could be to use the Collisions resource in the PostProcessCollisions schedule. That runs after collision detection but before actually resolving the contacts and updating velocities
thank you β€οΈ
np π
@vestal minnow i managed to get valid velocity of both items, but now i get 3-4 invocations. I think im doing something wrong:
system registration in 1st screen
system in 2nd screen
logs after collision in 3rd screen
p.s. sorry for useless information on screen. But i wanted to show Res<Collisions> and is_first_occurence
Hmm so this might be because the collision detection is run at every substep in xpbd 0.4, and the collision might be getting solved over multiple substeps, so it's active for several runs of that system. This will be different in the next release though, which could potentially fix the issue...
I'm not sure what would be the best workaround, but you could maybe check if contacts.total_normal_impulse is zero to determine if it's the first substep
(I think you could also use this impulse to determine the impact strength in the Collision event like normal, instead of trying to determine it from velocities, unless you want to compute the impact in a custom way)
@vestal minnow thanks for suggestions. But for some reason normal impulse is always 0.0 for me
hmm okay
how i can try new release now? Should i change something in my code or just use master branch from github
It's not released quite yet, but should come in tandem with the Bevy 0.14 release
Okay other options for scuffed workarounds that could maybe work
-
An
IsFirstSubstep(bool)resource that you set totruein thePhysicsSchedulebefore the substepping loop with.before(PhysicsStepSet::Substeps)and then set tofalseat the end of yourcrash_into_smthsystem -
Go back to what you were doing before I suggested
PostProcessCollisions, but make aPreviousVelocitycomponent that you update for every rigid body before physics runs, and then use that instead ofLinearVelocity
I really wish the new solver stuff was released already though, I think all of this would be so much easier 
holy sh... this looks like a solution. I'll go try to implement it. I'll let you know how it ended
Trying out the avian branch with the current release candiate, but getting a strange not a bundle compile error:
`(MaterialMeshBundle<bevy::prelude::StandardMaterial>, RigidBody, Collider)` is not a `Bundle`
I really want to try the new solver, also tried the current release branch (of bevy) but that panicks at start.
I guess I just need to wait...
That branch doesn't have the new solver just yet, I'm in the process of making PRs to add it in chunks though
I have this massive local branch with over 50 commits over several months that I'm trying to break up into PRs π
i made it work with first solution. Thanks again
How stable is the new solver? Is it close to what rapier currently does?
I haven't had time to do comprehensive comparisons with Rapier yet, but yeah, it's pretty close. Box2D V3 has been my main reference though, so it's probably the closest equivalent stability-wise.
You can see the TGS Soft solver and how it compares to other solvers in Erin's Solver2D video. I have the pyramid and some other samples replicated as well, there's an old video of that here and others sprinkled elsewhere on the Discord probably :P
In this video I go over Solver2D results in detail.
Find the blog post here: https://box2d.org/posts/
Github repo: https://github.com/erincatto/solver2d
00:00 - Intro
00:31 - Parabolic Arch
03:56 - Confined Circles
07:44 - Double Domino Effect
09:41 - Friction Ramp
13:13 - High Mass Ratio 1
17:34 - High Mass Ratio 2
20:18 - Overlap Recovery
24:...
Some big differences from the old XPBD contact solver are:
- There's significantly less drift, and bodies settle down better. Previously things like the pyramid would just drift and collapse.
- Less substeps are needed for stability, which gives you better performance as well.
- Overlap is solved more smoothly and softly, which reduces explosive behavior.
- Contacts can overall be softer; this is a trade-off, but it's pretty important for stability. The softness can also be tuned, unlike before.
- Speculative collisions mean that there should be essentially no tunneling by default, outside of overlap caused by contact softness. This should be pretty huge.
- Narrow phase collision detection is only performed once per frame instead of once per substep, which gives a major performance boost. With XPBD, I think this would've caused stability issues (iirc I tried). Typically it would also increase tunneling, but with speculative collision it's not an issue.
And then the narrow phase rework also fixed several long-standing collision (event) bugs, and an impulse-based solver is in some other ways nicer to work with too, like you just have the contact impulses instead of having to compute them separately (users could also modify them technically)
Oh and triangle mesh colliders should be less buggy, both because of Parry updates and because I'm adding (optional) contact skins / collision margins like Rapier, which let you add artificial thickness to colliders, which can help with perf and stability in some cases
One thing that Rapier has and I don't is a block solver for 2D contacts, meaning that it can solve two contact points simultaneously, which helps give it some really stable box stacking; this is pretty niche though (Box2D even deliberately removed its block solver for SIMD optimizations) and 2D-only for now, because solving just two contacts at once in 3D can cause some other stability issues
And all of these also apply to 3d?
yes
I canβt wait to give it a try 
hehe I can't wait to get it released :P
I still have some annoying issues with a couple of new joint things I've been wanting to add, but if I can't get them working then I might just leave them for the next release to not delay things
hmm tomorrow I think I'll actually focus on getting everything else PR'd and merged first and leave the joint stuff last since it's overall less important and more WIP
That would be great, really want to try it, it will be targeting the 14 rc correct?
Ah the avian branch didn't compile for you right? So it's currently actually targeting the Bevy repo's release-0.14.0 branch, because rc.2 had a serialization bug which was making my CI fail. It should be fixed in rc.3 which to my understanding should be getting released very very soon
once that's out it will target the rc again
iirc Francois mentioned that rc.3 is blocked on at least this, which now has two approvals already
and ideally someone backporting the observer PR to the 0.14 branch
There was some issue with bevy, but I will try again tomorrow with a clean first.
Ok have it working targeting:
bevy = { git = "https://github.com/bevyengine/bevy", branch = "release-0.14.0" }
(which is the same branch the avian branch is targeting)
Got asked about how much the new solver will help with the tendency of overlapped spawning being explosive (and deep overlap just causing issues overall), so I thought I'd share a comparison here as well
Old solver:
New solver:
It's also a lot more configurable than before
Nice fluid simulation you got there π
How supported is it to have my own system inside the SubstepSchedule that modify ExternalForce?
I think you could do that, yes
You need the system to run before SubstepSet::Integrate
Note that the system sets and ordering will change a bit in the next release though
I see, thanks. But would something similar still be possible in the future?
Very curious to test how the new solver handles colliders changing scale over time.
Currently it leads to explosions, hopefully the new solver will handle it more graceful.
For best stability would the size change need to happen in fixed update ?
Yeah you'd use .before(IntegrationSet::Velocity) instead
in the next release
I think currently collider scale is actually applied internally in PostUpdate (or whatever schedule you run the PhysicsSchedule in) and not with a fixed time step... I might change that
But yes it should be more graceful
I'll actually test that in a bit
@quartz heart seems pretty good :)
just changing scale in Update here
(newly spawned boxes always have the same initial size in this demo)
Hope itβs available soon to test, I wanna try it too!
Itβs looking very promising!
Here's one with more shape variation where you can see what's happening better
I had an annoying bug while porting my old code that caused offset centers of masses to make bodies glide in the air and behave more like airplanes π managed to fix it though
I'll update some examples and docs, and do a couple more API tweaks, and then make that PR for the new solver
should hopefully be ready later today, and if not, then tomorrow
hmm, not sure what to do for the KCC examples since they used a (bad) position-based collision solve which is a lot more annoying to do now
ofc a collide-and-slide type thing would probably be better, but idk if I should revamp the examples that heavily
What's a KCC?
kinematic character controller