#Avian Physics

1 messages Β· Page 28 of 1

frail robin
#

Is it possible to disable physics picking at runtime?

vestal minnow
#

The picking backend was largely made to match Bevy's MeshPickingPlugin, which doesn't support toggling picking at runtime either. I would merge a PR adding an enabled property for PhysicsPickingSettings though

frail robin
#

Got it, thanks for the info!

vestal minnow
#

I'll look into this when I have time, though I am confused why this would be happening. The broad phase should already be filtering out collisions between static or sleeping entities

formal heart
jolly rover
vestal minnow
#

It's 3D but 2D works the same

hot osprey
formal galleon
#

What do I need to do to enable Collider picking? I enabled the "bevy_picking" feature of bevy and added the PhysicsPickingPlugin, but it doesn't work out of the box. Then I tried setting require_markers and added PhysicsPickable to the camera (which isn't the main/default camera on the default RenderLayer) and added the same component to the entity I want to pick. I already checked the collider of the entity with the PhysicsDebugPlugin, which seems fitting.

#

I believe the issue stems from having two different scenes in the same world - one for the normal game world and one for the inventory. While the objects in both scenes have different CollisionLayers, the camera used for picking doesn't have a CollisionLayer assigned. This likely means when picking, I'm hitting other large objects (like hills or trees) instead of the intended pick target. Is there a way to filter during picking, similar to how CollisionLayers work?

golden python
#

Hey, say I want to generate a collider for a polygon defined by the lines (Vec2, Vec2) that form it's outershell, what would be the way ? Collider::polyline ?

hexed veldt
#

When I insert an AngularVelocity to an mesh that is a child entity of another entity which has a non-identity rotation. The rotation applied to the mesh seems a bit off, i.e. it is applying the parent rotation as well. How can I apply an AngularVelocity to a child entity only at local level (excluding the parent transform impact)

dreamy viper
#

What are the resources that are used to compute the position/rotation of Colliders? Any resources that might need to be rolled back in time (on top of the collider entities) in the case of a network rollback?
(sorry I think i asked this before already)

dreamy viper
#

I realized that some resources that I was missing that might be important are Time<Physics> and Time<Substeps>

cinder summit
#

I haven't actually been able to avoid mispredictions at all with sleeping enabled however, since the waking logic uses change detection, and rollback will always trigger change detection

#

I assume the whole sleeping issue should get fixed once we get simulation islands, tho I'm not 100% sure about that

vestal minnow
cinder summit
#

Yea, it's especially noticable if the rollback doesn't even bother checking if the value actually changed before rolling back, since at that point it creates a situation where things never sleep

#

Because Position, Rotation, LinearVelocity, AngularVelocity, etc all get "changed" every frame

vestal minnow
#

Are rollbacks needed while the body is sleeping? Like can you just not roll back position and velocity etc. for sleeping bodies

cinder summit
#

In theory once it's sleeping it's fine if the sleep timer is longer than the window used for rollback, the issue is that the timer will get reset constantly and thus go to sleep/wake up at different times compared to the server

#

Which then manifests in slight differences in collision responses

vestal minnow
#

Right

dreamy viper
cinder summit
#

As for elapsed, I don't do anything with it, I'm not sure avian even uses it πŸ€”

dreamy viper
#

I see, yes it's a good call to switch Time<()> to be equal to Time<Fixed> before the rollback

#

Oh i already did that actually

vague pebble
#

@vestal minnow Hello curious what is this massive number

vestal minnow
vague pebble
#

ah i see tought i was doing something wrong

dreamy viper
#

@cinder summit for the Sleeping issue, I guess the ideal solution would be to reset the component value AND its ComponentTicks value so that it gets reset to exactly the same state as it was n frames ago in terms of ChangeDetection. Then if the entity was sleeping n frames ago, sleeping is not triggered even with the rollback

cinder summit
#

That's not actually ideal tho, then things won't be able to detect that the value did in fact change

dreamy viper
#

You mean in case the component had changed in our prediction, but when you rollback the component did not change at all?
I think that's what we want though, after rolling back the component fundamentally didn't change. The rollback itself shouldn't count as a change, we are just rewriting history

cinder summit
#

If there's a component or resource that only does something based on changed values, like say updating a spatial index with new Positions, we probably don't want to roll back that entire resource just so this hacky sleeping implementation works tho πŸ€”

dreamy viper
#

hmm..

vestal minnow
#

So we have this thing

#

I've been trying to figure out why the heck it's like that and not just this thonk

#

Also the old/current version is doing a lot of math like a + (b - a) like wut

bold garnet
#

is that bevy code?

vestal minnow
#

My code from July 2023 lol

#

in Avian

#

I had some weird reason for doing this in a convoluted way but I don't remember why and it makes no sense at all now

#

(this also seems to be part of the cause for a lot of the rotation denormalization issues people keep having)

vestal minnow
# vestal minnow So we have this thing

Fundamentally what this appears to be doing is

position.0 += transform.translation - previous_transform.translation;
rotation.0 = previous_transform.rotation.inverse() * transform.rotation * rotation.0;

but with a lot of extra steps lol

#

I don't understand why I wanted to add the change in transform though, rather than simply setting Position and Rotation to the actual new transform

#

I think I'll just test a bunch of scenarios with the simpler version and see if it has broken anything :P

#

If not, I'll make a PR

vestal minnow
#

Sleeping and change detection work fine with the new simpler version πŸ€·β€β™‚οΈ I legit have no clue why I originally made it like that, I'm confused

#

well, PR it is

vestal minnow
grizzled depot
#

Would a difference be that your simplification doesn’t retain previous β€˜z’ for 2d? Still I applaud such simplification πŸ‘

vestal minnow
#

The vecs get truncated to 2D anyway so it shouldn't matter

#

the z isn't used for anything here in 2D since Position stores a Vec2

grizzled depot
#

Still for graphics conserving Transform z might be useful I imagine ?

#

I mean yeah graphics should probably be a separate entity but eh

vestal minnow
#

Yes it's still conserved for the visual Transform and GlobalTransform, but this is just updating the Position component used by physics, where the Z coordinate doesn't matter

#

for 2D

#

Position and Rotation are like Rapier's internal RigidBodyPosition::position, and are kept in sync with the GlobalTransform used for rendering

#

components for the physics position must be separate from GlobalTransform, for now at least

dreamy viper
#

Is there something triggering change detection on Collisions every frame?

2025-01-10T23:51:48.392280Z  INFO lightyear::client::prediction::resource_history: Resource "avian3d::collision::Collisions" changed, adding to history
2025-01-10T23:51:48.392294Z  INFO avian_3d_character::shared: collisions tick=Tick(28) collisions=Some(Res(Collisions({})))
2025-01-10T23:51:48.400536Z  INFO lightyear::client::prediction::resource_history: Resource "avian3d::collision::Collisions" changed, adding to history
2025-01-10T23:51:48.400535Z  INFO avian_3d_character::shared: collisions tick=Tick(29) collisions=Some(Res(Collisions({})))
cinder summit
#

Doesn't Collisions just change every frame?

#

It recomputes collisions so it makes sense it would get triggered πŸ€”

#

I have a really nice solution for this in my rollback crate: I only store changes

dreamy viper
#

What do you mean by "I only store changes"? You don't use change detection?

#

When I disable the SleepingPlugin, my colliders fall through the floor (RigidBody::Static) for some reason

dreamy viper
#

Ok I managed to have no rollbacks for my player-controlled RigidBody, but for some reason when I add an extra non-controlled RigidBody I do have rollbacks on that one.

vestal minnow
#

Another mildly scuffed way to disable sleeping globally is to set the threshold(s) in the SleepingThreshold resource to be negative

dreamy viper
#

In my example https://github.com/cBournhonesque/lightyear/tree/main/examples%2Favian_3d_character, I don't have any rollbacks for the character controller but I have some for the inter boxes which are Cuboids.
If I just spawn a Cuboid I see constant rollbacks, and I see that it's Position/Velocities keep changing slightly. Is that expected? I would expect them to have 0 velocity, but they seem to twitch very slightly

vestal minnow
#

That's the second reason for sleeping (first reason is optimization), it allows objects to be properly resting instead of constantly moving slightly

dreamy viper
#

This doesn't explain why I keep getting constant rollback on that cube.. I don't know which component/resource I am missing. I just spawn a cube on client/server with no movement

vestal minnow
#

Contact solving is iterative and not exact. Even with a "block solver" that solved all contact points simultaneously, I doubt you'd get contact impulses that perfectly cancel out gravity to reach exactly zero velocity, especially with floating point math. You could maybe have some minimum velocity threshold for object movement though, where e.g. velocities below 1e-3 units per second get clamped to zero

dreamy viper
#

I see, so avian dynamics is deterministic but not contact solving?

vestal minnow
#

No engine for real-time applications has an exact solver, they're pretty much all iterative and approximate

dreamy viper
#

You have deterministic tests that check that run_cubes() gives the same result every ime. Does run_cubes() also include contacts?
I guess the tests are deterministic because the contacts are solved sequentially in the same order, but if I spawn the cubes in a different World maybe the contacts would be solved in a different order?

vestal minnow
#

(there's also a matching determinism_2d example you can run to see it visually)

vestal minnow
#

This could probably be tested by randomizing entity spawn order to make the IDs unstable across runs

dreamy viper
#

Yes i probably have something similar happening again. ClientWorld has more entities than the ServerWorld which might cause some hashmap to be iterated in a different order or something

vestal minnow
vestal minnow
dreamy viper
#

I think it's deterministic even with collisions when I only have one contact point. If I only have the main player (which is a capsule that collides with the floor), it is deterministic

#

So it might just be the order of iteration of contact points

vestal minnow
#

@dreamy viper It looks like it's definitely not deterministic if I shuffle the order of entity columns spawned in the determinism_2d example, which implies that entity ID order indeed affects things

dreamy viper
#

Is it something that I missed in my past PR?

vestal minnow
#

Not sure, I'm looking into it

vestal minnow
#

haven't found the source of non-determinism yet, I tried changing some things but it still produces different results for different entity orders

#

(and now I've been nerd sniped into writing JS to embed some tags into Bevy docs xD)

cinder summit
dreamy viper
#

I guess I was just surprised that change detection was triggered on Collisions even though the collisions were all empty

cinder summit
#

Yea it's trivially easy for change detection to trigger on resources with collections, you just iter_mut because you might need to change stuff, and then it triggers change detection despite having 0 entries or not actually mutating anything

#

We could bypass change detection for it, count the number of changes, then mark it changed if there were any πŸ€”

glacial nebula
#

related

#

The performance characteristics and easy of triggering when there is no change means I rarely use change detection in bevy, it's too brittle and slow. I'd much prefer it if I could opt-in to a slow path for certain components for granular detection that does equality checks and only iterates over the changed set.

formal galleon
vague pebble
#

Question, when inserting a dynamic rigidbody does avian, insert a series of aditional components too?

thin hare
#

is there a good way to deal with ejecting dynamic rigidbodies inside of another collider?

thin hare
#

These are the required components that get inserted alongside rigidbody, as long as they aren't already decalred on that entity

vestal minnow
twilit canopy
#

i'm super new to Bevy and was trying to just get a feel for stuff, play with some planets. Can't seem to understand why the collisions here aren't working though
Here's the full file
Thanks!

vestal minnow
# formal galleon I believe the issue stems from having two different scenes in the same world - o...

This could be related, yeah. There isn't a way to apply CollisionLayers to picking currently, but I would probably accept a PR that implements it. I guess the simplest approach would be to just have CollisionLayers on the camera entity and use that for the filter, but it's a bit weird since CollisionLayers has both "memberships" and "filters", but picking only cares about the filters to determine what layers it should consider πŸ€”

formal galleon
#

I worked around this by using the MeshPickingPlugin, but that's awkward, because if the player wants to pick / select a rotating small worm in my game, he needs to hit it exactly, obviously. A bigger collider and picking by physics would be great. I also think thats a really important feature for real world applications/games.

#

I never looked into the implementation details of avian, but if you think that would be cool, I would give it a try.

vestal minnow
#

Might want to add the PhysicsDebugPlugin to visualize the colliders and make sure they look like they're actually intersecting

twilit canopy
#

hmm, i was trying to scale everything in terms of Meters with realistically sized planets, so it is pretty large,
it does complain here
WARN avian3d::dynamics::rigid_body::mass_properties: Dynamic rigid body 19v1#4294967315 has no mass or inertia. This can cause NaN values. Consider adding a `MassPropertiesBundle` or a `Collider` with mass.
but i did add a MassPropertiesBundle

#

i'll try to add the Debug plugin

vestal minnow
#

You could log ComputedMass and/or ComputedAngularInertia, they store the actual mass properties used by physics stuff

#

Yeah so your cuboid with a side length of 1,000,000 and a density of 2 would have a mass of 2,000,000,000,000,000,000 :P

twilit canopy
#

ahhhh

#

yeah that makes sense we're out of Memory now πŸ˜‚

#

thanks!

formal galleon
#

@vestal minnow should I open an issue before starting with the implementation?

true hearth
vestal minnow
twilit canopy
#

got it, ill just scale it down since i'm just playing around right now

vestal minnow
#

We could just add a PhysicsPickingLayers component or similar, but this sort of feels like there should be a more unified API between different picking backends

formal galleon
#

but maybe its a bit to global

vestal minnow
#

Yes I was considering that as an option, but I think it would be good to also allow having different layers for each camera if there are more than one

#

Something that I think could make sense is to change PhysicsPickingSettings from a resource to a component that you can put on cameras

#

But ideally it'd be consistent with other backends, like MeshPickingSettings should also be a component, so we'd need to change those too on the Bevy side

#

I might ask around about that in #1236111180624297984

formal galleon
#

I create an issue and start trying around until we have a final solution

wispy lance
#

how do i raytrace with avian3d and check for collisions? i would also like to know the entity it hit

wispy lance
#

alright thanks

dreamy viper
#

ChangeDetection is triggered spuriously for avian components, right? i.e. even if the value doesn't change, LinearVelocity/Rotation/etc. are all updated every time the physics schedule runs?

cinder summit
vestal minnow
#

Interesting issue I discovered today (or well, I kinda knew about it, but it resurfaced now)
Edit: I was at least partially wrong about things here, added a clarifying comment
https://github.com/Jondolf/avian/issues/629

GitHub

Rapier stores world-space angular inertia as the square root of the inverse angular inertia tensor, effective_world_inv_inertia_sqrt. Avian and most other physics engines on the other hand just sto...

arctic fulcrum
#

If I have a kinematic rigidbody, is there a way to make it push dynamic objects "gently"? For example, I want a pusher like in one of those coin game machines - but no matter how fast the pusher moves, I want it to only nudge the coins forward, instead of flinging them at high speed. Since this is very unphysical I imagine that it might be tricky to achieve this, but can I somehow approximate it?

true hearth
#

maybe you could query for collisions around a larger radius and then manually apply damped spring forces?

#

(not literally a damped spring, would be a repulsive force based on the distance, but damping would still make sense)

#

if your collider shape is complex and the shape matters a lot, then the hardest part is probably figuring out the distances relevant for the repulsive force

#

the force could maybe look something like this:

// r is the vector between the colliders
// gamma is a parameter controlling how steep the repulsive profile is (between 0.5 and 3 maybe)
let force = strength*r.normalize_or_zero() * r.pow(-gamma)
quartz heart
#

If I understood it correctly, to apply a force or an impulse, you add an ExternalForce or impulse to the entity.

If you have multiple systems exercising forces, you would then always check if the component is already present and modify or add it based on its existence?

Or what is the best approach?

sullen lantern
#

Is there any good way of debugging the spatial query pipeline? I cannot get picking with colliders to work and I'm kind of at my wit's end in terms of what could be going wrong

true hearth
vestal minnow
#

Picking should work if the relevant physics plugins are enabled, PhysicsPickingPlugin is enabled, and ofc the colliders are correct (if they're rendered correctly with the PhysicDebugPlugin then they should be)

#

Also I think RenderLayers for the camera and colliders must match, if you've configured them πŸ€” though this seems strange for collider picking

#

It was like that in the original bevy_mod_picking's Avian backend, so I guess I copied it over

#

I'd probably remove it since colliders have no connection to RenderLayers at all, there should just be a way to filter by CollisionLayers

glacial nebula
#

only reason for renderlayers is to ensure WYSIWYG for rendered objects

#

for colliders it probably doesn't make sense

vestal minnow
#

yup

vestal minnow
sullen lantern
#

Thus the end of wits

#

Is anything other than a collider necessary to get something to appear in spatial queries?

vestal minnow
#

Position, Rotation, and Collider are the only necessary components afaik. The physics position components are inserted automatically for colliders, and they're auto-synced with Transform (if present) so you shouldn't need to use or specify them anywhere

#

assuming the relevant plugins are enabled of course, if you have e.g. PhysicsPlugins::default() then they should be

sullen lantern
#

Yeah, the relevant plugins in this case should literally just be PhysicsPlugins::default() and PhysicsPickingPlugin

vestal minnow
#

probably not too helpful, but there's a functioning picking example here

sullen lantern
#

Yeah I've looked at that. Basically I just don't see how our code is different from that in a way that matters

#

I guess I should mention that I'm using the settings that require PhysicsPickable components, but as far as I can tell those are also everywhere that matters

vestal minnow
#

wait

#

oh that is cursed

#

but technically documented

#

@sullen lantern make sure your camera has PhysicsPickable too :P

sullen lantern
#

It does πŸ™‚

#

(This is how the old bevy_mod_picking rapier backend used to work, so it's not a surprise, although it is weird)

vestal minnow
#

yeah I was also confused why require_markers: true broke picking, but I remembered the marker is needed for both

#

with that it does work for me

sullen lantern
#

Okay it turns out the problem is weirder than I expected

#

So, I can get pointer events to fire targeting my entities, but it seems fairly inconsistent

#

I'll have to test some more tomorrow morning, it's almost bedtime for me 😴

quartz heart
true hearth
raw stirrup
#

Is there an easy way to get a SpatialQuery in an exclusive system (i.e. a system that just takes &mut World)?

vestal minnow
vestal minnow
#

huh, that's pretty cool

raw stirrup
#

Thanks both! 😁

sullen lantern
#

@vestal minnow Okay, I've concluded this likely has nothing to do with avian πŸ˜… Thanks, regardless

vestal minnow
#

Okay cool πŸ˜„ did you figure out what it is / how to fix it yet?

sullen lantern
#

Nope! Basically, it turns out that picking events aren't being reported correctly unless the mouse button is held down

#

Next place to look is probably interactions with bevy_egui

#

(In other words, the reason I thought that the backend wasn't working correctly was that Pointer<Over> events were not being reported, but that lack of reporting is the shortfall, the backend is reporting hits correctly)

vestal minnow
#

Huh, yeah that sounds strange πŸ€”

#

Do you have UI or something overlaid and blocking pointer hits? Or something else like that (I'm not too familiar with how the picking stuff works :p)

sullen lantern
#

Unsure πŸ™‚ For example, right now, a global observer of Pointer<Click> always reports 0v1 (the window) as the hit entity

#

Holding down the left mouse button and dragging over the actual collider entities will produce Pointer<Over> events though

#

But the main difference between the application and a simple picking example at this point is probably the use of egui, sooooo

quartz heart
vestal minnow
#

Yeah it shouldn't be getting removed with the current way things work. I intend to rework the force and impulse API at some point though, probably to use commands or a ForceHelper system param for applying individual forces without having to deal with component shenanigans. Likely also a separate, optional ConstantForce component for "persistent forces" (e.g. custom gravity)

bold garnet
#

the egui picking back-end uses wants_input or something to tell if the stuff drawn with the painter is going to try and grab the pointer input.

sullen lantern
# bold garnet yeah, this sounds like egui

Yeah, it was egui. Basically, the change in bevy_egui 0.32 to capture mouse pointer events essentially caused all our pointer events to die. I'm not sure if there's a very good way of addressing this in general, since it's not like we can control when the egui context wants_mouse_input. I think right now it just always thinks it wants it because the viewport that's being picked in is basically just composited in. Not sure if there's a better way of handling that...

bold garnet
#

uh oh, my work is on 0.30/0.31.

#

what changed

sullen lantern
#

In 0.32, bevy_egui captures mouse input in every Window by default (i.e. as a default field in EguiContextSettings)

#

as far as I can tell, there is no way of disabling this other than creating a system which manually overwrites the EguiContextSettings

#

so, for us, the bevy_egui 0.32 upgrade essentially quietly broke all picking interactions on the application

#

Maybe the way this works makes sense if your application is like, a game window with an egui::Window floating on top of it, but if it's primarily an egui application with camera views composited into it, then picking in all those views just... doesn't work

#

Again, I'm also kind of a novice with egui/bevy_egui, so it's possible that a more "natural" configuration avoids this problem

bold garnet
#

I'm seeing if we've run into this at work, give me a bit. if we haven't then we will, if we have then there's a fix.

sullen lantern
#

On the other hand, this also just wasted like 8 entire hours of my life

bold garnet
#

We're interested in getting this fixed too

sullen lantern
#

Yeah, I'll ping them and/or write up an issue

formal galleon
willow elbow
#

Hello, I'm quite new to both Bevy and Avian so apologies if the following question makes little sense.
I was wondering why in the official examples the systems related to movement run in Update rather than in FixedUpdate for example. How do the schedules defined by the user (to update for example LinearVelocity) relate to the internal schedule of the PhysicsPlugin?
To avoid changing the LinearVelocity in Update I thought about following the custom_broad_phase example to overwrite the First step phase but there seems to be no FirstPlugin like BroadPhasePlugin.

golden python
#

Hey, say I want to generate a collider for a polygon defined by the lines (Vec2, Vec2) that form it's outershell, what would be the way ? Collider::polyline ?

golden python
#

Collider::polyline was the solution, it works perfectly

rocky seal
#

if i want to run something in FixedPostUpdate after all avian systems, is the best way to do it .after(PhysicsSet::Sync)?

dreamy viper
#

Yes

sleek thicket
dreamy viper
#

If I update Transform in PreUpdate, the first Physics update step-update will be ignored, right?
Since StepSimulation runs first, (which will update pos/rot), then Sync:TransformToPosition will run, and finally Sync::PositionToTransform.

cinder summit
#

I think TransformToPosition is supposed to run once before all the substeps πŸ€”

dreamy viper
#

Ah i see there are some systems that are running outside of any SyncSet and before StepSimulation..

I was mostly looking at at the SystemSet order which implied that the TransformToPosition would happen after StepSimulation

This isn't really documented

GitHub

ECS-driven 2D and 3D physics engine for the Bevy game engine. - Jondolf/avian

cinder summit
#

Yea the whole SyncPlugin situation kinda sucks in general ... I've seen even @vestal minnow be frequently confused about why things are the way they are, and it's neither particularly efficient nor intuitive ... It's just a bit unfortunate that bevy_transform isn't really made for non-graphical purposes ... Not yet anyway

vestal minnow
#

but yeah movement should be done in FixedUpdate generally

vestal minnow
dreamy viper
cinder summit
#

I'm not sure there's an issue but I've at the very least seen nth show up here to discuss Avian's needs for reworking bevy's Transform ... There might be some stuff that could be investigated head of time tho ... The main thing iirc is that Position is global while Transform is local, this difference could potentially be bridged if we propagate the inherited transform down πŸ€”

#

There's also some weirdness around non-uniform scales and shear, but I think avian already handles those somewhat so they might not be a major concern atm

vestal minnow
#

Avian mainly just needs a global transform (or isometry) that is not in affine/matrix form, and also a 2D version of that

#

And an f64 version assuming we want to keep support for that

cinder summit
#

Afaict people just use it for cases that really just need big space

cinder summit
vestal minnow
#

things like collision queries take a "base offset"

#

and yeah big_space support

vestal minnow
#

Hmm the upcoming non-fragmenting relations could be nice for our ColliderParent stuff

#

Replace it with ColliderOf and RigidBodyColliders

#

Also I wonder if we could handle multiple physics worlds nicely with physics worlds as entities (resources like Collisions, SpatialQueryPipeline, etc. are components) and relations that support querying by value (each physics world has a different ID, systems can query for entities belonging to a specific world)

#

or something like that

dreamy viper
#

Damn, my server-entity Transform gets slightly updated during the physics step, but not my client entity... I don't know what it could be. I'm running the same physics plugin in both, with no gravity and no sleeping

#

ah it's collision-related. Is there anything I can do to help debug the non-deterministic contacts?
If you give me a couple pointers to get started (how to modify/run the deterministic test, if that's what you're using) I can work on that.
I'll test:

  • when entity orders are different
  • when there's multiple points of contact
sullen lantern
#

@vestal minnow How do CollisionLayers interact with picking? I noticed that entities with colliders become non-pickable when they have CollisionLayers::NONE

cinder summit
dreamy viper
#

no, do i have to?

cinder summit
#

Easy way to check if you have issues with rolling back Collisions

dreamy viper
#

Something is modifying my Kinematic's Transform during the physics-step but i don't know what:

2025-01-17T20:53:10.186746Z  INFO shared::player: AfterInputsApplied is_rollback=false tick=Tick(5061) transform=Mut(Transform { translation: Vec3(0.0, 0.0, 0.0), rotation: Quat(0.00449998, -0.0014999844, -6.749975e-6, 0.99998885), scale: Vec3(1.0, 1.0, 1.0) })
2025-01-17T20:53:10.187295Z  INFO shared::player: After Physics is_rollback=false tick=Tick(5061) entity=212v1#4294967508 transform=Transform { translation: Vec3(0.0, 0.0, 0.0), rotation: Quat(0.0044999802, -0.0014999846, -6.749976e-6, 0.9999888), scale: Vec3(1.0, 1.0, 1.0) }

it only happens on the server

#

could it be the transform->position->transform sync step?

#

The thing is that on the client the physics-step doesn't change anything:

2025-01-17T20:53:10.166628Z  INFO shared::player: AfterInputsApplied is_rollback=false tick=Tick(5061) transform=Mut(Transform { translation: Vec3(0.0, 0.0, 0.0), rotation: Quat(0.00449998, -0.0014999844, -6.749975e-6, 0.99998885), scale: Vec3(1
.0, 1.0, 1.0) })
2025-01-17T20:53:10.167346Z  INFO shared::player: After Physics is_rollback=false tick=Tick(5061) entity=399v1#4294967695 transform=Transform { translation: Vec3(0.0, 0.0, 0.0), rotation: Quat(0.00449998, -0.0014999844, -6.749975e-6, 0.99998885)
, scale: Vec3(1.0, 1.0, 1.0) }
vestal minnow
dreamy viper
#

ok thanks

sullen lantern
dreamy viper
vestal minnow
#

To eliminate any potential effects of Transform shenanigans while debugging, you could also use Position and Rotation directly for the physics entities and maybe debug render the entities with PhysicsDebugPlugin to still visualize what's happening

vestal minnow
cinder summit
#

My strategy was to just disable SyncPlugin, network Position and Rotation instead, and put a custom system after the fixed main loop to sync pos/rot to Transform πŸ˜‚

dreamy viper
dreamy viper
cinder summit
vestal minnow
#

(also the layer filter can't currently be configured for picking but after I merge #632 it can)

vestal minnow
#

I'll leave a comment on the PR and can probably get it mergeable over the weekend myself as well

#

Or I guess that had the problem that then aabb might not work for some colliders that require the context

cinder summit
#

Yea, I'd have to panic on aabb

#

Being able to skip the argument when it's not necessary would be really nice tho, passing () all the time is kinda clunky

#

And if the default collider ever ends up needing it it would be possible to just wrap it in some kind of system param or something too πŸ€”

vestal minnow
cinder summit
#

Might be worth changing the API so that specific case can't happen

vestal minnow
#

Right this idea

#

I guess make AnyCollider only have the _with_context versions, and implement the empty context version manually for Collider

#

ideally we'd implement Bounded2d/Bounded3d but at least for now we still need to support f64 bounding volumes :P

dreamy viper
#

So I wasn't able to understand why this happens, but I have 0 rollbacks if I add

        app.insert_resource(avian3d::sync::SyncConfig {
            transform_to_position: false,
            position_to_transform: true,
            ..default()
        });

but i have constant rollbacks if I use transform_to_position=True.

So maybe the transform->position sync is causing some issue.

Note that I only have interpolation added on the client, so the sync_transform_to_position will always run before PhysicsSet::StepSimulation. (which shouldn't cause any issues because the Transform value is reset before that thanks to interpolation, but maybe the sync is causing some numerical instability? Or does someone have another hypothesis?)

cinder summit
#

I guess that makes some sense if a hierarchy is involved. Some floating point error would add up in transform -> position, then it would add up (possibly in the same direction again) in position -> transform

#

Iirc Jondolf had some awful hack to avoid it from detecting its own changes, but that wouldn't stop it from picking changes up changes caused by rollback or network updates πŸ€”

willow elbow
#

did anyone try the pickable functionality? I just took the picking example, added
.insert_resource(PhysicsPickingSettings { require_markers: true, })
to the main, added PhysicsPickable to the entities, and nothing is pickable.

wispy lance
#

is there an efficient way of only getting the collisions of entities with a component?

void dragon
#

Can it be that Avian is just too inaccurate? This is a plane facing upwards, and I am shooting a capsule downwards. This should be just a Y vector, however it is not precisely that. I have never had any issue with this in other physics engines. I do not want to shit on Avian or anything, because all my respect to Jondolf and the other maintainers, however this is a real issue in my opinion.

vestal minnow
#

Avian can't control how normals are computed from ray casts or shape casts, those are computed by Parry

#

I believe capsules in Parry use a form of GJK for shape casts, it is an iterative algorithm that produces approximate results

#

Regardless of the algorithm though, getting exact results for something like this is basically impossible with floating point math, it is extremely unlikely that you'd get a perfect Vec3::Y

sleek thicket
vestal minnow
#

I have not seen any engine use something other than GJK (or specifically a form of Minkowski ray casts) for general shape casts and it cannot return exact results

#

you could probably get more accurate results than Parry's implementation does though

sullen lantern
sleek thicket
#

especially when they happen on a flat mesh collider

vestal minnow
# wispy lance is there an efficient way of only getting the collisions of entities with a comp...

Depends on what exactly you need, but you could have a query like Query<(Entity, &CollidingEntities), With<MyComponent>>, and then for each pair of colliding entities you get their contacts from the Collisions resource

fn print_contacts(
    query: Query<(Entity, &CollidingEntities), With<MyComponent>>,
    collisions: Res<Collisions>,
) {
    for (entity1, colliding_entities) in &query {
        // Note: If you also want to make sure the second entity
        // matches the query, use `query.iter_many(colliding_entities.iter())`.
        for entity2 in colliding_entities.iter() {
            let Some(contacts) = collisions.get(entity1, entity2) else {
                continue;
            };
            // Do something
            info!("{entity1} and {entity2} are colliding");
        }
    }
}

Make sure to add CollidingEntities to the entities, since it's not added automatically to avoid unnecessary overhead for entities that don't need it

#

You could also just iterate over all collisions and then check if they match a query but that can have more unnecessary iteration

wispy lance
vestal minnow
#

Are you trying to make projectiles not collide with each other? You could use CollisionLayers for that

wispy lance
#

yeah but im kinda trying to avoid that, i dont like using layers, i would rather rely on logic for that

sleek thicket
#

@wispy lance #1124043933886976171 message layers are perfect for "x shouldn't hit y", this sorts out the rest. still haven't found anything better.

vestal minnow
#

For example like this

fn bullet_hit(
    mut commands: Commands,
    bullet_query: Query<(Entity, &CollidingEntities), With<Bullet>>,
    other_query: Query<Entity, Without<Bullet>>
) {
    for (bullet_entity, colliding_entities) in &bullet_query {
        for other_entity in other_query.iter_many(colliding_entities.iter()) {
            // Despawn bullet since it hit a non-bullet
            commands.entity(bullet_entity).desapwn();

            // ...
        }
    }
}
#

But again this won't stop bullets from colliding with each other.

#

You just won't despawn them when that happens

#

You could use custom filters/hooks too but that would also be more expensive than just using layers

sleek thicket
#

if there are bullets that can kill enemy bullets (e.g. shoot down a rocket), you'll want at least some of them to collide

wispy lance
#

okay i guess im gonna use layers

vestal minnow
#

And maybe enable internal edge fixing for trimeshes by default

#

And maybe a tilemap collider at some point

sleek thicket
#

for tiles and voxels

#

unless you want to do the same thing as unity and just convert it to mesh so that it allows custom colliders on tiles

vestal minnow
#

I think theoretically it could be generalized to handle these cases too, but it might be much more expensive

sleek thicket
#

i never had ghost collisions on edges of a flat mesh in unity though, so maybe there's something that can be fixed before doing that

vestal minnow
#

for meshes

#

just default to TrimeshFlags::FIX_INTERNAL_EDGES

true hearth
#

(well sometimes the character has legs)

vestal minnow
#

(the stickman platformer game series)

true hearth
#

Not sure what exactly this will be, but it's a family of ideas that I have basically been following since maybe 12-13 years or so, and playing fancy pants was probably a big inspiration

#

this one is also an attempt to do something mirror's edge like (but physics based)

wispy lance
#

how do i apply velocity for knockback? i want it to start slow, get faster and slow again

true hearth
#

but I have opted not to show 1st person this time because I myself got sick playing in full screen for the first time πŸ˜›

willow elbow
sleek thicket
true hearth
#

that's just a bunch of lines in a row

#

just a loop over simulated time, adding external forces to the velocity each loop and drawing a line between the old and new simulated position

sleek thicket
true hearth
#

not really, but I am doing shapecasts in the loop there to find where the player is going to land roughly, to orient the "feet" properly on landing depending on player input

#

but I am also doing some rough prediction of the player position into the future on the ground to estimate the next feet positions (which are determined just using ik)

#

and then I'm also procedurally updating hip, neck and head positions based on the vector between contact point and center of mass, which gives a lot of the emergent motion

#

knowing when to do steps is the most tricky part of the animation part I would say, and I will probably try something a bit more fancy soon

sleek thicket
#

yeah you're probably halfway there to rediscovering motion matching xD

true hearth
#

hmm not sure, I will probably never have a huge database of animations

sleek thicket
#

i think most of it is just blending

true hearth
#

yeah I mean the trajectory prediction part is probably shared with motion matching, but I would say the largest part of motion matching is still the lookup into the database based on the motion features and last animation clip

vestal minnow
cinder summit
#

Guess we doing music in our physics now thonk

vestal minnow
#

at least we're not writing Swift

cinder summit
#

It would've been so funny if this PR was on a physics engine written in Swift πŸ˜‚

cunning gust
#

I have an issue with shapecasts, they keep detecting and not detecting at random, and the normals are going haywire (in the debug renderer)

vestal minnow
cunning gust
cunning gust
cunning gust
#

The max distance was set to 0f32.next_up(), if I set it to 0.1 then it stops disappearing and reappearing but normals get... weird

#

getting vid

vestal minnow
#

Yeah that's largely expected I think, the hit point and normal just moving around a bit, likely due to inaccuracies with Parry's shape cast algorithm

#

Same as #1124043933886976171 message

cunning gust
# cunning gust

and here, why does it disappear? It says it's not hitting anything sometimes when it is

#

and that messes with my player controller

vestal minnow
#

You need a larger max distance, even something like 1e-3 might be enough

cunning gust
#

What do you think might be good?

vestal minnow
#

I'd say test what is large enough to not miss hits but not too large to cause other problems with your controller

cunning gust
vestal minnow
#

If I figure out a more accurate shape cast algorithm then maybe. Could also try improving it in Parry in the meanwhile

cunning gust
#

Alrighty, cool

#

That works for me since slightly inaccurate normals and "weird" ground angle detection is fine for me while I'm still just learning gamedev with bevy. If I am ever in the position to sit down and make a real game for other people, it'll probably be in a long while. Maybe even after bevy is stable (or has a scene editor)

#

Thanks :)

vestal minnow
#

No worries πŸ™‚

cunning gust
#

another question

#

When my player moved mid-air

#

how do I stop them from launching up when moving into a wall?

#

I'm using the capsule collider and the character is dynamic not kinematic

cinder summit
#

I think the physicsy solution would be for it to have friction so it doesn't slide past and redirects all velocity, but for character controllers I've more frequently seen code that just removes velocity when you touch things, and then only reapplies the velocity that should exist πŸ€”

cunning gust
cinder summit
#

I don't think there's actually a way to know, the code I've seen in other character controllers just tracks the current velocity it is applying so it can cancel any velocity it didn't create when you bump in to something that's supposed to stop you ... It's odd that it would happen with default friction tho, might be something else going on here too then πŸ€”

cunning gust
#

When in the air I'm using externalforce and not velocity for movement

#

since I like the floaty feel while airborn

#

wait no

#

I'm using velocity

#

lemme try using externalforce

#

bug still present

cinder summit
#

ExternalForce/Impulse would just end up modifying velocity anyway

cunning gust
#

Yeah

#

btw, for character rotation, should I just modify transform directly and use a spherical collider?

#

since that's what I'm doing rn

#

for snappiness

cinder summit
#

Iirc the main cause of flying up like that is usually just the result of inputing too much power from the character controller. Especially if the case is that forces are redirected up, you then see you're no longer moving in the desired direction and apply more force. If that repeats a few frames you end up pretty far in the sky

cunning gust
#

hmm

#

The think is, I don't want to player to move slowly

#

maybe I just need a cylinder collider?

#

that fixes it :)

#

But wait

#

do shapecasts have colliders?

#

as in

#

around the origin

cinder summit
#

Shapecasts cast shapes so yes

cunning gust
#

as in

#

do they interact w/ physics

cinder summit
#

They don't interact with physics, they just find any collider matching the filters

cunning gust
#

lemme send a vid

#

ok so

#

I'll just show you actually yeah

#

Is it just because it's the center of the shape?

#

of the player collider

#

This seems to happen at the location of the shapecast even if I move it

#

and I'm not doing anything with that collision info (yet)

cinder summit
#

Both the shapecast and the cylinder start at 0,0,0 in the entity's local space

cunning gust
#

I tried moving the shapecast down and it happened at it's location too but I think I just found the problem

#

I am actually using it

#

when it collides it moves as if it's grounded

#

and I don't want that

#

hmm

#

how do I make it not collide on its sides...

cinder summit
#

You check the dot product between the normal of the shapecast hit and the up vector

cunning gust
#

ooh and this would work w/ ramps too

cinder summit
#

So you can specify some arbitrary range of angles that are acceptible as "grounded"

cunning gust
#

brilliant

#

thanks

sleek thicket
cinder summit
#

It's easy to mix them up tho πŸ˜‚

vestal minnow
#

I feel like they should be the other way around but switching them is an annoying breaking change :P

cinder summit
#

Just get rid of the numbers thonk

#

Like point_shape and point_hit

cunning gust
#

cast_point, hit_point?

sleek thicket
#

hit_point_self and hit_point_other

vestal minnow
#

Maybe like

  • Get rid of normal2, and only have normal, which is the normal on the shape that was hit. This is consistent with ray casts, and I think the normals are just opposites of each other anyway.
  • Store point as the hit point on the shape that was hit, and shape_point/cast_point/self_point for the other one.
cinder summit
#

Oh no, I have unleashed the bikeshed ... What have I done ferris_spooky

sleek thicket
#

we really do need a bikeshedding channel

cinder summit
#

Time to create an Avian Bikeshed crate just to get an extra channel for bikeshedding πŸ˜‚

cunning gust
vestal minnow
#

What is the second normal for a raycast?

#

a ray has no surface

cunning gust
#

lol

#

brainfart

vestal minnow
#

And storing normal2 is kinda pointless if normal1 == -normal2

cunning gust
#

Is it always like that tho?

vestal minnow
#

yeah we need to verify that this is always the case, but I think so

cunning gust
#

if the surface is perpendicular to the cast location, sure, but what if it's slanted?

#

wait

#

nevermind

#

brainfart 2: electric boogaloo

#

wait no

vestal minnow
#

The normal is the normalized vector between the two points

cunning gust
#

OH

#

THAT'S WHERE THE NAME CAME FROM

#

ok sure

vestal minnow
#

Or it's also perpendicular to the surfaces, hence the name normal

cunning gust
#

if it's perpendicular to the surface then what if the surface is slanted

#

and it gets hit by a shapecast

#

its normal might not point towards the origin

vestal minnow
#

Can you give an example? Like what the two involved shapes are

cunning gust
#

wait nvm

#

I thought it was the normal on the casting location (which doesn't even exist)

#

brainfart 3

sleek thicket
cunning gust
vestal minnow
#

Yeah it's the normal pointing from the surface of shape A to the surface of B at the point of contact. I'm saying surface kinda broadly here, of course if you have e.g. a ball that is cast towards the corner of a triangle, the "surface" of the triangle there is really just that single vertex

cunning gust
#

I get it now I think

#

and yeah I think normal1 and normal2 are just negative vers of each other

sleek thicket
#

looks like unity doesn't have normal2 on spherecast

vestal minnow
#

yeah looking at Parry it's just doing this

normal1: Unit::new_unchecked(normal1),
normal2: Unit::new_unchecked(pos12.inverse_transform_vector(&-normal1)),
sleek thicket
#

looks like godot doesn't have it either

vestal minnow
#

It looks like some things are in local space and some aren't

sleek thicket
#

maybe it'll make more sense when you start rewriting it from scratch

cunning gust
#

lol yeah

#

I have a vec3 called movement that never has a y component. I want to rotate it so that it never points away from the surface you're on

#

so if you're on a plane, it would be the same

#

and if you're on a ramp, forward moves you up and forward at the angle of the ramp

#

and more importantly, backwards moves you with the ramp, and doesn't send you flying off of it

cinder summit
cunning gust
#

How do I get RHS

#

as in, how do I get that vec3

#

for the plane that I wish to project onto

sleek thicket
cunning gust
#

it exists in bevy but I need a vector to project onto

sleek thicket
#

RHS is plane normal

cunning gust
#

Ohhh

#

I thought it was on the plane, not the normal

#

lemme try that

cunning gust
#

it works :3

#

yippee

#

I now have a somewhat mostly functional player controller!

#

(as long as the environment is fully static but shhh)

dreamy viper
cinder summit
#

Yea that Transform -> GlobalTransform -> Position + Rotation -> Transform chain is going to be far too lossy, especially if we dare also use hierarchies

sleek thicket
vestal minnow
#

For transform_to_position there is this check

// Skip entity if the global transform value hasn't changed
if *global_transform == previous_transform.0 {
    continue;
}

which seemed to work when I tried it, but there could definitely be some problem(s) there

cinder summit
#

Hmmm ... Rolling back whatever previous transform is might have some effect

cunning gust
#

I could just increase friction

cunning gust
sleek thicket
cunning gust
cinder summit
#

It will yeet you off eventually

dreamy viper
sleek thicket
cinder summit
#

@vestal minnow I think we discussed the idea of using Transform as the source of truth and getting an entity's local space by just propagating that info down instead ... Would that actually be viable, or would we need features from a Transform rework first? πŸ€”

sleek thicket
#

when porting over to bevy i wondered if i even need that, every game i remember has like one rotating cog/turbine/car/train as a platform in the entire game and never uses it again

vestal minnow
#

Like don't use GlobalTransform at all and instead propagate manually to compute the global Transform?

cinder summit
#

Yea, except we might not necessarily want to compute the global transform and instead just up to the collider root or the parent

cunning gust
#

Except for maybe the wall sliding bit

#

w/ friction

sleek thicket
vestal minnow
cunning gust
#

I see

vestal minnow
#

no Taylor nor Swift πŸ˜”

sleek thicket
cunning gust
#

shrink them and increase max_distance

#

it's only a partial solution and extremely context dependent

#

but it works

sleek thicket
#

if you're shrinking it anyway then why not raycast

cunning gust
#

I should probably think things through more before I send messages

#

especially if I ping people

#

sorgy Jondolf

vestal minnow
#

no worries I didn't even get a ping for some reason :P

cunning gust
#

Ah ok

#

:)

vestal minnow
#

also I don't mind pings, I'm a madman who has all notifications enabled for #math-and-physics, #ecs-dev, #math-dev, this thread/topic and some other channels probably

sleek thicket
#

@cunning gust

I should probably think things through more
that's probably not gonna happen with adhd unless you get it treated

cunning gust
#

Probably not enough, but my psych advised against increasing the dose since I'm starting a new medication rn

vestal minnow
#

I've been trying ways to make the API in the collider context PR less ugly, I managed to at least make wrappers like AabbContext and ContactManifoldContext to remove the entity arguments from the methods and make you not have to do &<Self::Context as SystemParam>::Item<'_, '_>

fn aabb_with_context(
    &self,
    position: Vector,
    rotation: impl Into<Rotation>,
    context: &AabbContext<Self::Context>,
) -> ColliderAabb;
sleek thicket
vestal minnow
#

that's the rotation of the shape whose AABB you're computing

#

This is a method on Collider (or the AnyCollider trait specifically)

wispy lance
#

is there a way to invert the collisionlayers? i want something to collide with everything except one, and adding each layer to collide with every time i add a new one is kinda messy.

cunning gust
#

If I use spacialquery's shape_cast with a max distance of 0, does that just check if the shape can fit in the space?

cunning gust
#

I've found something weird. When I set the velocity of an entity and it moves, it doesn't take it's children with it, but it does when I set it's transform πŸ€”

#

AYWGQUIFGUAIUAWIGFU

#

I JUST TRIED TO GO BACK TO AN OLD GIT VERSION

#

BUT I WASN'T TRACKING THE FILE FOR THE MODULE WITH THE PLUGIN FOR MY CHARACTER CONTROLLER

#

THAT

#

THAT WAS A DAYS WORK

#

ALL OF TODAY

#

i

#

i

#

oughhh

#

whelp, time to restart :/

#

and this is why you don't develop while tired πŸ™ƒ

gloomy folio
#

if i wanted to generate something using physics in a loading screen do i put the physics step in a loop?

#

also is there a way to simulate radial gravity? i want fall towards a point rather than a direction vector.

willow elbow
#

I might have found something strange about the picking plugin. I was using the basics of the official example and found that after dragging for a while the shape would distort. After adding more and more from the example I isolated the problem to being caused by omitting the AngularVelocity.
Check this clip to see what happens

vestal minnow
willow elbow
dreamy viper
#

Hi is there a way to a ray cast between a Point/Direction and a single entity? (i.e. I don't need the QBVH, etc.) because i'm only considering a single entity

#

Maybe I can just use cast_ray_and_get_normal from Parry directly?

cinder summit
#

Using parry methods directly is probably the way to go yea

willow elbow
#

anyone knows how to avoid having UI nodes subjected to picking functions in the example such as drag and rotate? I have a node with buttons that rotates. Adding With<PhysicsPickable> to the system makes it crash if I drag

reef owl
#

@vestal minnow A while back I raised the issue of multiple physics worlds. This is the reason I'm compelled to use rapier (not bevy_rapier, but bare rapier) for my physics. Is there any likelyhood that this would be supported in, say, the next year?

wispy lance
#

can i add multiple colliders to 1 entity?

vestal minnow
vestal minnow
# reef owl <@545959292281552928> A while back I raised the issue of multiple physics worlds...

On the main branch, there are already some collision hooks (bevy_rapier has an equivalent too). These could be used to emulate at least a very basic form of "multiple worlds" with say a custom InteractionGroup(u16) component, since you could make a custom pair filter hook that skips broad phase collision pairs that don't belong to the same world/group. For spatial queries you can have similar filters with methods like cast_ray_predicate IIRC. Of course this isn't optimal, since the engine is still iterating over all of these entities, and you're simply filtering them without truly simulating each world separately.

I think the path forward for actual multi-world support might involve "physics worlds as entities", where a lot of the current resources like Collisions and SpatialQueryPipeline are turned into components on entities. You could then assign rigid bodies and colliders to these worlds using their Entity IDs. This naturally seems like something that could maybe be encoded with relationships. I think(?) relations could eventually make it efficient to iterate over entities belonging to a specific world, which would help make this faster and more powerful.

Again I can't give any real ETAs, but I'd certainly like to try to experiment with my current idea this year. The filter hooks on the main branch can also give a basic workaround just for "ignore interactions between different worlds".

wispy lance
#

assertion failed: b.min.cmple(b.max).all()

    pub fn grow(&self, amount: Vector) -> Self {
        let b = Self {
            min: self.min - amount,
            max: self.max + amount,
        };
        debug_assert!(b.min.cmple(b.max).all());
        b
    }```
#

im never calling this, this is somewhere in avians code

#

idk why its crashing

vestal minnow
#

Presumably some value is invalid, like rotation or position having NaN or infinite values for some reason

#

causing AABBs to be wonky

wispy lance
#

okay im gonna look into the code causing it

#

that doesnt seem wrong, or can you find anything?

#

this is what i think caused it

wispy lance
cunning gust
# wispy lance that doesnt seem wrong, or can you find anything?

You shouldn't directly manipulate translation for player controllers, that teleports them (eg: into a wall when they walk into a wall) and doesn't change velocity (so a player can have velocity opposite to where they're walking using this method, and have no way to fix it)

wispy lance
cunning gust
#

ExternalForce also has the method apply_force() that takes a vec3 and applies that force

#

which is convenient

wispy lance
#

idk what that all is cuz i havent been using avian for anything except collision yet

cunning gust
#

here's the docs for the component

#

the description at the top explains pretty well

#

The engine never changed ExternalForce, so if you clear it or something, it's fine

wispy lance
#

is that also in 2d?

cunning gust
#

Probably

#

yeah

#

I've yet to use avian in 2d but it should be the same

#

@wispy lance if you're relatively new, just remember for future reference (this'll save you some time) USE .normalize_or_zero() WHEN THE VECTOR YOU'RE NORMALIZING CAN BE ZERO

#

otherwise you'll get NaN NaN or something

#

and it'll cause you a headache

wispy lance
#

alright, thanks i didnt know that xd

cunning gust
#

I had quite the bug: moving would slowly rotate you sometimes even with LockedAxes

wispy lance
#

just because the wrong normalize function?

cunning gust
#

using .normalize_or_zero() for my ExternalForce fixed it :)

wispy lance
#

yo how did you ever find out

cunning gust
cunning gust
#

they noticed it

#

oop gtg

#

for that character controller

wispy lance
#

are CollidingEntities cleared after each frame?

cunning gust
#

and what's ColidingEntities (Capitalization makes it look like a struct/enum)

#

ooh

#

Looked at the dock, that's an interesting (and useful) component

#

I think it probably is

wispy lance
#

or

#

oh

#

i found the error

cunning gust
cunning gust
#

lol

#

no it is

wispy lance
cunning gust
sleek thicket
wispy lance
#

i tested it and it seems like CollidingEntities doesnt clear after a frame?

#

is that correct behaviour?

vestal minnow
#

It has the entities that are currently colliding with it, they are only removed once they stop colliding

wispy lance
#

im printing the length of the set

vestal minnow
#

Once the player is no longer overlapping the sensor at all, that entity should be removed from the CollidingEntities of the sensor, if nothing is removed and you're sure the player is not intersecting it then it could be a bug, yeah

cunning gust
#

Why doesn't RayCaster have a point of intersection?

#

ShapeCaster does

cunning gust
wispy lance
wispy lance
#

ok

vestal minnow
wispy lance
#

the collidingentities is on a child of an entity, maybe this causes a bug?

cunning gust
#

Thanks tho

#

I'll use that code

wispy lance
cunning gust
#

How do I create a collider from a gltf gahh

#

I can load the gltf but idk how to turn it into a mesh

dreamy viper
#

The ColliderAABB is updated via an on_add hook, but otherwise if I mutate the Collider the ColliderAABB is not updated automatically?

vestal minnow
cunning gust
#

btw

#

why is distance for shapecaster from the surface and not the origin

#

it makes a lot of stuff w/ comparing it to raycasts annoying

#

and it makes doing stuff like checking how far you can go w/o clipping to teleport there damn near impossible for "weird" colliders (eg: capsule)

#

and another thing, how would I add multiple shapecasters to an entity? would I just have to give it a child entity w/ the second shapecaster?

vestal minnow
#

For ray casts it's the same, it's the distance the ray traveled before hitting the surface

#

The difference is that with ray casts you have a "point" moving along the ray, while with shape casts you have a shape moving along the ray

#

(ray casts and shape casts can actually use basically the same algorithm for most shapes)

cunning gust
#

time of flight sort of deal

dreamy viper
#

Out of curiosity, how come the init_transforms systems that adds Transform or Position/Rotation to a newly added RigidBody isn't implemented via observers? Is it because of some ordering constraint?

#

Also, if i have a collider C1 with P1/R1 (position/rotation), with a child C2 with P2/R2.
Would the child's GlobalTarnsform be based on P1 + P2 ? So P2 should just be relative w.r.t to the parent?
I saw this comment:
```/// Nested rigid bodies move independently of each other, so the Transforms of child entities are updated
/// based on their own and their parent's [Position] and [Rotation].

vestal minnow
dreamy viper
#

Ah that's also why you're running your own TransformPropagation systems in Prepare?

#

There's so many tricky details to remember w.r.t to hierarchy, transformPropagation and Sync. Kudos to you to keeping that all in your head πŸ˜„

vestal minnow
vestal minnow
dreamy viper
#

The on_add hook for Collider doesn't seem to add a correct ColliderAabb on the entity. Actually i'm not quite sure what it's doing:

let aabb = entity_ref
    .get::<ColliderAabb>()
    .copied()
    .unwrap_or(collider.aabb(Vector::ZERO, Rotation::default()));
if let Some(mut collider_aabb) = entity_ref.get_mut::<ColliderAabb>() {
    *collider_aabb = aabb;
}

Doesn't just this set the ColliderAabb value to itself?

wispy lance
#

@vestal minnow is there a way i can work around CollidingEntities?

cinder summit
dreamy viper
#

The ColliderAaabb is in local mesh coordinates right? not global?

#

I think I found a bug where:

  • I create a RigidBody with Transform (but no Position/Rotation) in FixedUpdate
  • I have SyncPlugin set to only do position->transform
  • In PhysicsSet::StepSimulation, I would expect Position to be added on my entity to match the Transform that I provided (-1, 4, 1); but it doesn't seem to be the case. A Position has been added on my entity (in the Prepare set but its value is different from (-1, 4, 1)
cinder summit
dreamy viper
#

Yes i think i just realized that, I opened a PR to mention this in the docs

vestal minnow
#

The details may change with the eventual broad phase rework

#

For now a tight AABB can be computed by just calling collider.aabb(...) if needed

dreamy viper
#

Thanks that's helpful! My broad-phase check is pretty coarse so the existing aabb should fit my needs

wispy lance
cunning gust
#

wondering how to clamp rotation

wispy lance
cunning gust
#

I ended up figuring it out

wispy lance
#

ok

cunning gust
#

and that wouldn't work

wispy lance
#

yeah idk what clamp is tbh

cunning gust
#

among other things, bevy uses radians

cunning gust
wispy lance
#

i usually use chatgpt for math and it provides the results i want

cunning gust
#

If I wanted chatgpt's answer, I would've asked chatgpt

wispy lance
#

but it isnt any different from a human answer most of the time

cunning gust
#

if someone asks here, it's because they either already asked chatgpt and didn't get the right answer or, like me, don't want to use chatgpt

jolly rover
hot osprey
#

Is that what you're looking for?

#

I don't know if maxangularspeed clamps the rotational motion of an object, but if maxlinearspeed is clamoing linear velocity than maxangularspeed should clamp angular velocity

#

There you go

quartz heart
#

For sensors, the collision.collision_stopped() seems to never return true, is that possible?

sleek thicket
sleek thicket
paper maple
#

How can I force a certain velocity that ignores external forces ?

I have an infinite friction circle that should stay still on a slope, but instead slowly roles down due to gravity (despite setting the angular velocity in FixedUpdate)

I had a look at most SystemSets and didn't see any that seemed to be appropriate. I tried sandwiching it between StepSimulation and Sync, but it didn't work.

sleek thicket
paper maple
#

"I have an infinite friction circle that should stay still on a slope, but instead slowly roles down due to gravity (despite setting the angular velocity to 0 in FixedUpdate)"

My end goal is for it not roll on the slope. (without extraneously bizarre methods)

rocky seal
#

disable gravity for the circle

vestal minnow
#

infinite friction doesn't help prevent rolling, friction is specifically what allows objects to roll instead of sliding

#

rolling resistance would be what slows down rolling, but it's not supported by Avian (or almost any other engine) outside of using e.g. AngularDamping or just fully locking rotation

paper maple
#

That's why i said it's rolling down, not sliding

#

The issue as far as I can tell is that after the system that I run sets the angular velocity to 0, Avian's systems applies gravity and normal force on the circle, resulting in rolling

#

And there's not an obvious way for me to prevent that from happening (Im reluctant to use LockedAxes)

paper maple
#

I thought putting it after WarmStart and before IntegrationSet::Position would work :/.

Tangential forces due to friction (from gravity) cause it to roll. I just want to negate those force (or really, just force a constant angular velocity), but still have gravity because that's what's giving it friction in order to be able to roll

dreamy viper
#

Just triple-checking, are the docs in cast_ray_predicate correct? The ray stops and we return an answer when the predicate returns false?

sleek thicket
dreamy viper
willow elbow
#

Hello, is there any way to set an observer on a specific collider collisions without having to read all events and filter?

willow elbow
#

just found this, which doesn't seem to work though. Has an alternative been implemented since?

paper maple
wispy lance
#

@vestal minnow

I've looked further into the issue and I found out, that

2D

  1. The entity is not removed from CollidingEntities once it leaves, if the leaving entity is a Static RigidBody.
  2. ColldingEntities does not remove the entity, if the entity is deleted with commands during collision.

And I wanted to ask if there are still plans on adding this?
https://github.com/Jondolf/avian/pull/364

severe urchin
#

is there a nicer way to dynamically enable/disable the PhysicsDebugPlugin at runtime? i want to toggle it on occasionally during dev. looks like i'd have to set all the PhysicsGizmos fields to None or false myself to effectively turn it off atm.

#

afaik you can't use a run condition on an entire plugin

vestal minnow
severe urchin
#

ah! thanks

severe urchin
vestal minnow
#

As for that PR, I'm probably not adding it; the way it is implemented in that PR is bad for performance and has overhead even for entities that don't have IgnoredCollisions, and the behavior of that component is something that I think would be better and more flexible to handle by the user with a custom pair filtering hook. A hook for this exists already on the main branch (see #610) and will be available in Avian 0.3

wispy lance
golden python
#

Hey,
I'm new to avian and I do this whole charade just to do something when two specific entities collide:

    mut collision_event_reader: EventReader<Collision>,
    mut ore_q: Query<(&Transform, &mut ExternalForce, &Ore)>,
    mut ship_q: Query<(&Transform, &mut Inventory), With<Ship>>,

for Collision(contacts) in collision_event_reader.read() {
        let e1 = contacts.entity1;
        let e2 = contacts.entity2;
        if ore_q.get(e1).is_ok() && ship_q.get(e2).is_ok() {
            maybe_ore = Some(e1);
            maybe_ship = Some(e2);
        }
        if ore_q.get(e2).is_ok() && ship_q.get(e1).is_ok() {
            maybe_ore = Some(e2);
            maybe_ship = Some(e1);
        }
        let Some(ore_entity) = maybe_ore else {
            continue;
        };
        let Some(ship_entity) = maybe_ship else {
            continue;
        };
//do stuff with ore_entity and ship_entity

Is there a better way to do it or are there plans to make a better way to do these kinds of interactions, seems like one of the most common usecases ?

#

I had already asked that question but the answer was not as flexible as I wouldve liked

cinder summit
golden python
#

How would that look like ?

golden python
#

Okay we need a bevy_two_entities + avian collab

cinder summit
# golden python How would that look like ?

iirc something along the lines of

fn some_system(
    mut ship_q: Query<(&Transform, &CollidingEntities, &mut Inventory), With<Ship>>,
    mut ore_q: Query<(&Transform, &mut ExternalForce, &Ore)>,
) {
  for (ship_transform, ship_collisions, mut ship_inventory) in ship_q.iter_mut() {
    for entity in ship_collisions {
      let Ok(ore_transform, mut ore_force, ore) = ore_q.get_mut(entity) else {
        continue;
       };
       // Do something with ship and ore properties
    }
  }
}
golden python
vestal minnow
astral smelt
cinder summit
vestal minnow
cinder summit
#

Oh right, I forgot we now have iter methods instead of just get_many πŸ€”

vestal minnow
#

it'd be this I think

fn some_system(
    mut ship_q: Query<(&Transform, &CollidingEntities, &mut Inventory), With<Ship>>,
    mut ore_q: Query<(&Transform, &mut ExternalForce, &Ore)>,
) {
    for (ship_transform, ship_collisions, mut ship_inventory) in ship_q.iter_mut() {
        let mut iter = ore_q.iter_many_mut(ship_collisions.iter());
        while let Ok((ore_transform, mut ore_force, ore)) = iter.next() {
            // Do something with ship and ore properties
        }
    }
}
#

for iter_many you can just use a for loop

wispy lance
#

error[B0003]: src\combat\knock_back_system.rs:28:33: Could not insert a bundle (of type avian2d::dynamics::rigid_body::forces::ExternalForce) for entity 30v1#4294967326 because it doesn't exist in this World. See: https://bevyengine.org/learn/errors/b0003
stack backtrace:

            force.persistent = false;

            if let Some(mut entity_commands) = commands.get_entity(*entity) {
                entity_commands.insert(force);
            }```
#

im checking if it is there???

vestal minnow
wispy lance
vestal minnow
#

No I haven't reproduced this with any setup I've tried, to be clear

#

So code for anything that reproduces CollidingEntities not getting cleared correctly would be good

wispy lance
#

okay

dusty bolt
#

i have a sort of spring system that applies a torque onto a player controller, but i need it to scale with player mass, and hence angular inertia, whats the best way to achieve this? (where the linear force solution is to multiply by the mass)

let upright_torque = (axis * (angle_radians * upright_s.upright_strength)) - (angular_v.0 * upright_s.upright_damper);
                    torque.apply_torque(upright_torque);
turbid mango
#

Just randoly hit this, looks like it's possible for the AABBs to be degenerate under specific circumstances? I'm using convex hull colliders

#

I fixed it by just tweaking the geometry, and it went away

vestal minnow
#

the convex hulls are computed by Parry

vestal minnow
# dusty bolt i have a sort of spring system that applies a torque onto a player controller, b...

I think you'd need to just multiply by the total angular inertia tensor, which is stored in ComputedAngularInertia. However, this value is in local space in 3D. If you want the global version, you can use GlobalAngularInertia (updated once every physics step), or compute it manually with computed_angular_inertia.rotated(rotation).

Then you can just apply it like this

angular_inertia.tensor() * upright_torque

(If this is 2D, just using ComputedAngularInertia directly is enough)

#

We should probably have a way to just apply acceleration directly, without having to deal with mass properties

#

kinda like Unity's ForceMode

patent depot
#

Hello, this is a feature I wish I would have in other game engines (Unity, Godot) but which is always lacking.
Is it possible to have subtracting collision shapes in Avian ?

vestal minnow
# patent depot Hello, this is a feature I wish I would have in other game engines (Unity, Godot...

The standard collision detection algorithms rely on convexity, and subtracting shapes tends to very easily introduce concavity. I think colliders for these shapes would need to be mesh colliders or use convex decomposition to break them into many smaller convex parts.

So no, subtracting collision shapes isn't supported, but if you can create a mesh for the resulting shape, you could make a collider for it. Subtracting shapes typically requires CSG (Constructive Solid Geometry) with boolean operators, which is not supported by Avian, but there are some other Rust crates for it.

#

(Side note: this is actually supported to some capacity by NiseVoid's SDF colliders as well, but that's currently only in their project and doesn't integrate with Avian's own Collider)

cinder summit
#

Actually planning to rework the SDF collisions to better support cases like this. Subtracting creates bound SDFs which can cause ghost collisions, there are some ways to fix them (at the cost of infinitely thin SDFs no longer being detected as collisions, which I'd argue is probably physically correct πŸ˜‚

#

Also gotta try implementing those arbitrary SDF-SDF collisions, once I get to things like object placement, having only spheres and capsules against arbitrary SDFs isn't gonna cut it anymore

turbid mango
wispy lance
#

@vestal minnow ive sent you the code examples to replicate the 2 bugs. I dont know if ur dms are open, i can send it in here too if you want.

dusty bolt
#

well i just tried angular inertia, but something happened and now the forces are pretty much zero, but that's probably to do with my suspicious method of getting the torque, oh well mass worked fine anyways ill revist it later

dreamy viper
#

How come the order of sets is BroadPhase, NarrowPhase, Solver, ReportContacts?

#

Wouldn't we want to compute contacts AFTER the physics have been updated in Solver?

#

i.e. Solver, BroadPhase, NarrowPhase, ReportContacts

vestal minnow
#

How do you solve contacts if you haven't detected them yet?

dreamy viper
#

Ah i see, I was only thinking about dynamics.
But that means that the ColliderAabb after Solver has run is 1-tick old compared to the actual collider position, right?

vestal minnow
#

Yes I think so

#

But not from the POV of collision detection since the AABBs are updated before that

dreamy viper
#

Also, can ColliderAabb be 'rotated'? or will their axes always match x/y/z

vestal minnow
dreamy viper
#

Should I make a PR to make Dir public? (the wrapper around Dir2/Dir3)
I need to create some for the SpatialQuery, but it doesn't seem exposed

vestal minnow
#

the Dir name is a bit questionable though, sounds like a directory

dreamy viper
#

My usecase is that I'm building a helper crate for Avian that makes use of SpatialQuery, so it would be convenient.
I can just stick to

#[cfg(all(feature = "2d", not(feature = "3d")))]
use {
    bevy::math::Dir2 as Dir,
};
#[cfg(all(feature = "3d", not(feature = "2d")))]
use {
    bevy::math::Dir3 as Dir,
};

that's fine too

vestal minnow
#

yeah a PR would be good if you want to make one

#

Direction might be better for clarity and consistency with the other feature-dependent types like Vector, but I believe it conflicts with Bevy's Direction (text direction iirc) type

#

eh Dir is actually in Bevy too, just not in the prelude

#

Bevy's Direction should really be renamed to TextDirection

dreamy viper
#

So Dir?

#

Also it would be nice if there was a cast_ray_predicate api where I could use the result of my computation inside the predicate.
Something like
cast_ray_predicate<D>(..., predicate: &dyn Fn(Entity, RayHitData) -> Option<D>) -> Option<D>)
where the predicate has the Entity + HitData and can return any arbitrary data D. If it does return D, then that gets propagated as the output of cast_ray_predicate

#

actually I can just modify some external variable inside my predicate

glacial geyser
#

If I have line segment that's rotating quickly from one end, what would be the most effective way to find the first point it would contact within a frame? Would it be to just sweep a ray with small angle changes?

rocky seal
#

i'm stumped by something - does avian rely on some of the plugins in DefaultPlugins?

if i set my plugins like so:

            .add_plugins(
                DefaultPlugins
                    .set(AssetPlugin {
                        file_path: "../../assets/models".to_string(),
                        ..default()
                    })
            )

then it works as i expect. but if i replace the above w/ this:

            .add_plugins(MinimalPlugins)
            .add_plugins(StatesPlugin::default())
            .add_plugins(AssetPlugin {
                file_path: "../../assets/models".to_string(),
                ..default()
            })
            .add_plugins(ScenePlugin)
            .add_plugins(MeshPlugin)

then it doesn't work. in both cases, i am adding avian like so:

        app.add_plugins(
            PhysicsPlugins::default()
                .build()
                .disable::<PhysicsInterpolationPlugin>(),
        );

any ideas?

#

oh and i'm using a fixed timestep:

        app.insert_resource(Time::<Fixed>::from_hz(SIM_HZ));
vestal minnow
#

We have a test that just uses this plugin setup currently, and it works

app.add_plugins((
    MinimalPlugins,
    TransformPlugin,
    PhysicsPlugins::default()
        .with_length_unit(0.5)
        .build()
        .disable::<ColliderHierarchyPlugin>(),
    #[cfg(feature = "bevy_scene")]
    AssetPlugin::default(),
    #[cfg(feature = "bevy_scene")]
    bevy::scene::ScenePlugin::default(),
))
#

(disabling ColliderHierarchyPlugin shouldn't be required, it's just unnecessary in that test and doesn't work if HierarchyPlugin is disabled)

vestal minnow
# glacial geyser If I have line segment that's rotating quickly from one end, what would be the m...

This sounds like a "non-linear time of impact" query. Parry (Avian's current collision detection lib) has a cast_shapes_nonlinear method for this, but there is no corresponding spatial query that queries the world for hits since it's pretty expensive. We also don't currently have an abstraction around it for Avian, but it's possible to use Parry's version directly, passing in collider.shape_scaled().as_ref() for the shapes.

#

What you could technically do is to use e.g. SpatialQuery::aabb_intersections_with_aabb to get all of the entities inside the area taken by the line segment when it does a full rotation, and then call cast_shapes_nonlinear for each of those. The details depend on what exactly you're doing though, and how accurate/robust it needs to be

#

What you're doing actually seems very similar to the swept CCD stuff in Avian, but you're predicting future motion instead of sweeping from previous positions to current positions

dreamy viper
dreamy viper
vestal minnow
#

yeah

// src/spatial_query/pipeline.rs#L885
if self.query_filter.test(*entity, *layers) && (self.predicate)(*entity) {
    f(Some(iso), &**shape.shape_scaled(), None);
}
dreamy viper
#

Actually I just need whatever data i computed inside the predicate, I don't even need the RayHitData

#

I suppose I could use interior mutability? something like RefCell can still be mutated inside a dyn Fn maybe

vestal minnow
#

Oh so you want the ray cast to return data computed inside the closure πŸ€” This is more like ray_hits_callback which takes an FnMut

#

The callback is just called for hits in arbitrary order, it's not guaranteed to give the closest hits first

dreamy viper
#

Yeah but ray_hits_callback doesn't have the order guaranteed

#

The other option is to just use ray_hits and sort by distance

#

I think that's fine too actually

#

Also I have an example where i add RigidBody + Transform to an entity, but Position/Rotation don't get added. Should I try adding unit tests for it in avian?

#

Actually it looks like you already have plenty..

glacial geyser
vestal minnow
#

The resulting point is not necessarily a vertex, it could be on an edge or face too depending on the shape. But that may be preferable here anyway? ClosestVertex also wouldn't work for e.g. spheres or capsules since they have no vertices

vestal minnow
#

I intended to do this earlier, but here's the 0.2.1 patch finally

#

@wispy lance This should also fix the bugs you had with CollidingEntities

golden python
#

Anyone know why this entity wouldn't move with Avian3D ?

commands.spawn((
    RigidBody::Dynamic,
    Mass(70.),
    LinearVelocity(Vec3::ONE * 10000000.),
    Collider::capsule(0.2, 1.8),
    Transform::default(),
));
vestal minnow
golden python
#

I feel like an idiot, thanks

vestal minnow
#

So I was thinking, for #632 (PhysicsPickingLayers) it would make sense to include a whole SpatialQueryFilter instead of just layers, right? So it would be PhysicsPickingFilter instead

#

Currently SpatialQueryFilter is just layers + excluded entities, but it'll likely have some more things like filtering by rigid body types and maybe custom predicates in the future, and I imagine it could be nice to have the full filtering options for picking too

#

cc @formal galleon, I can implement and push these changes to your PR if that sounds reasonable

dreamy viper
#

The LayerMask can only express OR? i.e. bit 1 | 2 means interact with an entity that has layers 1 OR 2?
Is it possible to express AND? (interact with entities that are part of layer 1 AND 2)

#

Also, it seems like in cast_ray_predicate my predicate is called on entities that should be excluded by the filter. Or are entities with no CollisionLayer considered to belong to all layers?

#

I see "Colliders without this component have all filters and can interact with any layer." in the docs; it's not clear if they also have all memberships

vestal minnow
#

We could theoretically make this configurable though. I saw Rapier has an open PR with something very similar. I would be open to this if the perf impact is negligible

vestal minnow
#

same as Box2D and Rapier now iirc

dreamy viper
#

It's strange then; i'm doing filter.mask = LayerMask::from(31 as u32); and i'm still getting collisions with entities that don't have the CollisionLayers component

vestal minnow
#

Isn't that 0b11111 in binary? Which includes the first bit, i.e. the default layer

#

If you want the 31st layer, that's 1 >> 31 I think

dreamy viper
#

oh duh..

sleek thicket
#

1 << 31

vestal minnow
#

right, I get those mixed up

#

oh and 1 << 31 is the 32nd layer isn't it

sleek thicket
#

yeah, last one

vestal minnow
#

1 << 30 is 31st

dreamy viper
#

yep i wanted the 32nd layer; i'll do the AND logic in my predicate, thanks

sleek thicket
#

wasn't layermask doc supposed to have it explained anyway

#

oh, it does have it

#

@vestal minnow now that first layer is default, i think it'd be a good idea to change FIRST_LAYER to DEFAULT_LAYER in docs

vestal minnow
#

Hmm I'm not sure, it does already say in the comment that it's the default layer, and it's also good to emphasize that it's specifically the first layer, especially since that code snippet is kinda intended to teach how bitmasks and bitshifting work

sleek thicket
#

you could just add SECOND_LAYER

rocky seal
#

i would like to generate colliders from meshes (meshes from .glb files) and then serialize them to disk (so i can load them in the future w/o needing access to the meshes). is this possible to do w/o starting a full blown bevy App?

#

i'm thinking i'll put this in a build.rs file. starting up an app and having it execute a single system and then exit should work fine but seems like a lot of machinery

#

tho i guess i'll have to ask this same question about bevy's mesh and gltf plugins

#

so maybe less work to just run it thru the whole rigamarole

vestal minnow
#

I haven't tried that sort of thing myself yet

rocky seal
#

i feel like i'm not the only person to want to have colliders w/o having meshes

#

like to run a headless simulation that is viewed by a remote client (that uses the meshes)

#

which is what i'm doing

#

colliders should also be serializable
i assume you mean meshes here

vestal minnow
#

Collider should also support serde Serialize/Deserialize afaik, at least it implements the traits

#[derive(Clone, Component, Debug)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[require(ColliderMarker, ColliderAabb, ColliderDensity, ColliderMassProperties)]
pub struct Collider {
    shape: SharedShape,
    scaled_shape: SharedShape,
    scale: Vector,
}
#

You might want to serialize just the Parry shape though I guess

rocky seal
#

yeah i'm fairly certain this'll all work fine just thinking about the most straightforward way to do it. i'll ask elsewhere about whether bevy's gltf loaders are useable outside of an App. if i can write a build.rs that loads a gltf, and extracts a mesh, i should be able to run that collider fn you mentioned (or a similar one) to make a collider, then save it to disk

vestal minnow
#

@rocky seal it seems that @ethereumdegen has done this in some way btw #1278020494687338629 message

rocky seal
#

oh wow nice find, thanks

vestal minnow
#

I vaguely remembered seeing that a while back, somehow still found it with Discord's search lol

rocky seal
#

discord's search function is unfairly maligned imo

outer shadow
#

Hello there, I want to add 6 ShapeCaster to a cube shape(entity) so it would shoot out of each side. When I try to add multiple ShapeCaster I get duplicate error. Example of current code:

commands.spawn((
    Name::new("red_cube"),
    RigidBody::Dynamic,
    Collider::cuboid(1.0, 1.0, 1.0),
    AngularVelocity(Vec3::new(2.5, 3.5, 1.5)),
    Mesh3d(meshes.add(Cuboid::from_length(1.0))),
    MeshMaterial3d(materials.add(Color::srgb_u8(255, 0, 0))),
    Transform::from_xyz(0.0, 2.0, 0.0),
    ShapeCaster::new(
        Collider::cuboid(0.2, 0.2, 0.2),
        Vec3::ZERO,
        Quat::from_rotation_y(0.),
        Dir3::Z,
    ).with_max_distance(2.),
));```
got my help from here: #general message
glacial geyser
mild stump
#

Does Avian Physics provide cross platform determinism

cinder summit
vestal minnow
#

Yeah it should in theory be cross-platform deterministic with the enhanced-determinism feature enabled

#

There's also a test and example that verifies this for 2D, with a scene that has collisions and joints

#

There may still be some issues around determinism when used with networking though, or at least it's trickier to get fully working

cinder summit
#

I mean technically it is deterministic with networking, it's just that some of the stuff involved with networking like rollback or receiving things out of order can mess with things like warm starting and sleeping

mild stump
#

Thanks for the info. I’m doing some research to see which physics engine I should use for my bevy project and I’m deciding between Rapier or Avian. And since it is a multiplayer physics game I’d like to get consistent physics.

vestal minnow
#

I believe some of the current issues may be related to the order in which entities are spawned (or the order of Entity IDs) affecting the simulation, and how that order may not be entirely stable across clients, or something like that. I don't really have experience with networking yet, though I should probably try making some test app to learn about it more

mild stump
#

I think Bevy has a way where you can force entities to spawn in a certain order. I mean periwink is the maintainer of light year so he has experience with networking

vestal minnow
#

Yeah periwink has been experimenting with these things with Avian and Lightyear, and has encountered these determinism issues causing rollbacks

#

and that's without networking and with a stable entity order

#

Avian should at least be deterministic without networking stuff (and if not, please make an issue!)

#

@grizzled depot may be more up to date about determinism on the bevy_rapier side though

grizzled depot
#

I think that issue is still relevant, that’s an interesting problem I look forward to dig into, but I didn’t yet.

vestal minnow
# cinder summit Trough a feature to use `libm` instead of `std` I think

Random thought but I don't love how this means that libm operations are now used over std everywhere. For things like rendering, you rarely care about bit-per-bit cross-platform determinism, and it can have a pretty significant cost. It would be good to use cross-platform deterministic math only where it is relevant, like in specific places in physics

#

I guess more specifically I think that enabling enhanced-determinism for Avian shouldn't mean you get slowdowns elsewhere

#

I think we should vet which Glam methods aren't cross-platform deterministic (this should be in the Glam docs!), and use software implementations only for those in Avian

#

And lint against using the non-deterministic methods maybe

golden python
#

Hello, the kinematic character controller has a collision solution that works pretty well but I think it says somewhere that it has some problems.
Right now it works fine except that when jumping when hugging a wall there is a high velocity loss even though I have Friction::ZERO.

Is there a work around or an alternate system someone knows about ?

golden python
#

something like collide and slide or smth

worldly cove
#

Can you "recalculate" a collider when a mesh changes vertex positions? I have a cylinder that slides over a terrain (a plane made of triangles). I added a collider with ColliderConstructor::ConvexHullFromMesh. It works well, but part of my game involves dynamic modification the terrain mesh - and so then the collider needs to be updated to match.

The only thing I can find that is similar is this open issue: https://github.com/Jondolf/avian/issues/455, which makes it sound like it's not possible ... is there any other way to do it? Thanks!

GitHub

ECS-driven 2D and 3D physics engine for the Bevy game engine. - Issues Β· Jondolf/avian

little maple
#

wouldn't you just generate and insert a new collider?

worldly cove
#

Yep, thanks! I just tried that and it works, but I'm guessing it will be pretty sub-optimal: I was kind of hoping I could modify the collider vertices the same way I modified the mesh vertices without recalculating everything. Though, I don't have much geometry so performance is not an issue. Thanks.

worldly cove
#

Slide-y question: I have a flat disc that slides along a low-friction plane3d that is subdivided into a bunch of triangles. Even if the plane is flat (all Y values are 0), the Collider::cylinder will collide and get stuck on the triangle edges - instead of smoothly gliding over the surface. I tried upping the CollisionMargin, but it doesn't help. I could model the colliders as spheres (like a roomba) but are there any easier tricks to stop hitting flat edges?

glacial geyser
raw surge
vestal minnow
#

there should be a _with_config version of whatever you're using to construct the mesh collider

little maple
#

another approach is to use raycasts and forces to float your collider above the ground

last hollow
#

Im getting a bunch of conflicting implementations of trait errors trying to run the avian demos on both rust 1.83 and 1.84.

How do you run the demos?

vestal minnow
#

(on both Rust 1.83 and 1.84)

#

Does it say which trait?

#

if it's like Component or something like that then you most likely have conflicting Bevy versions somewhere

last hollow
# vestal minnow Works for me with just `cargo run --example INSERT_EXAMPLE_NAME`

ah, I looked at my cargo run being ran when executing it via vscode's rust analyzer plugin run button and it was running:

Executing task: cargo run --package avian3d --example dynamic_character_3d --all-features --features 3d --features default-collider --features bevy_scene 

im not sure why its running with all of these extra arguments though...

last hollow
peak timber
vestal minnow
#

Still no real progress there on my side unfortunately, my current primary objective is to add proper timers and diagnostics to make profiling easier, add better benchmarks, and finish some collision detection optimizations and improvements I've been working on

#

aevyrie implemented spatial hashing for big_space though, which may help with a physics integration

dreamy viper
#

Something in avian 0.2.1 is breaking the way my ColliderAABB is computed. My flow:

  • after Solver but before SpatialQuery, I update the Position/Rotation/Collider of an entity that is a child of a parent Collider (the child entity is not a RigidBody, though)
  • in PostUpdate, I use a gizmos to display the child's ColliderAABB (which is updated with one-frame delay in update_aabbs which runs in BroadPhase (before Solver)
  • I use the normal sync plugin

It works fine in 0.2.0 but in 0.2.1 my ColliderAABB is in a different position than expected
The only PR which seems to be related is https://github.com/Jondolf/avian/pull/620

GitHub

Objective
Fixes #573 (hopefully)
Fixes #618
The transform_to_position system is currently doing some rather complicated computations that appear to be prone to causing error and rotation denormaliz...

#

(Also do you use PreviousTransform to avoid change detection issues with interpolation?)

quartz heart
#

Avian physics feels soooo good… was so much fun to use for my little experiment project.

gloomy folio
#

i'm looking up SpatialQuery but the example only deal with the returned collision shape.. how do i also get other bundled items along with that?

vestal minnow
gloomy folio
#

so both Query and spacial query and find the query item that way

vestal minnow
#

yeah

gloomy folio
#

ok, i'll give it a go

vestal minnow
#

Depends on the number of actual collisions and how complex the shapes are. There was a demo a long time ago with over 15 k colliders at over 60 fps, and I would expect performance to also have improved since then, but the colliders in that scene were flying around in space, so there weren't that many active collisions.

#

But yeah, Avian is not particularly optimized yet, and I would typically expect bevy_rapier to outperform it for collision-heavy scenes right now. It is something I am working on to improve though

#

do make sure you're running the app in release mode or with optimizations enabled for performance intensive things though, that can have a huge impact over debug mode

little maple
#

what does the path to increasing performance look like? Thinking if there's anything I can avoid doing that may help squeeze out a little more performance

vestal minnow
#

On Avian's side

  • add a contact graph and rework contact management (largely my current focus)
  • simulation islands (half-implemented, blocked on the contact graph)
  • rework broad phase to use BVHs, with separate trees for dynamic, kinematic, and static bodies, and for sensors probably
  • rework solver to access body state more efficiently
  • AoSoA SIMD constraints
  • generally reduce allocations, branching, data fetching, etc. and increase parallelism
#

and a whole lot of other miscallaneous optimizations

little maple
#

yeah, I've been experimenting with substepcount 1 πŸ‘€

vestal minnow
#

haha yeah that could maybe be alright for simple scenarios where you don't have any complex interactions (like chains, vertical stacks of objects, etc.)

grizzled depot
#

Does reducing fixed update rate really help with perceived performance ? From my (limited real-cases) experience, it was leading to lag on every frame where it’s computing, so if you’re not combining that to a background execution it’s quickly limiting πŸ€”

vestal minnow
cinder summit
#

Also another optimization that might be worth it in some specific cases would be trying to deduplicate large colliders, which would require the assets thing ... Probably not a high priority tho, and some of the weird legacy things bevy_asset v2 inherited that might still backfire

vestal minnow
#

could make it a SparseSet component, though that would impact query perf afaik

vestal minnow
#

Might not apply to your SDF collider type tho

cinder summit
#

But again that is somewhat of a niche usecase probably

vestal minnow
#

yeah

cinder summit
#

Haven't even started on reworking the collision code tho ferris_sob

vague pebble
#

@vestal minnow Master Jondi, I have a little bit of an issue with your crate, so I am building a dynamic scene that stores also the player. Player has physical components, since his body is dynamic, he has multiple components being inserted, I dont mind filtering them when building the scene but do you know where I can check which components are automatically inserted with a dynamic rigid body

last hollow
#

Are avian joints mutually exclusive with transform propagation? I.E: can you have a joint thats a child of something, and still connect as a joint to something thats a fellow child of the parent or is outside of their parent child hierarchy?

last hollow
vestal minnow
vestal minnow
#

Then there's also Position and Rotation which are automatically inserted by a system. They should really use required components too, but it caused some problems so I left it for the time being

gloomy folio
#

anyone get bugs when they try to rotate something and it starts scaling and flipping like crazy?

gloomy folio
#

is this because of interpolation settings?

vestal minnow
#

Scaling and flipping implies you're making the rotation denormalized, make sure you're not adding rotations with addition + and instead use multiplication * or associated methods

gloomy folio
#

yeah i'm using rotate_local for rotation

urban flume
#

hm I tried using ColliderConstructorHierarchy::new(ColliderConstructor::TrimeshFromMesh) and I was getting stuck on the geometry, like I would jump on my rock and couldn't move (using tnua)

#
  commands.spawn((
      SceneRoot(object_handles.0[&object.object_type].clone()),
      transform,
      RigidBody::Static,
      ColliderConstructorHierarchy::new(ColliderConstructor::TrimeshFromMesh),
  ));
#

it works fine if I load the mesh/standardmaterial separately and use just ColliderConstructor::TrimeshFromMesh

vestal minnow
#

Not even remotely complete, but I have a very early prototype for multiple physics worlds using @surreal rune's new component indexes πŸ‘€

#

Here, the blue and red boxes are assigned to different PhysicsWorld entities. Each world has its own Collisions, SpatialQueryPipeline, and so on as components instead of resources. This lets people simulate groups of bodies separately, running in parallel where relevant/possible, keeping data structures localized to just the relevant entities. This could perhaps even be used for a big_space integration, with a separate world for each island.

#

Configuration is still shared (gravity, time step, solver parameters), and the vast majority of systems still operate on all entities across all worlds, but we could add more per-world options and flexibility as needed.

#

Some things I'd still like to try:

  • Currently, all worlds are still run at the same time. It could be cool to support running specific worlds individually, possibly even at different time steps.
  • SpatialQuery could either query all worlds, just the main world, or a given world. For querying specific worlds, we could also have a SpatialQueryByIndex to mirror QueryByIndex.
  • It could be useful to be able to share static bodies across physics worlds.
    I also need to profile to see if there's any meaningful performance impact compared to before. So far it looks fine
#

Fun side note: Just based on the description in Unity's docs, Unity Physics' implementation for multiple physics worlds sounds quite similar. Entities are assigned to worlds based on PhysicsWorldIndex.Value, and entities in different physics worlds are stored in separate ECS chunks, kinda like our archetype-level grouping by value. And the PhysicsStep is also shared across worlds

surreal rune
vestal minnow
#

Yeah, I really like how straightforward the component index stuff is to use, it wasn't too bad to implement this (so far)

#

There's a few mildly annoying quirks I ran into, like how at changes the query filters for the Query signature, but nothing too bad

surreal rune
#

Tradeoff for sure

vestal minnow
#

I pass the query returned by at to a helper method in one place and I need to add this extra () to make it work πŸ˜›

aabbs: Query<AabbIntervalQueryData, ((), With<PhysicsWorldId>)>,
surreal rune
#

Oh yeah that's ugly

vestal minnow
#

hopefully I should have some version of this ready for Avian 0.3 / Bevy 0.16, assuming the component index PR gets merged

#

currently I'm mostly just prototyping though, and testing the PR with it

surreal rune
bitter hatch
#

Are there any examples of setting up ragdoll on skeletal mesh?

glacial nebula
#

Not to mention there would be a different physics transform for all these entities, in "partition space". That's why I was leaning toward a physics integration that is less tied to bevys built in transforms.

winged frost
#

If I change the linear velocity of a RigidBody in Update, it won’t take effect until the next FixedUpdate (when avian2d solves it), right? Also, I’m new to Bevy/Rust, what’s the best way to read the docs/source to find this kind of information on my own?

sleek thicket
vestal minnow
#

Still a bit WIP, but I have a working implementation for physics diagnostics (perf timers and counters)

#

the narrow phase and constraint solving are clearly pretty huge bottlenecks atm like expected

vestal minnow
# glacial nebula Heh, that looks familiar

Aesthetics may have been inspired πŸ‘€ I've been meaning to add this for a while though, I need this for profiling + it's useful for more directly comparing performance to e.g. Box2D which has a very similar solver and similar timers

glacial nebula
vestal minnow
#

I'm afraid the patent isn't valid, I have a lot of translucent rounded rectangles on my old website from years ago

#

that website isn't even hosted on the internet anymore but we can ignore that, just trust me bro

grizzled junco
#
    ship.0.rotation = Quat::from_rotation_z(
        Rotation::radians(ship.0.rotation.to_euler(EulerRot::XYZ).2)
            .nlerp(Rotation::radians(angle), 0.25)
            .as_radians(),
    );

is there a way to simplify this? i want the ship rotation to also affect its children, if i understand correctly changing Rotation doesn't affect its children, no?

kindred hinge
#

I've not found a built-in way to apply torque between two entities (e.g. applied to a RevoluteJoint from a motor). Am I right that's missing? Is it planned? And is the workaround to apply external torque to both but and reorient it every update to ensure it's aligned with the correct axis?

vestal minnow
kindred hinge
vestal minnow
#

Likely a property of the joint since the implementation is heavily tied to it, but it could also be a separate component like RevoluteJointMotor

#

but on the same entity as the joint either way

vestal minnow
# grizzled junco ``` ship.0.rotation = Quat::from_rotation_z( Rotation::radians(ship....

Rotation should have a From<Quat> impl which would shorten this to

ship.0.rotation = Quat::from_rotation_z(
    Rotation::from(ship.0.rotation)
        .nlerp(Rotation::radians(angle), 0.25)
        .as_radians(),
);

Changing rotation does affect children if they also have transforms and are not rigid bodies themselves. Rigid bodies currently ignore hierarchies and transform propagation for the most part.