#Avian Physics

1 messages · Page 39 of 1

vestal minnow
#

lol apparently using f32::INFINITY for the mass makes the center of mass NaN

#

This particular issue should be fixed now if you run cargo update, hopefully

#

assuming you're using main

cinder summit
#

Dis you fix the f32::MAX rotation and the NaN/inf prone position yet?

little maple
#

is there something that stores contacts across frames?

vestal minnow
#

That logic should handle static bodies differently (I have this on my broad phase rework branch) and ideally static bodies probably shouldn't have mass property components at all (I have this on the rigid-body-split branch)

vestal minnow
little maple
vestal minnow
#

There's a remove_collider_on observer that runs when a collider is removed, and it removes the collider from the contact graph and constraint graph and sends CollisionEnded events etc.

little maple
#

ah.. it looks like... I'm despawning the collider and then it gets added to the constraint graph

little maple
#

hmm, I kinda fixed it by disabling the sensor and then delaying its despawn for a couple seconds and that prevents the panic. Despawning colliders seems to be kinda tricky though... is there a safe pattern for that?

cinder summit
#

Did someone say entity disabling? 👀

marble cradle
#

Im having a slight problem w avian and tnua. I dont see a tnua help channel here. But basically my character isnt always being “pushed up” properly after walking up a shallow incline . I feel like it has something to do w the “spring “ sensor under them

#

But also i wonder if theres an integrator used for this

hoary turret
#

is this the "idiomatic" way to say collide with everything but this particular thing?

vestal minnow
#

If you don't want to use bitwise ops, this should also work

let mut filters = LayerMask::ALL;
filters.remove(GameCollisionLayers::WorldBorderCollider);
#

I thought we had some helper that you can chain nicer, like LayerMask::ALL.without(GameCollisionLayers::WorldBorderCollider), but it doesn't seem like it

hoary turret
#

yep

#

I also was expecting a .without() helper

#

that's mainly why I came to ask

#

hahah

#

Will use LayerMask::ALL

echo parcel
#

Isn't there a way to apply a force at the local point?

vestal minnow
#

No, I haven't seen a method for it in any other engine either. "Local point" is also kind of ambiguous in this context; should it be relative to the transform origin, or relative to the center of mass? Either one can be useful depending on what you're doing

#

You can just transform your local point into world space and apply a world-space force

cinder summit
#

@vestal minnow I can't find anything specific in the commit history, but did you happen to scopecreep any fixes for warnings and crashes (relating to diagnostics iirc) that happen when the default collider is disabled? The last commit I have in my current branch is https://github.com/Jondolf/avian/commit/81dcb5f737b6054f3089fbb536864e91f2ed9769 but I have a bunch of random changes there to make my game not crash, and I have an ungodly number of clippy warnings bavy

echo parcel
#

CenterOfMass::new takes x, y and z, as the local variables relative to the entity's origin, right?

sweet sundial
snow urchin
#

I'll switch to this for my project just to be up to speed when kcc comes out.

vestal minnow
#

it's very possible it has issues though, we should really test it in CI somehow to catch problems

little maple
#

I'm not understanding how to scale a collider... whatever I set on the Transform when the collider is created doesn't stick... but using collider.set_scale also doesn't seem to affect the final collider... I'm judging this based off of the debug shape.. it seems to always stay at scale 1.0... but I can change the shape of the debug scale if I modify the Transform's scale... not sure if that actually affects the physics though

#

oh wait, it's possible something else is changing the transform

#

🤦‍♂️ yeah I was resetting the scale to 1.0 lol

echo parcel
#

Is there a way to assign different collision channels? I want to spawn 100 objects at the same location, and I want them to collide with the ground but not each other

vestal minnow
#

32

snow urchin
#

Doesn't unreal engine have something to prevent that kind of issue?

#

Also I would like to see fluid simulation in avian, as i'll be using it in my game.

vestal minnow
#

yes I've seen that

snow urchin
#

If avian doesn't have it already, I guess the best way is just recording the next position and last position and looking for an intersection if that's possible.

vestal minnow
#

Avian has both speculative collision and sweep-based CCD. That paper is about a different problem, specifically inter-penetration-free collisions in particle simulations

#

Afaik it basically merges colliding particles into larger "meta-particles", stores the potential energy stored in the virtual bond to preserve kinetic energy, integrates movement, and later splits the meta-particles back into smaller particles

snow urchin
vestal minnow
#

depends on what "realtime fluid sim" means

#

their test scenes have several seconds per frame

#

But do you have millions of particles? 2D or 3D? It depends on the scene

#

Pretty much no particle-based fluid simulation method I know of can handle large-scale 3D fluid simulations in real time on consumer hardware

#

But again depends heavily on how large or detailed the sim is

#

something like an SPH sim in the range of a few hundred thousand to a million particles should be doable, especially on the GPU

snow urchin
#

Btw, how long is it estimated until the kcc is finished?

vestal minnow
dry jolt
#

is there a way to use avian with a water surface as a collision mesh? like the mesh could allow objects to go inside it a little bit and still provide some bounce /push back...?

visual sparrow
orchid sail
#

mut query: Query<(RigidBodyQueryReadOnly, Forces)> panics because of a conflict:

&avian3d::physics_transform::transform::Position conflicts with a previous access in this query. Shared access cannot coincide with exclusive access.

Anyone know how I can query both information of a rigid body and be able to apply forces to it?

Wrapping them in a QueryData doesn't work either

#[derive(QueryData)]
#[query_data(mutable)]
struct TestQueryData {
    body: RigidBodyQueryReadOnly,
    forces: Forces,
}
#

Looks like picking out the specific components of RigidBodyQuery stops the panic

vestal minnow
#

I would suggest not using RigidBodyQuery and just querying for the components, yes

#

I'm most likely removing RigidBodyQuery soon, it was originally not really intended for users and is also kind of big/inefficient and easily causes conflicts like this

orchid sail
#

Sounds good, I'll avoid it then

full lagoon
#

I realised that doing my own physics for a jam isn't the best idea, I've figured out a plan on how to move over to avian. I'm aware that there's Collider::compound, is that all I need to do in regards to reducing checks? I assume keep the compound colliders roughly rectangular to reduce overlapping to reduce the number of collider checks, and doing it as a grid will avoid covering open areas as much. Docs are fantastic and I assume I've managed to overlook what the recommendation is

I just don't know how much Avian does and how much I should be helping it

echo parcel
#

I'm spawning an child entity with collision, but I've noticed that if I rotate an parent(right_leg_axis), collider doesn't follow. Why, and how can I fix it?

let right_leg_axis = commands.spawn((
            right_leg_axis_transform,
            ChildOf(rocket_id),
            LegDirection::Right,
            LegAxisTag
        )).id();
        commands.entity(rocket_id).add_child(right_leg_axis);

        let right_leg = commands.spawn((
            Mesh3d(leg_mesh.clone()),
            MeshMaterial3d(shader_material.clone()),
            Collider::cuboid(LEG_WIDTH, LEG_HEIGHT, LEG_THICKNESS),
            CollisionLayers::new(0b00100, 0b00010),
            Transform::from_xyz(0.0, LEG_HEIGHT / 2., 0.0),
            ChildOf(right_leg_axis),
            LegDirection::Right
        )).id();

        commands.entity(right_leg_axis).add_child(right_leg);
sweet sundial
#

you don't need both add_child and ChildOf btw

#

when are you rotating it

jovial herald
#

is it expected that OnCollisionStart doesn't trip if a collider is spawned colliding with another collider?

jovial herald
#

actually it seems to be working now. but maybe it's inconsistent

echo parcel
pulsar bone
echo parcel
pure patio
#

Should adding an ExternalImpulse component to an entity with a RigidBody::Dynamic be enough for the impulse to take effect on the body, or is there something else to it? The examples in the docs only show an ExternalImpulse being added when the entity is spawned, but I'm assuming it should work when added to an existing entity too? (Of course I am asking because so far it is not working for me 😸 )

full lagoon
#

I have a player who is a circle and I want to just handle them as a circle, completely balanced and without anything sticking out. I would like to add some things sticking out that would then put it off-balance and I'm not sure what the best way to deal with it is - the bits sticking out is a head and legs (head slides, legs pivot)

The simple solution is to attach them to the dynamic body but I don't want a leg placed at a specific angle to cause the character to rotate weirdly or bounce in the wrong direction. The next solution is that I stick the head and legs onto a kinematic body and put it on a physics layer where it doesn't interact with the dynamic body, and then pre update I predict where the dynamic body will go (position and rotation, it may be placed overlapping a solid), then avian handles collisions and then after I move the kinematic body to where the dynamic body actually is. There may end up being a slight difference in head and leg positions but it's purely visual

I think that there's no way to have a dynamic body and for it to ignore if a part that does collide collides with something, and I'm assuming that what I want to do is niche enough to not have a ready made solution. But I feel like I should ask just in case I could do it a better way, ideally I'd do physics for the dynamic body, and then move the kinematic body and do physics again but it's also not that important

echo parcel
#

Does Applies a linear impulse at the given point in world space. The unit is typically N⋅s or kg⋅m/s mean that impulse in apply_linear_impulse_at_point should be multiplied by deltatime? Why is it newtons multiplied by seconds?

cinder summit
#

An impulse is an amount of force that was applied over a duration, accumulated and applied all at once iirc

#

As opposed to just a force, which is applied over time for as long as it is relevant (either 1 tick or until you remove it if it's a constant force)

visual sparrow
visual sparrow
echo parcel
echo parcel
#

If I apply force with apply_force_at_point to the child, will it also affect the parent, e.g. will parent be lifted? And what if I just apply_force at the child. Would there be any difference between applyying force at the children's point, or applying force directly to the children?

vestal minnow
vestal minnow
#

(default dominance is 0, so you could set it at -1 or something for the head and legs)

#

I'm assuming you're using joints for the attachments here

full lagoon
#

Yep, I'm just drawing my concern with attaching it to the player atm

#

As a rough idea, the leg in that position would push the circle into a new path because it's attached to it, would setting a vevy low dominance avoid that?

#

I guess I would be happy with having legs rather than swing they could slide, along with the head, and they can be round so shouldn't affect anything - or combined linear and rotational. I'm just aware that in this scenario the leg doesn't really have anywhere to go, I was just going to leave it up to the kinematic body to figure it out, I guess it might just push the leg out to the side

vestal minnow
#

Oh right so they're not purely visual but do collide with the environment, they just don't affect the player or the things they're colliding with

#

The lower dominance should do that, but the head and legs might kinda freak out in some cases like that where they're essentially being forced into impossible positions

full lagoon
#

Ah perfect, yeah I'm fine with them freaking out as long as the player's path would be the same with or without them 👌

vestal minnow
#

adding some compliance to the joint (i.e. lowering the stiffness) might make it handle cases like that a bit more gracefully instead of blowing up

full lagoon
#

Ahh

#

I've been trying to figure out how to make a springy joint and is that something I'd have to do myself, setting a force to push it to the neutral position? Been playing around with constant forces and there's world space ones but the neutral position changes angle as the character rotates, but that's very easy to calculate as it's just based on the character's rotation, and then local which has no effect as it's moving with the leg so either it's parallel to the centre of mass to joint and does nothing, or it spins. Is there some kind of middle ground where a parent can apply a force to children? So I could attach the leg to some shape and that applies a force down and to the right, and the leg may hit things and move out of place but have the force return it?

vestal minnow
#

A DistanceJoint is kinda like a spring, though maybe not as configurable as you might want, and only constraints positions, not rotation

full lagoon
#

Ah yeah RevoluteJoint with force just being updated every frame may have to do

#

At least with the PrismaticJoint I can use local force there

#

It would be cool if I could attach a local force that negates rotation. Something like spawning the RigidBody pointing out 45 degrees bottom right, and then slap on a ConstantLocalLinearAccelerationWithoutRotation::new(100.0, -100.0) (long name, or would it be WithRotation? Absolute? It's kind of like a world space but just on a local space so could have the awful name ConstantLocalWorldLinearAcceleration) and it just counters its rotation and doesn't care about the world

snow urchin
#

How do you check for collisions with an object?

visual sparrow
vestal minnow
full lagoon
#

Ah

vestal minnow
#

it'd drive the bodies to a target relative transform or velocity; if the other body is static/non-existent, it'd only drive that single dynamic body to the desired target

#

with optional force and torque limits and spring parameters etc.

full lagoon
#

Ouh that would be cool

#

Thank you for your work, I'm here after messing up my physics engine, it only needed to handle a dynamic circle against static circles, aabbs, and obbs with bouncing and rolling - I'm taking part in a jam and I had time and figured I'd do it myself yesterday, it's got TOIs and everything should work fine (I have unit tests and it works exactly as predicted) but circles randomly give huge velocity when a dynamic rolled down to about 35 degrees (not 30, not 45, I might have been able to understand but it's between them), and when they weren't going between circles they were climbing up the side and resting at the top. I did also add in a polar coordinate physics engine which handles swinging on tethers which actually worked well tbh, but turns out that it's not a great idea to merge coordinate systems, when swinging can be handled in cartesian coordinates fine

snow urchin
snow urchin
#

Does the circle collider use vertices?

vestal minnow
#

no, almost all geometric primitives like circles, rectangles, capsules, and so on are represented by their properties like the radius or half-extents

#

simplices (line segments, triangles, tetrahedra), polytopes (polygons and polyhedra) and triangle meshes use vertices

full lagoon
#

Thanks to Jane Street for supporting this video. Check out their open roles, programs and events: https://www.janestreet.com/join-jane-street/

Here is the original "Is there an equation for a triangle?" video. https://www.youtube.com/watch?v=4K-Jx914NcQ (I'm taking suggestions for what Part III should be named. Comment below.)

And thanks to ev...

▶ Play video
snow urchin
#

So that's why the debug plugin displays it that way.

valid zenith
#

My implementation of Augmented Vertex Block Descent by Chris Giles at al.
https://graphics.cs.utah.edu/research/projects/avbd/Augmented_VBD-SIGGRAPH25.pdf

Source code: https://github.com/Raikiri/LegitParticles

I'm definitely glad that we finally have something that actually sometimes works better than PBD, but AVBD has quite a few more paramet...

▶ Play video
visual sparrow
valid zenith
#

craughing fair enough

full lagoon
#

Probably a silly question but how do I use the most up to date version of avian2d? Github says avian3d = { git = "https://github.com/Jondolf/avian", branch = "main" } but that's for 3d, I tried to select crates/avian2d but got a 404, I haven't needed to get a dependency from git that wasn't the default. This is to use the force rework

echo parcel
#

How can I detect collision with a specific entity? E.g. I want to despawn en entity after it hit other, specific entity

echo parcel
#

Does avian use delta time or fixed timestamps?

full lagoon
#

Both, fixed and looks at the delta time

Edit: I think you mean is the ticks dynamic or fixed - it's fixed. Delta time would be used for both

echo parcel
full lagoon
#

It is fixed, sorry my reply was half a joke

vestal minnow
#

By default it uses Time<Fixed> which has a fixed delta time (= fixed time step)

echo parcel
#

What is the fixed time stamp? 60fps?

full lagoon
#

.insert_resource(Time::<Fixed>::from_hz(100.0)) whatever you want

vestal minnow
#

Bevy defaults to 64 Hz

#

which I don't love but it's fine

full lagoon
echo parcel
#

How would it behave when there are lags? Would it just multiply it by delta time and "jump", or would it just move at the slower rate?

vestal minnow
# full lagoon What do you tend to go for? Hz and substep

Whatever is most suitable for the given project to get the desired perf and stability. I have a mild preference for 60 Hz, but usually I just start with Bevy's default of 64 Hz and 6 substeps, and adjust the substep count if needed

#

The motivation for Bevy's 64 Hz is

This value was chosen because using 60 hertz has the potential for a pathological interaction with the monitor refresh rate where the game alternates between running two fixed timesteps and zero fixed timesteps per frame (for example when running two fixed timesteps takes longer than a frame). Additionally, the value is a power of two which losslessly converts into f32 and f64.
https://docs.rs/bevy/latest/bevy/prelude/struct.Fixed.html

#

But in practice, I had never seen this "pathological interaction" or needed lossless conversion when using the old default of 60 Hz. And switching to 64 Hz had the downside that movement becomes very choppy on 60 Hz monitors (like mine) unless you're using transform interpolation, since on some frames you skip physics

full lagoon
#

I see, I see

vestal minnow
#

It's not too bad, since you probably want interpolation for higher refresh rates anyway, but it is a bit annoying, as it makes the default experience on 60 Hz monitors stuttery

full lagoon
#

Yeah

vestal minnow
#

The downside is that you can get stuck in a "death spiral" where frames always take more and more time because it's running fixed updates in a loop to try and catch up

#

You could limit the maximum number of time steps per frame to alleviate this, though I don't remember if Bevy supports it. The downside with that is that it will no longer be guaranteed to be caught up with real time, and things can slow down at low frame rates

echo parcel
#

Btw. I spawn 20 objects(Collider for tube and 4 colliders for legs, so the total of 100 colliders) and they start to lag as hell, when they hit the ground

pulsar bone
echo parcel
#

Any idea why? 100 seems like a very small amount

#

This is leg's entity

let front_leg_axis = commands.spawn((
            front_leg_axis_transform,
            ChildOf(rocket_id),
            LegDirection::Front,
            LegAxisTag,
        )).id();
        commands.entity(rocket_id).add_child(front_leg_axis);

        let front_leg = commands.spawn((
            Mesh3d(leg_mesh.clone()),
            MeshMaterial3d(shader_material.clone()),
            //Collider::cuboid(LEG_WIDTH, LEG_HEIGHT, LEG_THICKNESS),
            //CollisionLayers::new(0b00100, 0b00010),
            Transform::from_xyz(0.0, LEG_HEIGHT / 2., 0.0),
            ChildOf(front_leg_axis),
            LegTag,
            LegDirection::Front
        )).id();

        commands.entity(front_leg_axis).add_child(front_leg);
#

And the collision is added at the real time

vestal minnow
echo parcel
vestal minnow
#

Yeah if those are primitive shapes like cylinders and cuboids, it definitely shouldn't be slow. Are you running in release mode or with debug optimizations? That can make like a 100x difference in performance

echo parcel
#

Debug without optimisations

vestal minnow
#

yeah that will be extremely slow with any Bevy app, especially with physics stuff

echo parcel
#

building with --release flag should build it with all the optimisations, right?

vestal minnow
#

a lot of optimizations, but not all, there's stuff like codegen-units = 1 and lto = "thin" if you want to squeeze out even more perf for release builds at the cost of longer compile times

#

the Bevy docs describe that a bit more

full lagoon
#

I was playing around with the prismatic joint example and it doesn't seem to like the joint axis being in line with gravity causing it to jump

    let anchor = commands
        .spawn((
            square_sprite.clone(),
            RigidBody::Kinematic,
            //AngularVelocity(0.00075), // Changed. Slight turn and the jumping goes away
        ))
        .id();

    let object = commands
        .spawn((
            Sprite {
              color: Color::srgb(0.7, 0.2, 0.2),
              custom_size: Some(Vec2::splat(50.0)),
              ..default()
            },
            Transform::from_xyz(0.0, -50.0, 0.0), // Changed, it being +50 with +Vector::Y is the same effect
            RigidBody::Dynamic,
            MassPropertiesBundle::from_shape(&Rectangle::from_length(50.0), 1.0),
        ))
        .id();

    commands.spawn(
        PrismaticJoint::new(anchor, object)
            //.with_local_anchor_1(Vector::Y * -50.0) // Having the anchor outside of the shape doesn't change it
            .with_free_axis(-Vector::Y) // Changed
            .with_limits(20.0, 200.0) // Changed
    );
vestal minnow
#

Try putting SleepingDisabled on that dynamic object, I'm curious if that fixes it

#

if so, it should be properly fixed once I finish the simulation island PR

full lagoon
#

Yes, that's fixed it

vestal minnow
#

It's kinda weird but I think it currently has a bug where the body goes to sleep for a frame when it's resting at the bottom, and is immediately woken up by the joint, but it was still simulated for a part of the frame or something, so it falls down a bit and then the joint limit snaps it back

#

or something like that lol

full lagoon
#

A square's hypnic jerk

vestal minnow
#

I think you can explicitly choose a specific package from the workspace using package = "avian2d", but it should also be able to find it automatically based on the dependency name

full lagoon
#

Ouh I see, I didn't realise

#

Also is it intended behaviour that Collider::round_rectangle(width, height, radius) will result in a rectangle that is expanded by radius on each side (width+radius*2.0, height+radius*2.0)? I just expected it would give back a rectangle that is width by height with corners rounded. Seems yes, I guess it might be designed for a different purpose

echo parcel
#

How can I gen an acceleration?

#

Is there a built in function or do I have to calculate it myself?

vestal minnow
#

The API could be designed to automatically subtract the radius from the shape's extents to avoid inflating them, but this wouldn't work well for more general shapes like rounded polygons, and would break in cases where the extents are smaller than the border radius

vestal minnow
#

or alternatively the Forces API if you're on the main branch

#

or do you mean how you can get the current acceleration of a body?

echo parcel
echo parcel
#

Oh, I made a typo

#

now see

vestal minnow
#

right, I thought you meant "generate" haha

echo parcel
#

I came up with something like this to get an acceleration in the local space:

#
for (mut accelerometer, transform, solver_body) in accelerometer_query {
        accelerometer.current_velocity = solver_body.linear_velocity;

        let acceleration = (accelerometer.current_velocity - accelerometer.previous_velocity) / time.delta_secs();
        accelerometer.acceleration = transform.rotation.inverse().mul_vec3(acceleration);

        accelerometer.previous_velocity = solver_body.linear_velocity;
    }
vestal minnow
#

Yeah that should work

#

There is no first-party thing for getting the total current acceleration since you need to figure out all the contact forces and joint forces and their effects on the bodies, which requires running basically the whole solver. So the best you can do is to estimate it based on the current and previous velocity, like you're doing

full lagoon
# vestal minnow The API could be designed to automatically subtract the radius from the shape's ...

Ah, makes sense, ty

I didn't realise that a rounded polyline was a thing, that does make what I'm doing a lot simpler which is nice

Nvm, it seems to only exist for solid convex shapes

the trait bound `RoundShape<avian2d::parry2d::shape::Polyline>: Shape` is not satisfied
the following other types implement trait `Shape`:
  RoundShape<avian2d::parry2d::shape::ConvexPolygon>
  RoundShape<avian2d::parry2d::shape::Cuboid>
  RoundShape<avian2d::parry2d::shape::Triangle>
required for the cast from `std::sync::Arc<RoundShape<avian2d::parry2d::shape::Polyline>>` to `std::sync::Arc<(dyn Shape + 'static)>`

Not sure why it wouldn't be possible, I get that concave corners wouldn't be rounded but that's fine

full lagoon
#

Nvm, I got the terminology mised up, it's not a hull, it's a line

#

Actually that should still be possible it's just that it would expand on both sides. It surprises me that I'm the first to say "round polyline" here or in dimforge's discord server and I feel like I'm missing something obvious which would lead people to not think to want it

cinder summit
sweet sundial
full lagoon
#

Oh yeah of course, I assume there's no concerns with overlapping colliders sharing edges

vestal minnow
#

Or maybe you or some other dependency is also depending on bevy_heavy directly and there's a version conflict

cinder summit
#

Okay yea a cargo update fixed those errors ... But not the ```rust
cannot borrow *self.contact_status_bits as mutable, as it is a captured variable in a Fn closure

#

and ```rust
expected a FnMut((usize, &mut T)) closure, found F

vestal minnow
#

mm is that with parallel disabled?

cinder summit
#

Yes, why would sdf collisions enable parallel for the end user bavy

#

Also so damn many warnings and they aren't even from my changes ferris_sob

vestal minnow
vestal minnow
#

Oh that's cursed, the function wants to be FnMut for single-threaded but Fn for multi-threaded

#

because par_chunk_map_mut takes Fn but .iter_mut().for_each(...) takes FnMut

#

and the single-threaded narrow phase kinda needs FnMut right now

#

this was a macro before, which didn't have this issue, but it broke RA

full lagoon
vestal minnow
#

it's relative to the position and rotation of the collider, yes

full lagoon
#

Perfect, thank you

vestal minnow
#

@cinder summit #802 should fix that along with many other errors and warnings, like those annoying warnings about unused diagnostic stuff

GitHub

Objective
We have a lot of errors and warnings when using minimal feature configurations. Even usage without parallel is currently broken!
Solution
Fix the errors and warnings.

cinder summit
#

🥳

vestal minnow
#

Uhhhh yeah don't worry about the PR size bavy

#

-# it's not done

cinder summit
#
  • A lot more :D
#

We can tell just from the PR size bavy

vestal minnow
#

yeah I need to somehow write a proper cohesive description for this later, just wanted to put it out there already

#

a part of the PR is that it technically lets you use Avian without any XPBD since it's now properly isolated and feature-gated

#

with the intent that we just swap out the XPBD constraint implementations later when the new joint solver is done

#

I also made the joint components much more general and moved most solver implementation details out of them, so that they could technically be used with any solver

#

which would also be nice for a future bevy_physics if we want it to support multiple physics backends

#

The main remaining work is figuring out the details of how the JointFrame API should work 🤔 I like having the Auto variant, but it can also be quite confusing and unintuitive sometimes

#

I might start off with having just the Local and FromGlobal variants, and leave the automatic frame stuff to a follow-up

#

and default to local identity frames like the current defaults

full lagoon
# sweet sundial a round line is a capsule, so you could combine multiple capsules

Sharing for if anyone else needs a round polyline in the future, it's in 2 parts, one for getting a translation back so that points given go to where they should do, and another which doesn't process points and it just preserves shape, but could just be round_polyline and ignore the transform

https://gist.github.com/zeddash/a52735835396ca3c67824dbf014aa264

Gist

GitHub Gist: instantly share code, notes, and snippets.

snow urchin
#

How do you check if a component with CollidingEntities collides with a certain component?

#

aka what would go in

for (entity, colliding_entities) in &query {
        
    }

at that point?

little maple
#

like, if using CollisionLayers doesn't make sense for whatever reason

echo parcel
#

Is there some sort of the event that fires when 2 entites collide?

visual sparrow
little maple
#

not sure if this is the best place to ask, but has anyone implemented recording physics and then playing it back? I'm wondering how feasible it'd be to add a replay mode in my game

cinder summit
#

@vestal minnow there wouldn't happen to also be a compile error with serialize enabled by any chance?

cinder summit
echo parcel
#

Avian is deterministic

#

Just save parameters

little maple
# echo parcel Avian is deterministic

yeah, so far I haven't been opting into the deterministic features.. I guess "saving parameters" would be like.. tracking what each entity is doing each frame? 🤔

cinder summit
# little maple rollback?

Yea, the networking magic where you record a bunch of values, then play everything back when you receive data that was in the past

echo parcel
little maple
echo parcel
#

But that shouldn't be a problem

#

If you want to add randomness, just also save random numbers you generated and added into physics

little maple
#

would just... disabling physics and only "recording" transforms and then play it back work too though?

rough nebula
#

Hello, i am trying to speed up the game by setting the speed of the virtual time,
however, this causes the physics to slow down, effectively movig at the same speed. Is that ment to happen or did i messs something up?

little maple
# snow urchin How do I do that

there's probably better ways of handling this but something like this works for me

fn handle_vehicle_collisions(
    mut commands: Commands,
    mut collision_event_reader: EventReader<CollisionStarted>,
    trees: Query<Entity, With<IsTree>>,
    vehicles: Query<Entity, With<IsVehicle>>,
) {
    for CollisionStarted(entity1, entity2) in collision_event_reader.read() {
        match (
            trees.get(*entity1),
            vehicles.get(*entity2),
            trees.get(*entity2),
            vehicles.get(*entity1),
        ) {
            (Ok(entity), Ok(_), _, _) | (_, _, Ok(entity), Ok(_)) => {
                // "entity" is the tree that got hit
            }
            _ => (),
        }
    }
}

I have one system where it's iterating over the collisions and then comparing different scenarios. (The match is a little gross, I wrote it a loooong time ago and just haven't revisited it)

#

that's iterating over the CollisionStarted events but.. I think you could do something similar

snow urchin
little maple
cinder summit
#
thread 'main' panicked at avian/src/dynamics/solver/mod.rs:478:21:
Contact pair not found in graph: ContactId(0)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `avian3d::dynamics::solver::prepare_contact_constraints`!
Encountered a panic in system `avian3d::schedule::run_physics_schedule`!

thread 'main' panicked at avian/src/dynamics/solver/mod.rs:482:51:
index out of bounds: the len is 0 but the index is 0
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace
Encountered a panic in system avian3d::dynamics::solver::prepare_contact_constraints!
Encountered a panic in system avian3d::schedule::run_physics_schedule!

little maple
cinder summit
#

Huh ... I don't even think I'm despawning anything, but I might remove components for rollback or disable entities 🤔

little maple
#

it's possible that causes it too. I ended up disabling the collider, waiting a few frames and then despawning

cinder summit
#

Well, if it's related we'll probably want this to just ... not crash 🫠

vestal minnow
#

I know there's still one that happens when you change a dynamic or kinematic body to a static one while a collision is still happening

cinder summit
#

Let me test if this also happens on my bevy_rewind example, if so that's somewhat minimal

#

Interestingly only my game's client crashes, while the server doesn't

#

So I assume it's caused by something rollback does

#

Huh ... it doesn't? That's odd 🤔

#

Is there some way to add logging for the conditions causing these two crashes?

#

Cause afaict the problem originates from elsewhere

vestal minnow
#

They happen when the ConstraintGraph has contacts that don't exist in the ContactGraph anymore

#

so the contacts are not being updated correctly somewhere

#

most likely related to adding or removing colliders, or changing the body type, or something like that

cinder summit
#

Let's see if I can spot any trends in when it happens if I just ignore the errors bavy

cinder summit
vestal minnow
#

mm, I wonder if maybe some observer is querying for a component that you've removed, which then breaks contact management

#

feels unlikely, I don't think the observers that respond to removing colliders etc. really use queries

cinder summit
#

These are all the components/resources I currently roll back

.register_authoritative_component::<Position>()
.register_authoritative_component::<Rotation>()
.register_authoritative_component::<LinearVelocity>()
.register_authoritative_component::<AngularVelocity>()
.register_predicted_resource::<ContactGraph>()
.register_predicted_component::<CollidingEntities>()
#

Meaning they can get removed too

#

Should I add the ConstraitGraph here too? 🤔

vestal minnow
#

maybe?

#

it's persisted across frames and updated as contact pairs are added/removed

cinder summit
#

Absolutely everywhere in avian starts panicking bavy

#

Okay no more crashes now ... but why are my collisions broken? thonk

vestal minnow
#

Broken as in not being detected, or behaving wonky?

cinder summit
#

I wonder if this change is even valid bavy

 let sdf_local_min_point = (start + sdf_local_up * *at).into();
-let gradient = sdf.gradient(sdf_local_min_point);
+let gradient = Vec3A::from(sdf.gradient(sdf_local_min_point));
 let world_normal = sdf_iso.rotation * -gradient;
-let point1 = Vec3::new(0., *at - self.half_length, 0.)
-    + self_iso.rotation.inverse() * world_normal * (self.radius + dist.max(0.));

-adder.push(
-    point1,
-    sdf_local_min_point,
-    world_normal,
-    self.radius - dist,
-);
+let dist = dist - self.radius;
+let anchor1 = world_normal * (self.radius + dist * 0.5);
+let world_point = self_iso.translation + anchor1;
+let anchor2 = world_point - sdf_iso.translation;
+
+adder.push(world_point, anchor1, anchor2, world_normal, dist);
#

Wait that sign on the penetration is wrong ...

#

Okay changing that makes no difference ... Wouldn't expect a wrong penetration value to cause such a casual phasing trough the floor anyway

#

... Wait do I still get the errors now? Gotta make sure it's not related to that ...

#

Okay no more crashes now that I roll back the constraint graph ...

cinder summit
#

Okay it seems I did have some collision bugs, I fixed them, yet I still fall trough the floor thonk

#

... The client doesn't update AABBs? Huh ... That can't be a good sign

cinder summit
#

@vestal minnow am I supposed to add VelocityIntegrationData and TimeSleeping manually for Forces to work? thonk

#

Note that SleepingPlugin is not enabled

vestal minnow
#

We could maybe make the ForcePlugin also register the requirements to allow Forces to work without the other plugins

#

Or make TimeSleeping an optional component in the query

#

probably that

cinder summit
#

Definitely that is sleeping stays optional (which is always useful for debugging and stress testing)

#

Oh the other one works again now ... Huh, I must've messed something up earlier then ...

#

Yet I keep falling trough the floor ferris_sob

#

I do see gizmos with absolutely massive lines, so I'm a bit confused as to why I just fall trough 🤔

snow urchin
#

Would I just need to combine CollisionStarted and CollidingEntities or does CollidingEntities have something like that in store?

little maple
vestal minnow
#

CI also runs tests with it enabled

cinder summit
#

Huh, that's weird. For me one specific type breaks 🤔

vestal minnow
#

which type?

cinder summit
#

ContactEdge breaks because of one of the fields containing a SmallVec or something 🤔

#

Ah, that might just mean smallvec needs the serde feature enabled

vestal minnow
#

I'm guessing something is enabling it for me locally then, like maybe some dev dependency 🤔

#

not sure which one

#

yep

#

I'll make a PR to enable it when serialize is enabled

cinder summit
#

I somehow can't even figure out where it happened now, which means the cargo update earlier might've hidden the issue. Definitely want to set that correctly though

vestal minnow
snow urchin
little maple
snow urchin
little maple
little maple
#

I.. might not understand what you're asking. What you wrote is a way to check if that entity has that component

snow urchin
#

Well, I figured out that, i'm just trying to debug something else and let it sit until I either figure out the issue or solution.

snow urchin
#

Yeah couldn't figure it out, but here

fn magic_mouse_collision(magic_mouse: Query<(Entity, &CollidingEntities), With<MagicMouse>>, spell_radius: Query<&SpellRadius>) {
    for (entity, colliding_entities) in &magic_mouse {
        if spell_radius.contains(entity) {
            info!("oof")
        }
    }
}

SpellRadius is spawned with a collider

#

Also tried

Query<&Collider,With<SpellRadius>>

And nothing

#

contains() won't return true

little maple
snow urchin
#

ah. lol.

#

Don't you just need CollidingEntities then?

little maple
#

yes, you don't need the Entity in the magic_mouse Query but it also depends on what you're doing in that function (i.e., you might end up needing it once you start doing whatever it is that happens when it hits a spell_radius)

snow urchin
#

potentially.

little maple
little maple
#

wooo Avian shout out in the birthday post

snow urchin
#

Is there a CollidingEntities to see if objects are overlapping? If not, how do you do it in a version that is like CollisionStarted?

#

As in overlapping, not just colliding.

vestal minnow
#

In practice those are basically the same thing. If two objects are colliding, they are touching (or expected to start touching within the time step) or have inter-penetration

#

You only get a contact between separated shapes if it is a speculative contact

#

If you want to filter out speculative contacts, you can get the collision data for each contact pair from Collisions, use find_deepest_contact to find the contact point with the largest penetration depth, and check that it is non-negative

snow urchin
#

Understood. The issue that caused me to ask that question is resolved.

dry jolt
#

hi. im trying to use the main branch of avian to use the new Froces API.
Im trying to use the Forces in query

pub fn movement(
    mut query: Query<
        (
            &ActionState<Action>,
            &mut Transform,
            &mut LinearVelocity,
            &mut AngularVelocity,
            &mut Forces,            
        ),
        With<Player>,
    >,
    time: Res<Time>,
) {
    for (action_state, position, vel, mut forces) in &mut query {

and gettign an error

`avian3d::prelude::Forces` is not a `Component`
the trait `bevy::prelude::Component` is not implemented for `avian3d::prelude::Forces`
consider annotating `avian3d::prelude::Forces` with `#[derive(Component)]`
the following other types implement trait `bevy::prelude::Component`:
sweet sundial
#

no &mut, it impls QueryData directly

#

that query will have a conflict anyway, have to also remove the &mut velocities

#

(can get them back with Forces:: lin_vel_mut and ang_vel_mut)

dry jolt
#

perfect. thank you.

sweet sundial
#

o7

dry jolt
#

seams a bit more more logical and cleaner so far.

#

im moving over from rapier3d
how do we use the mesh from a gltf asset for the terrain?

vestal minnow
# dry jolt im moving over from rapier3d how do we use the mesh from a gltf asset for the t...

You can use the ColliderConstructorHierarchy component

#

It's similar to the AsyncSceneCollider in bevy_rapier, but more customizable and flexible

dry jolt
#

sweet. thats what we were using

dry jolt
#

wow its working. changed over 7 systems in our game to use avian. and we get to bring our speed constants back to something reasonable. our force vector was like 10000 before and now its more like 10

#

its deff smoother on mac m1 so far.

#

i was using a capsule_z for my boat. but i only see capsule.

#

it feels like such a more stable simulation

#

on the mac with lower frame rate the simulation on rapier would get all wonky. now its like not bad because everything goes where it seams like it should when the frame drops a little.

dry jolt
#

is there a debug display so i can see how to rotate my capsule?

little maple
snow urchin
#

and the ends aren't touching

#

is that still a collision?

vestal minnow
#

yes

#

unless that shape is hollow from the inside, like a polyline or 3D trimesh

#

but then they would not be overlapping anyway

snow urchin
#

hm

#

how do I do boolean operations in run_if?

#

I require something like xor

sweet sundial
dry jolt
#

for doing simulations i had my scale about 1 unit in bevy equals 10 feet. and it was working pretty awesome with avian. i tried scaling up the 3d model to a 1:1 so my boat is like 50 feet long. and the simulation breaks. it slows down and needs insame amount of force which i think might be breaking it...
what kinda scale is recomended? maybe do i need ot switch over to f64 and DVec3? thanks

dry jolt
#

i set the colider density to 10 and its working pretty good with a 1 unit = 10 feet

crimson crest
#

Did you ever end up making that version where spatial queries return the actual surface normals and not the separating axis?

vestal minnow
#

Not yet, that needs to be added directly to Parry (or Peck)

#

or I guess we could have a trait in Avian and implement it for Parry's shapes, though at that point I'd just upstream it to Parry anyways

little maple
#

how much does enabling determinism affect performance? is that a "it depends" question?

vestal minnow
#

Avian is locally deterministic by default. enhanced-determinism makes it use libm for cross-platform deterministic math, which can be meaningfully slower, but I haven't measured exact numbers

#

Ideally we would have a nice way to use the libm versions only for the operations where it's relevant, in the places where it's relevant, instead of glam just having a global "use libm" feature

#

Box2D is fully cross-platform deterministic and doesn't even have an option not to be. The performance cost was basically negligible for it

little maple
#

oh wow. Maybe doing a record and playback feature wouldn't be too bad. I think I've seen issues in my game in the past where when I slow down the physics time, the physics seem to behave differently.. like, not equivalent to what would happen at full speed... but, that could be caused by my code incorrectly introducing deltatime in places where I'm using fixedstep, right?

vestal minnow
#

Behavior should be consistent as long as Time<Fixed> has a fixed delta time. To speed up or slow down physics without losing determinism you'd have to run physics more/less frequently while keeping that fixed time step. I think changing the relative speed of Time<Virtual> should have that effect

#

And yeah your own code that affects physics needs to correctly consider delta time and be deterministic as well

little maple
#

my slowdown/speedup code is changing Time<Physics> 🤔

vestal minnow
#

A caveat for something like record and playback is that there is cached state like the ContactGraph and ConstraintGraph that affect behavior. To properly reproduce the same behavior, you may need to record those as well, which can get expensive

little maple
#

hmm.. yeah I was considering either... using physics and recording inputs.. or just trying to record transforms of everything, take out physics and interpolate

bold garnet
vestal minnow
#

Side note, this video pretty neatly shows some of the differences you can have with a stateless (Unity DOTS Physics) vs. stateful (Havok, Avian, Rapier, Box2D, Jolt...) physics engine
https://youtu.be/Uv7DWq6KFbk?si=KqquMUSDxFVomXeB&t=804

This session gives an overview of the physics systems and workflows powering our Data-Oriented Technology Stack (DOTS). Viewers will gain insight into design considerations underlying Unity Physics, how its use cases differ from those of Havok Physics, and how both offerings express concepts familiar to users of our classic GameObject-based phys...

▶ Play video
#

The stability difference is pretty massive; though they have improved on it more recently with some interesting (mildly cursed) heuristics
https://youtu.be/EGv3u8GgUlI?si=EUezfnwaN5XMRMJj

The Unity Physics DOTS package, developed in partnership with Havok, needed to be cache free in order to better support scenarios such as simulation rollback for networked simulations. Stacking rigid bodies tends to require a cache, spanning multiple frames, to produce stable results. Here we will talk through some heuristics needed to resolve t...

▶ Play video
little maple
#

"Free"

snow urchin
#

How to get the normal between 2 objects in a collision?

dry jolt
#

i think i will need to scale my stuff a bit. but wow this is really really fun to use compared to rapier.

past escarp
#

such as

let point = contacts // contacts: Res<ContactGraph>
    .get(projectile_entity, object_entity) // Colliding entities
    .and_then(|pair| pair.manifolds[0].normal)
minor sandal
#

I just wanted to say working with avian has been lovely. I am just starting to do integration tests using bevy_mod_scripting, and it works nicely:

(red line is an intercept point, and the arc and arrow are the missile torque and thrust commands)

crystal cosmos
#

I was spawning lots of spheres and a few trimesh got this xD

thread 'main' panicked at /Users/choc/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/avian3d-0.3.1/src/collision/collider/mod.rs:508:9:
assertion failed: b.min.cmple(b.max).all()
stack backtrace:
   0: __rustc::rust_begin_unwind
   1: core::panicking::panic_fmt
   2: core::panicking::panic
   3: <Func as bevy_ecs::system::function_system::SystemParamFunction<fn(F0,F1,F2,F3,F4,F5) .> Out>>::run::call_inner
   4: <bevy_ecs::system::schedule_system::InfallibleSystemWrapper<S> as bevy_ecs::system::system::System>::run_unsafe
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Encountered a panic in system `avian3d::collision::collider::backend::update_aabb<avian3d::collision::collider::parry::Collider>`!
Encountered a panic in system `avian3d::schedule::run_physics_schedule`!
Encountered a panic in system `bevy_app::main_schedule::FixedMain::run_fixed_main`!
Encountered a panic in system `bevy_time::fixed::run_fixed_main_schedule`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!

I'm not really sure why this debug_assert would trigger, I never call grow or change the size of colliders after spawning them. I don't really know how to reproduce, I was just spamming them.

/// Increases the size of the bounding volume in each direction by the given amount.
#[inline(always)]
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
}
#

Either some part of Vector is negative or hitting inf or smth?

weary ember
#

Here's my usecase for simulating a robot in bevy env. Cuttently it's rapier, but idk about switching to avian.

How's avian now for robotics? I'm currently using rapier but it behaves in certain cases, such as stiff collisions and funky momentums in UAV simulations.

I have mujoco bevy bindings, where bevy is just a renderer, and I need to construct scenes dynamically from bevy.

minor sandal
vestal minnow
#

which we don't have yet

weary ember
#

I'm unsure where to invest time if I want an accurate robotics sim on rust. It all goes to simplifications made along the way to make it suitable for gamedev, but unusable for robotics. There's a ton of movement in python land with a differentiable accurate GPU physics, but i need that in rust. Rapier is funky in robotic cases.

fossil pendant
#

is there a way to not link children's colliders to their parent's rigid body on spawn?

#

do I have to manually remove ColliderOf?

#

or can I just mark them as sensors

crystal cosmos
#

Is there a way to get more information about why Trimesh generation might have failed? I am trying to generate colliders for chunks of voxel terrain so they're not nice shapes, truly just a bunch of triangles that are unlikely to be connected together. Convex won't work, I really just need polygons/triangle based colliders.

knotty thicket
#

I'm trying to replicate the bush behavior from tunic as seen here.

Right now I'm trying to use a SphericalJoint with a static rigidbody on a "below-ground" bone and a dynamic rigid body on the bush bone. So its two bones and a mesh child on the second bone. The intent being that the below-ground bone is static and never moves while the above ground can rotate around the ground position.

I want it to interact with a "player" (just a sphere collider right now) and the ground in terms of collision, and to prefer returning to the original neutral position.

Does this sound reasonable or am I overcomplicating it?

#

I see an align_position on Joint, but not entirely sure if that could be used to do the "return to neutral" force. I also tried a persistent ExternalForce on the bush in the Y direction but that felt a bit weird.

bleak wadi
#

could there be a way to create a hitbox for a tile depending on he surrounding tiles? using ldtk if there's any inbuilt thing that could help

sweet sundial
knotty thicket
#

oh you mean like another on top hmm

sweet sundial
#

(i was a little excessively worried there would somehow be a spoiler in that video, i should probably buy that game)

knotty thicket
cinder summit
minor sandal
knotty thicket
# minor sandal Isn't it possible to just get character position and just tilt the thing dependi...

yep, and that seems to be similar to how tunic actually does it. (the bushes don't interact with each other and non-player items that roll around seem to not really interact either). enemies do, so just using the player position as input wouldn't be enough. I was hoping to take advantage of the physics/collider systems to not have to safelist entities into affecting the movement, for example.

minor sandal
knotty thicket
minor sandal
#

Yeah, layers can be useful.

dry jolt
#

theres no way to have the bone springy towards it initial orientation?

knotty thicket
knotty thicket
#

this conversation basically

dry jolt
#

interesting.
and what are the joint motors?

knotty thicket
#

I'm just reading about them now though, so grain of salt with my explanations 😅

knotty thicket
minor sandal
#

Noice !

knotty thicket
minor sandal
knotty thicket
#

yeah, could put some work in to make the correction only apply if not in contact, etc, but at that point I feel like I'm re-coding it anyway

minor sandal
knotty thicket
#

yeah

cinder summit
knotty thicket
fossil pendant
#

I was trying and make some simple projectiles by using sensors and despawning them when they collide with something, but if I make them too fast they seem to just magically collide with the floor even though they are traveling away from it

#

I don't quite understand what's going on

sweet sundial
#

try despawning them when their velocity changes too much instead

cinder summit
#

Very possible these are ghost collisions with <0 penetration. You might also need better CCD modes for this to work

golden python
#

Hello, what is the general wisdom when it comes to dynamic rigidbodies that only have colliders in their children.
I can't seem to get it to work, right now I get this error:

thread 'main' panicked at \avian3d-0.3.1\src\collision\collider\mod.rs:508:9:
assertion failed: b.min.cmple(b.max).all()
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `avian3d::collision::collider::backend::update_aabb<avian3d::collision::collider::parry::Collider>`!
Encountered a panic in system `avian3d::schedule::run_physics_schedule`!
Encountered a panic in system `bevy_app::main_schedule::FixedMain::run_fixed_main`!
Encountered a panic in system `bevy_time::fixed::run_fixed_main_schedule`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!

(the line referenced is about the aabb grow() method)
This is the offending code I think:

 commands.entity(entity).insert((
    RigidBody::Dynamic,
    Mass(1.0),
    children![(ragdoll.transform, ragdoll.collider.clone()),],
));
vestal minnow
#

make sure that transform is valid and e.g. doesn't have a scale of zero

#

typically that error means you have NaN somewhere

golden python
#

also it seems like I'm missing something to get the rigidbody moving, I always forget the checklist, idk if it's written down somewhere

vestal minnow
#

Other common things that can cause NaN or infinite values are stuff like division by zero, using .normalize() on a zero vector, and so on

vestal minnow
#

If there are NaN values then that might mess things up though

cinder summit
#

I think there's also a case with placeholder AABBs, I fixed that in my branch. Don't think parry can cause that behavior though

golden python
#

If I have the collider at the top level it works fine, but I want to be able to offset it so I put it in a child but that results in a non falling object

cinder summit
#

Ah wait, that really could be placeholder AABBs 🤔

vestal minnow
#

I discovered a sleeping bug on main but otherwise this works like expected for me

commands.spawn((
    Mesh3d(meshes.add(Cuboid::from_length(1.0))),
    MeshMaterial3d(materials.add(Color::srgb(0.2, 0.7, 0.9))),
    RigidBody::Dynamic,
    children![(Collider::cuboid(1.0, 1.0, 1.0), Transform::default())],
));
fossil pendant
golden python
golden python
# vestal minnow I discovered a sleeping bug on `main` but otherwise this works like expected for...

I got a pretty minimal version of the bug working:

//on setup
commands.spawn((
    Zombie,
    children![(        
      Mesh3d(meshes.add(Cuboid {
        half_size: Vec3::new(0.5, 0.2, 0.2),
      })),
      MeshMaterial3d(materials.add(StandardMaterial {
        base_color: Color::srgb(1.0, 0.0, 0.0),
        ..default()
      })),
    )],
))
.observe(|trigger: Trigger<RagdollTrigger>, mut commands: Commands| {
    commands.entity(trigger.target()).insert((
        RigidBody::Dynamic,
        //Collider::cuboid(0.5, 0.2, 0.2), If the collider is at the root instead, it works as expected
        children![Collider::cuboid(0.5, 0.2, 0.2)],
    ));
});

fn trigger_ragdoll(
    mut commands: Commands,
    keyboard: Res<ButtonInput<KeyCode>>,
    zombies: Query<Entity, With<Zombie>>,
) {
    if keyboard.just_pressed(KeyCode::Space) {
        for zombie in zombies.iter() {
            commands.entity(zombie).trigger(RagdollTrigger);
        }
    }
}

The bug here is that if the collider is not at the root, the mesh will get it's transform set at 0 0 0 and will not move at all with the rigidbody, but if it is at the root, then it works as expected

quartz heart
#

Is it possible to have avian3d + aviand2d in one project?

#

(or use 3d physics, but apply it to 2d sprites in some way?)

#

I don't expect them to interact with each other, but using 3d physics for the 3d objects, and 2d Physics on the 2d layer (UI/Overlay)

sweet sundial
#

they'll probably act like different crates with two copies of everything non-external

viral goblet
#

A question to frequent users of the crate- do you use mostly Dynamic rigidbody or Kinemtaic?
I've been using kinematic with some complex calculations and I keep running into weird edge-cases
I thought of switching to dynamic with the built-in calculations but that would require me about a week of work, which I'm not sure would pay off

visual sparrow
#

But this heavily depends on the kind of game you make

past escarp
viral goblet
#

Well
If you both use only dynamic and static, then that's probably enough

#

My game doesn't really have any special physics, that's why I thought using kinematic would be enough to begin with

crystal cosmos
#

Ok figured out my previous issue, collider generation requires indices. Now it's working but the collider looks pretty different to my mesh 🤔 . I tried a few of the trimesh flags but they didn't seem to make a difference.

It's possible my naive index generation isn't lining up with my generated vertices though, still need to check that. Bevy renders the mesh fine though with those indices

golden python
cinder summit
viral goblet
#

Is there a Q&A Avian somewhere?

#

I just started using dynamic rigidbodies and Restitution doesn't seem to work

fossil pendant
#

if I have a rigid body with colliders as children will the collisions with those colliders point towards the rigid body entity or the collider entity

visual sparrow
cinder summit
#

@vestal minnow the Contact edge not found in graphs have come back to haunt me again ... This time it's when I switch maps (which naturally despawns everything that was colliding)

#

I already clear both graphs when I exit that state so idk why it still crashes though 🫠

little maple
golden python
vestal minnow
#

you're inserting children!, which overwrites the Children component and the existing relationships, so the mesh becomes orphaned

#

if you switch to .with_child there, it should work

commands
    .spawn((
        Zombie,
        children![(
            Mesh3d(meshes.add(Cuboid {
                half_size: Vec3::new(0.5, 0.2, 0.2),
            })),
            MeshMaterial3d(materials.add(StandardMaterial {
                base_color: Color::srgb(1.0, 0.0, 0.0),
                ..default()
            })),
        )],
    ))
    .observe(|trigger: Trigger<RagdollTrigger>, mut commands: Commands| {
        commands
            .entity(trigger.target())
            .insert(RigidBody::Dynamic)
            .with_child(Collider::cuboid(0.5, 0.2, 0.2));
    });
vestal minnow
vestal minnow
#

There's also an FAQ in the docs

golden python
vestal minnow
vestal minnow
#

What's your setup like?

viral goblet
#

I'll send a video soon

viral goblet
#

(I found no relevant information in the FAQ or in the discussions forum)

vestal minnow
# viral goblet so here's what it looks like

It's kinda hard to tell, it could be that you explicitly set velocity for the movement which negates the bounce, or maybe the damping is so high that the bounce is barely noticeable, or something else like that

#

some things you could try

  • Make sure you're not accidentally just overwriting the velocity somewhere
  • Reduce damping, and try making the restitution way larger just to see if it really doesn't work or if it's just too low here
  • If it still doesn't work, maybe try making an even simpler test case, like a circle with some initial velocity bumping into another stationary circle, just to have some simple functional scenario. Then go from there to try and figure out the problem with your actual setup
viral goblet
#

(it'll take a while until I'm back with an update because my rust is being funny)

vestal minnow
#

You can have a restitution coefficient larger than 1, but it means that the bodies will gain energy when they collide, which can cause explosive behavior and isn't possible in the real world

#

So it's typically not recommended, but it is something you should be able to technically do

viral goblet
viral goblet
#

Ok so I tested with 1.0 and I don't see any difference

#

time to test with 20.0 on both hehe

#

Ok it works with 20.0

#

Like, very visibly so

#

I guess I could just leave it this way as a "recoil factor"

vestal minnow
#

Yeahh a restitution of 20 is... mildly questionable, but if it works then why not lol

#

uhhh has someone seen this before?

#

consistently getting it in CI

visual sparrow
crystal cosmos
#

thread 'Compute Task Pool (2)' panicked at
A triangle mesh must contain at least one triangle.
Ah, so close haha.

little maple
#

so, if physics are on fixedupdate and everything is interpolated.. should I handle player input on fixedupdate or update? I feel like handling on update might be introducing some determinism issues 🤔

#

but then it's like.. if you have a high framerate you're not getting less input latency 🤔

visual sparrow
#

You’ll need some form of input accumulation as described there

little maple
visual sparrow
visual sparrow
crystal cosmos
#

Ok got it working smoothly now xD feels good

#

Only slight footgun is parry can't handle empty mesh as source for trimesh collider, whereas bevy is fine with it, so check first if mesh.count_vertices() >= 3

little maple
crystal cosmos
#

Probably on me though, I should have something before this step that early exists for empty mesh and just removes the renderer and collider entirely

visual sparrow
#

The from_constructor method IIRC returns an Option

#

So we could return None for empty meshes

visual sparrow
crystal cosmos
#
A triangle mesh must contain at least one triangle.
stack backtrace:
   0: __rustc::rust_begin_unwind
   1: core::panicking::panic_fmt
   2: parry3d::shape::trimesh::TriMesh::with_flags
   3: parry3d::shape::shared_shape::SharedShape::trimesh_with_flags
   4: avian3d::collision::collider::parry::Collider::trimesh_from_mesh
#

Another small one I found was in init_collider_constructors in avian, when there is no Mesh3d on the entity that had a ColliderConstructor added it explicitly panics. The code around it does error logging and handles weird situations fine so it wouldn't be big to modify that panic to a error log. I won't spam the console either since the constructor marker is removed in that system

#

Next step, navmesh generation 😛 do you play favourites with any of the libraries that work with rerecast @visual sparrow 😛 ?

visual sparrow
visual sparrow
#

I like landmass because it already has local avoidance out of the box

visual sparrow
#

But if you prefer polyanya, vleue_navigator has an example for how to manually import rerecast navmeshes.

#

There will be tighter / automatic integration for vleue_navigator once François has more time

visual sparrow
crystal cosmos
#

chefs kiss

visual sparrow
vestal minnow
#

pushed some changes to revert some of the API changes

little maple
# visual sparrow Easy for me to know, I wrote it 😄

I get the reason for the accumulated input, but it's true that in this example's implementation it somewhat is equivalent to just reading the input on the fixed update since it's only using the last frame, right? (obviously, if there was something like a boost, that would get missed without being implemented in the accumulated input)

acoustic spoke
#

oh dear

#

i knew this day would come

#

i seriously hate despawning entities inside observers for this exact reason lol

little maple
vague pebble
#

Physics in avian is natively lerped correct?

visual sparrow
vague pebble
#

ah

#

that makes sense

visual sparrow
vague pebble
#
/// Responsible for rotating our character, applies angular velocity. No smoothing operand added
/// Note - This does not adjust our character
fn handle_rotation(
    mut rotating_entity: Query<(&Rotating, &mut AngularVelocity, &Rotation), With<Controller>>,
    time: Res<Time>,
) {
    for (Rotating(quat), mut ang_vel, rotation) in rotating_entity.iter_mut() {
        // Differential between camera rotation and current controlled entity rotation
        let delta_rotation = *quat * rotation.0.conjugate();
        let desired_ang_vel = delta_rotation.to_scaled_axis() / time.delta_secs();
        ang_vel.0 = desired_ang_vel;
    }
}```
#

Which I guess is what is happening here

acoustic spoke
#

i don't tolerate frame latencies

little maple
acoustic spoke
acoustic spoke
#

i meant everything else in my game logic that relies on despawning

acoustic spoke
#

specifically OnRemove

little maple
acoustic spoke
#

... the fact that this error is not reproducible and just happens randomly is also really annoying

#

i suppose i should just enable RUST_BACKTRACE everytime i run so when i do catch the error i can at least see the stacktrace

viral goblet
#

Is gravity applied automatically to dynamic rigidbodies?
I just noticed that my player always falls really, really slowly (the game is top-down)

visual sparrow
visual sparrow
viral goblet
#

Which would also explain why I had to set the recoil factor to 20

#

Wait, how do I cancel the gravity?

visual sparrow
viral goblet
#

oh no

#

Maybe I'll wait with setting the scale then and hop players wouldn't notice they're falling

minor sandal
#

Is there an elegant way of extracting colliders as a reflect? I'm trying to figure out how to save/modify them on the run.

visual sparrow
minor sandal
vestal minnow
#

I'll probably do final testing and polish tomorrow and then merge hopefully

little maple
#

so.. I know avian is deterministic by default.. I'm trying to implement a replay/demo system and I'm running into small differences and am wondering what might be introducing them

A: Frame(1) Linear velocity: 20.0, P: Vec3(-1686.242, -65.70028, 898.1884) R: Quat(0.0, -0.5428654, 0.0, 0.8398197)
B: Frame(1) Linear velocity: 20.0, P: Vec3(-1686.242, -65.70028, 898.1885) R: Quat(0.0, -0.5428654, 0.0, 0.8398197)
A: Frame(2) Linear velocity: 20.002808, P: Vec3(-1685.9379, -65.70708, 898.0514) R: Quat(9.830844e-5, -0.5428622, -7.871953e-5, 0.8398218)
B: Frame(2) Linear velocity: 20.00281, P: Vec3(-1685.9379, -65.70709, 898.05145) R: Quat(9.743288e-5, -0.54286206, -7.81078e-5, 0.8398219)

these are the first two frames where A is when I was recording and B is the playback of the recording which happens on the same run of the app. It's recording a collider with the only force acting on it (aside from gravity) is it's spawned with LinearVelocity 20.0 on its forward vector. Are these differences just f32 rounding I can't avoid?

vague pebble
little maple
#

I think he has setup multiple unit tests that check for determinism. I suspect I'm just not finding where I'm introducing non-determinism

#

actually, I think I found what was causing it

#

maybe 🤔

visual sparrow
#

Or was that only necessary for cross-platform determinism hmm

little maple
acoustic spoke
little maple
#

my determinism seems worse with enhanced-determinism 🤔

little maple
#

ok, I determined that... if I relaunch the game... it matches.. like it is deterministic across runs of the game (i.e., if you take the transform output of the first X frames and compare to another run's first X frames they do match)

but, if I clear everything and reload the game without exiting and replay the same inputs... that doesn't match (i.e., frames 1-500 don't match 501-1000) So... I suspect either I'm missing something that I'm doing that's breaking determinism or.. is it possible that starting the same physics scenario on a different frame generates different results? I'm not sure if that falls under determinism or not 🤔

little maple
#

is it possible that something needs to be reset in Avian if I'm effectively reloading the world from scratch? Like the Time<Physics> ?

little maple
#

it might be the jitter of small objects 🤔 my game has a truck and when there are objects in the truck's bed, the truck behaves non-deterministically

vestal minnow
#

clears the contact graph and constraint graph

little maple
#

I'll try that but I think it's the items in the truck bed 😞 when I take them out, everything behaves more deterministic

vestal minnow
#

I think the thing with the contact graph is that it maintains a sort of linked list and free lists for nodes and edges. When you add pairs initially, it can just push them, but if you later remove nodes/edges, you get vacant nodes/edges and the insertion order can be different

#

So unless you fully clear those structures, you can get different results when "resetting" a scene

#

But across runs it should be deterministic

little maple
#

hmm.. yeah, I don't mind the jitters if it's deterministic 🤔 gonna try that out in a few

vestal minnow
#

That way, the contact removal order shouldn't affect the insertion order, and they should always be pushed in the same order when starting from a state of no occupied contact edges

little maple
crystal cosmos
#

The RaycastHits API is a bit confusing. I don't understand the purpose of count. Is using the vector.len() not enough? If count is supposed to represent the hits including those missed because max_hits was reached it should probably be called lost or ignored or something.

Currently RaycastHits::len returns count, so missed hits are included in the count, but if you iterate you might get less. But then as_slice returns the vec from 0..count which indicates count could be less than the actual length of the vec, otherwise it could just be &vector.

If count is there to account for hits that went above max_hits then it probably shouldn't have a single len function, because it's not obvious whether it should include those outside max_hits or not. It should have something like hits(), lost(), and total(). Even then I don't really like hits() because it's easy to assume that actually means total() but I can't think of a better name off the top of my head.

pub struct RayHits {
    pub(crate) vector: Vec<RayHitData>,
    /// The number of hits.
    pub(crate) count: u32,
}
crystal cosmos
#

After testing it seems count doesn't include missed/ignored hits over max_hits, so it seems unnecessary 👀

#

Maybe it used to?

#

The ray cast code include comparisons to count, but I am unsure what they are trying to do xD
if (hits.vector.len() as u32) < hits.count + 1

vestal minnow
#

Lol I have not looked at this code in like over a year, but it looks silly

#

I think the intent there is that count allows vector to be never cleared, and items are instead overwritten, because somehow 2023 me thought it'd be better/faster that way

crystal cosmos
#

ahh, yea I see where that's coming from. I was confused that I saw hit.count = 0; but no vector.clear also

vestal minnow
#

But like, I'm pretty sure it should be fast to just clear and push, since the vector allocation is reused anyway

crystal cosmos
#

yea exactly, vec is already doing that work in push. doing the check then assigning might actually be slower, since rust will still need to do the bounds check internally when assigning to somewhere in the vec buffer 😛

vestal minnow
#

yeah

crystal cosmos
#

I kinda love the debug visuals in avian haha. The little arrows on raycast hits are neat. I'm a little unsure where a big red line is coming from, only seems to appear while I move the camera 🤔

#

the direction the raycast hit has moved since the last update maybe?

vestal minnow
#

I believe the red arrow is from the ray cast or shape cast origin to its maximum distance

#

so like if a ray is cast from point a to b (where b = a + direction * max_distance), the arrow would be between those points

crystal cosmos
#

Hmm, the raycast is dead center (it's on the same entity as the camera) pointing forward, so I am unsure if it would be showing up like that. Though maybe it's from gizmo having a delayed position

vestal minnow
#

Yeah it might be a perspective thing + small delay that makes it look weird, not sure

vestal minnow
#

It seems to work for our determinism test scene at least

little maple
vestal minnow
#

In a follow-up, I'll probably rename

  • RayHitData, ShapeHitData -> RayCastHit, ShapeCastHit
  • RayHits, ShapeHits -> RayCastHits, ShapeCastHits
#

Or maybe RayCasterHits and ShapeCasterHits for the latter?

#

It'd associate the names more closely with the RayCaster and ShapeCaster components, while the RayCastHit and ShapeCastHit types are also used for SpatialQuery APIs

little maple
#

hmm does the hit belong to the raycast or to the raycaster? 🤔🤔🤔

vestal minnow
#

RayHitData and ShapeHitData (the current names) are the output types for ray casts and shape casts, and RayHits and ShapeHits are components that store one or more of those hits for a RayCaster or ShapeCaster

#

oh you're probably asking more semantically whether the hits belong to the raycast and therefore RayCastHits makes sense, or if they belong to the raycaster and therefore RayCasterHits makes sense

little maple
#

ya

crystal cosmos
past cargo
#

avian is faster than rapier? @vestal minnow

snow urchin
#

Is there an example of getting collision normals in avian2d?

#

I remember asking a simular question and someone answered with a manifold example, but the exact query wasn't shown to get manifolds of a collision/collider.

sweet sundial
#

mostly Res<Collisions> if you're not doing event handling i think?

snow urchin
#

Basically mouse snapping kind of.

sweet sundial
#

i don't understand that at all, sorry

little maple
vestal minnow
little maple
snow urchin
#

Kind of like plotting a grid, but what would be there appears when you're hovered over a spot in the grid.

vague pebble
#

How can I mutate the shape of a prexisting collider? Increase values like radius and so on

snow urchin
#

Or rather, how do you get normals from collidedentities if possible?

snow urchin
sweet sundial
#

oh, it's a systemparam now
apparently i missed an update

sweet sundial
#

parameter for a system
also apparently i didn't miss anything, i just misremembered

snow urchin
#

Isn't a resource apparently

sweet sundial
#

...yes

little maple
vague pebble
#

@vestal minnow Sorry for ping, but when is it safe to get collider aabb information?
I am running this system basically the moment the collider is added, and it returns me a is that supposed to happen?
On later frame he is normal
2025-08-20T19:44:44.052757Z DEBUG psycho_lag_compensation: collider=ColliderAabb { min: Vec3(inf, inf, inf), max: Vec3(-inf, -inf, -inf) }

fn handle_no_child_collider_scenario(
    query: Query<(Entity, &Collider, &ColliderAabb, &LagCompesated)>,
    mut commands: Commands,
) {
    for (entity, col, collider, lag_compensated) in query.iter() {
        if lag_compensated.collection().is_empty() {
            debug!(?collider);
            commands
                .entity(entity)
                .with_related::<LagBoxOf>((*collider, Name::new("Lag compensated collider")));
        }
    }
}
vestal minnow
#

I believe on the main branch it should be initialized correctly right after spawn though

snow urchin
vague pebble
fiery mortar
#

Has anyone done ragdolls with avian? any tips?

#

I already added (compound) colliders to each bone, but I can't get the joints to behave

sweet sundial
#

are the joints trying to intersect two colliders

fiery mortar
#

I don't have collisions enabled between them, only to the floor

#

If I understand spherical joints correctly, for a right shoulder the twist axis should be -X and the swing should be Y, but the cone ends up looking UP instead of to the side?

sweet sundial
fiery mortar
#

oh i meant this cone

#

but now that you say it i think i'll try to draw some gizmos

viral goblet
visual sparrow
knotty thicket
#

you also get ColliderOf if you have rigidbody/sensor, which can be really nice for direct "root entity" access

vestal minnow
#

In the future it is also likely that sensors will be a fully separate thing from "normal" colliders, at least internally

#

I.e. they would not compute contact manifolds, but would just detect intersections with separate optimized logic

#

(this is how e.g. Box2D does things, sensors are not really in the narrow phase, but have their own thing)

#

(source for that here)

viral goblet
#

Thanks guys!

viral goblet
#

Is there a built in way to check collisions on the very frame a collider is created?

vestal minnow
#

after physics (FixedPostUpdate), yes, before that, no

#

if you needed to, you could manually get entities that intersect the shape at some position via SpatialQuery

#

or use a shape cast which also includes some contact data

#

but it's not the same as the narrow phase collision detection

viral goblet
#

Alright
Thanks

viral goblet
#

If I understand correctly- if a collider was spawned on another collider, a CollisionStarted is emitted. Also, if a colliderwas despawned while touching another collider, a CollisionEnded will be emitted.

#

They always store whether they're touching or not, and when that status changes, and it doesn't matter why, the appropriate event will be emitted

#

(right?)

vestal minnow
#

yes that sounds correct

visual sparrow
#

Woah, new heart color spotted

bleak wadi
#

is there a way to prevent the character from sort of sticking to walls and also losing horizontal speed when bumping its head? (i'm using tnua if that changes anything)

fiery mortar
bleak wadi
#

thanks

bleak wadi
#

when you're moving into it

vague pebble
#

How expensive it is to update a collider continously? I mean reinserting it every frame. Is there a better option, to lag-boxes scenario?

#

Extending his collider aabb in my mind would be more optimal

cinder summit
#

@vestal minnow compilation broken on main if debug-plugin feature isn't enabled

#

-# Add the minimal features CI step

little maple
#

🤔 are raycasts deterministic?

#

I setup this system that hashes the transforms of every rigidbody every frame and I can see this frame has the same hash but on one run of the game my raycast hits and on another run it doesn't. The raycast starts from the same point, goes in the same direction and would hit the ground.. but in one run it does and one run it doesn't.

#

update_pipeline!

little maple
#

that actually helped. Still running into non-determinism but I feel like I'm getting closer 💪

acoustic spoke
#

try putting it inside PostUpdate after running fixed update

#

in my experience, Avian (and by extension, bevy) is very deterministic in a lot of things and can be relied on for frame-perfect logic, people just need to order their systems 😉

#

i believe update_pipeline is called in PhysicsSchedule on PhysicsStepSet::SpatialQuery at some point

#

PhysicsSchedule itself is run as part of FixedPostUpdate, which is run by PostUpdate on a system set i forgot the name of

little maple
acoustic spoke
#

i suspect that in your two runs, one raycast observes an "outdated" physics world because the fixed tick rate hasn't been reached yet

little maple
acoustic spoke
#

nice! good luck!

vestal minnow
#

all fixed schedules run between PreUpdate (or right after StateTransition) and Update

acoustic spoke
#

wait, for real...?

vestal minnow
acoustic spoke
#

wow, just made myself a huge source of misinformation there

stuck hull
#

why doesnt numcollisions have field NumCollisions

visual sparrow
crystal cosmos
stuck hull
#

how can i access multiple components from that query in that loop

visual sparrow
stuck hull
#

is there another way to use oncollisionstart apart from doing .observe(...) like in the docs

knotty thicket
cinder summit
#

Ah, well, that's something Jondolf is gonna have to change for the next release now I bet 🫠

knotty thicket
#

On<On<On<On<

#

trivial change tho, Trigger<OnCollisionStart> vs On<CollisionStart>. (CollisionStart isn't taken in avian afaik)

cinder summit
#

Ah, clever ... Annoying autocomplete but it works

knotty thicket
#

yeah, bit offtopic for the channel but the On* eventname prefix convention was really nice for documentation discovery

eager meadow
#

Ok, so, I'm working on a top-down 2d game (think kinda roguelike-esque though not turn based and not grid based) and I'm looking at using Avian for collisions and line of sight. Right now, my naive thought is in my player movement system to store the old position before moving, then after moving to check Collisions for anything intersecting the player entity, and to reset the player's location if so. Something like this:

fn player_movement(
    keyboard_input: Res<ButtonInput<KeyCode>>,
    mut player: Query<(&mut Position, &mut Transform, Entity), With<Player>>,
    collisions: Collisions,
    mut qt: ResMut<Quadtree>,
) {
    if let Ok((mut position, mut transform, player_ent)) = player.single_mut() {
        let backup = position.0;
        for key in keyboard_input.get_pressed() {
            match key {
                KeyCode::KeyA => transform.rotate_z(PLAYER_TURN_RATE),
                KeyCode::KeyD => transform.rotate_z(-PLAYER_TURN_RATE),
                KeyCode::KeyW => position.0 += transform.up().truncate() * PLAYER_MOVE_RATE,
                KeyCode::KeyS => position.0 -= transform.up().truncate() * PLAYER_MOVE_RATE,
                _ => {}
            }
        }
        collisions
            .entities_colliding_with(player_ent)
            .for_each(|_ent| {
                // If the player is bumping into something, record that position as "known"
                // then reset the player's location to before they moved
                qt.insert_point(position.0);
                position.0 = backup;
            });
    }
}
#

That doesn't really seem to work, though, as resetting the player's former position is still placing it in contact with the collider, so it gets stuck.

#

Is there a "better" way to accomplish this?

bold garnet
vestal minnow
vestal minnow
#

doesn't seem to be spurious, it has failed on that many times in a row even across different PRs

visual sparrow
#

Or remove binstall entirely and use cargo test instead of cargo nextest

#

which is slower for avian (I checked), but faster than waiting 50 minutes lol

#

btw want me to incorporate the bevy linter in the lint action at some point?

#

@dusky brook do you have an idea?

vestal minnow
#

It hangs on this, before any nextest stuff

#

Normally it's this

vestal minnow
#

can confirm that taiki-e/install-action works too as an alternative for cargo-binstall

dusky brook
#

although that is what the action's readme says you should use

#

v1.15.0 was released 2 days ago

vestal minnow
# cinder summit <@545959292281552928> compilation broken on main if debug-plugin feature isn't e...
GitHub

Objective
Minimal feature configs are broken again...
Solution
Fix 'em!

GitHub

Objective
Minimal feature configurations are easy to break accidentally. We should check them in CI.
Solution
Change the &quot;Check&quot; job to &quot;Check Minimal Features&quot;....

little maple
#

edit: had a problem where spatial queries were hitting things that were despawned previously. Turns out that you have to have physics running for things to update bavy

cinder summit
#

Could also manually update the pipeline I think, seems like a bit of a flaw if you just have physics paused or something though 🤔

vestal minnow
#

soon-ish it'll be changed to incrementally update the BVH, so spawns and despawns should update it immediately via observers

vestal minnow
#

tbh I'll be shocked if it works perfectly first try without any new crashes lol

#

it's a lot more tricky graph bookkeeping and managing linked lists and spawns and despawns and whatnot

little maple
cinder summit
#

Jondolf's beta tester group consisting of 2 people bavy

golden python
cinder summit
#

NaN values most likely

golden python
cinder summit
#

The Position or Rotation of whichever entity is causing the crash

#

I'd imagine either some wrong math for calculating forces, which NaNs velocity, or something moving or spinning very fast

vestal minnow
cinder summit
#

I've only once seen avian itself cause NaNs and it was because of the placeholder position/rotation when you don't set them and don't have transform propagation

little maple
#

if I insert a rigid body on a fixed update... how many fixed updates would pass before it "exists"?

vestal minnow
#

It should fully exist after the first time physics (i.e. FixedPostUpdate) runs for it

#

It will "exist" before that too, but won't have collisions and won't (currently) show up in spatial queries until physics schedules have run

little maple
#

is it at all possible that spawning a rigidbody while physics is paused affects its Transform in some way? Like.. if I'm spawning the same rigidbody at the same Transform::from_translation across runs of my game... there shouldn't be a difference of like 0.00004 in their X coordinates, right?

little maple
#

ok, it might be because I was switching one vehicle's collider while things are loading. I am constantly surprised how changing something by such a small fraction breaks determinism. It makes sense, but every time it surprises me

cinder summit
#

Change the number at all and float precision will take care of the rest for you

little maple
#

getting a weird thing with slab and get_disjoint_mut

little maple
#

thread 'main' (3379639) panicked at forks/avian/crates/avian3d/../../src/dynamics/solver/islands/mod.rs:728:17:
Neither body 375v1#4294967671 nor 163v1#4294967459 is in an island

little maple
#

@vestal minnow it seems to be complaining about this?

#

entity 375v1 is the gray uhh divider underneath the sign and entity 163v1 is the collider of the sign

#

if I move it up just a smidge so that they're not touching it doesn't crash

little maple
#

also, another thing I noticed when iterating over rigid bodies with this..

Query<
    (
        Entity,
        &Position,
        &Rotation,
        Option<&Name>,
        Option<&LinearVelocity>,
        Option<&AngularVelocity>,
    ),
    With<RigidBody>,
>,

the order isn't quite the same across runs. Again, I'm trying to setup replays in my game and I'm testing the determinism by iterating over everything on frame 1, outputting its position/velocity, and then doing the same on 500 and then doing a diff to see where the non-determinism is.

On the simulation-islands branch, the step 500 has a different order between runs for rigid bodies that haven't moved which is interesting.

#

and yeah, I had to set slab to use slab = "0.4.11" since get_disjoint_mut was added in 0.4.11 I think

knotty thicket
little maple
#

I thought it was somewhat determined by insertion order? Regardless, I can add the sort since this is just for debugging but I thought it was worth pointing out just in case it's a hint at some other problem.

I am seeing some non-determinism getting introduced about 50 frames in but it likely is something in my code

knotty thicket
little maple
#

yeah, I've been adding a lot of chain() and systemsets 🫠

#

a little off topic, but I think the main thing tripping me up right now are Commands that queue Commands. I've been converting them into observer triggers which seems to be helping

green haven
#

Hey, quick question, does anyone know how can avian2d use collisions to not let movement, like what system pr plugin uses avian2d for knowing if you can move infront of you or you can’t

ferris_sob ferris_sob ferris_sob super_bevy super_bevy

#

Cause in a proyect I got it was pretty straightforward, just put the collisions and if component static body haha you can’t move

#

But now I implemented my own rendering system

#

Soo it kinda hard to keep track of the real size of things

sweet sundial
#

usually you just apply forces to a dynamic body and it stops on its own when it hits something

#

can use shapecasts or collision events otherwise though

green haven
green haven
#

But I got stuck in thete

sweet sundial
green haven
#

I have to implement when the collision happens and how I want the forces to interact with the rigid body

sweet sundial
#

not if i'm interpreting you vorrectly

#

*c

#

avian's a physics system, dynamic bodies collide with each other

green haven
green haven
sweet sundial
#

static & kinematic also act on dynamic bodies, yes

green haven
#

And they detect the collisions, but they don’t anything besides that

sweet sundial
#

show the code?

green haven
#

Like I could give tou the repo

sweet sundial
#

just need the part where you spawn the physics objects

green haven
#

Ohhh sure

#

use avian2d::prelude::{
    Collider, CollisionEventsEnabled, LinearVelocity, RigidBody, SpeculativeMargin, SweepMode,
    SweptCcd,
};
use bevy::{
    ecs::system::{Commands, ResMut},
    log::info,
    math::{DVec2, Vec2},
    transform::components::Transform,
};

use crate::{
    ecs::{
        maze::{
            components::maze_meta_data::MazeMetaData,
            systems::utils::maze_tile_centroid::get_tile_centroid,
        },
        player::components::player::{Player, RayCaster},
    },
    global::PLAYER_COLLIDER_RADIUS,
};

//TODO: change this for being in the needed schedule

// just for game_start
pub fn spawn_player(mut commands: Commands, maze_meta_data: ResMut<MazeMetaData>) {
    // when first created, this will be the position of the player, cause it will be the first spawn_tile pos

    let spawn_position = get_tile_centroid(maze_meta_data.spawn_tile_initial_pos);

    commands.spawn((
        Transform {
            translation: spawn_position,
            ..Default::default()
        },
        Player,
        CollisionEventsEnabled,
        SweptCcd::default(),
        RigidBody::Kinematic,
        Collider::circle(PLAYER_COLLIDER_RADIUS),
        RayCaster {
            ..Default::default()
        },
    ));

    info!(
        "Player Spawned at: {},{}",
        spawn_position.x, spawn_position.y
    );
}

#

Here’s the player

#

pub fn generate_maze_tiles(
mut ascii_maze: ResMut<AsciiMaze>,
mut maze_meta_data: ResMut<MazeMetaData>,
mut commands: Commands,
) {
for (row_index, ascii_row) in ascii_maze.0.iter().enumerate() {
let mut tile_row: Vec<TileType> = Vec::new();

    for (col_index, ascii_tile) in ascii_row.iter().enumerate() {
        // for knowing where should the tiles begin
        let y0 = row_index as u32 * TILE_SIZE;
        let x0 = col_index as u32 * TILE_SIZE;

        let mut tile_entity = commands.spawn_empty();

        // for tyle properties and rendering
        let tile_type = match ascii_tile {
            '+' | '|' | '-' => {
                tile_entity.insert((
                    CollisionEventsEnabled,
                    RigidBody::Static,
                    Collider::rectangle(TILE_SIZE as f64, TILE_SIZE as f64),
                )); // only the walls will have static bodies
                Wall
            }
            ' ' => Path,
            'O' => {
                maze_meta_data.spawn_tile_initial_pos = (x0, y0); // for having easier acess to the imporant positions
                Spawn
            }
            'E' => {
                maze_meta_data.exit_tile_intial_pos = (x0, y0);
                Exit
            }
            _ => {
                //shouldn't happen, but just in case
                error!("Character {ascii_tile} not recognized in the ascii_maze");

                ErrorTile
            }
        };

        // just for managing general stuff and following the ECS architecture
        tile_entity.insert((
            MazeTile {
                initial_pos: (x0, y0),
                tile_type: tile_type.to_owned(), // cause of the borrow checker
            },
            Transform {
                translation: get_tile_centroid((x0, y0)), // for having the correct position
                // for the rigid body
                ..Default::default()
            },
        ));

        // for ease of rendering
        tile_row.push(tile_type); // but in here I can pass it fully
    }

    maze_meta_data.tile_types.push(tile_row);
}

// we remove all the ascii char, cause we don't need them anymore
ascii_maze.0 = Vec::new();

info!("MAZE TILES LOADED");

}

#

Here the “walls”

sweet sundial
#

"Kinematic" -> no physics, only velocity

green haven
#

Or maybe I didn’t had the plugins correctly set up

#

Like


default())
            // all of this plugins are for PhysicsPlugins to work correctly
            .add_plugins(TimePlugin)
            .add_plugins(TransformPlugin)
            // resources for collision detection
            .init_resource::<CollisionDiagnostics>()
            .init_resource::<SolverDiagnostics>()
            .init_resource::<SpatialQueryDiagnostics>();

#

After adding those plugins the collisions started to work, but before those plugins I got it on dynamic

sweet sundial
#

are you using PhysicsPlugins?

green haven
#

Is above those plugins

sweet sundial
#

i'm assuming that's the bit before the default

green haven
#

Yep

#

Those are from the physicsPlugin

#

But I’m not using bevy’s default plugins

#

Cause I made my own renderer

sweet sundial
#

i assume that means debug gizmos are a no-go?

green haven
sweet sundial
#

if you cut out most of the structure and just have your renderer, a ball with velocity, and a wall, does it work?
unless that would be overly difficult

green haven
#

But maybe tomorrow (it’s 2am)

#

I’ll tell you how it goes

sweet sundial
#

if you're getting collision events with a dynamic body, but it's not being affected, it's probably a somewhat tough issue

green haven
#

I’ll be ditching rigidbodies and just sticking with avian’s colliders

#

Luckly I don’t need complicated physics

#

But I didn’t want to implement ot

#

It*

sweet sundial
#

yeah, it's a little overkill here

green haven
#

A bit, but meh. If it does work I would just need like 20 lines

#

Less

#

8 lines

#

Vs 30 lines of my own implementation

#

Well thx, you are a live saver :D

green haven
#

@sweet sundial It did worked, but I think it wasn't working cause I didn't have the Diagonistic resources

little maple
#

🤔 Jondolf hasn't posted anything in a couple days...

cinder summit
#

I was just gonna comment on how Jondolf talked to me yesterday and Jondolf appears 🤣

vestal minnow
#

uni started up again this week, I'm here but a bit more busy

vestal minnow
#

I believe that panic is because for some reason neither body has BodyIslandNode, which is meant to be added automatically for dynamic and kinematic bodies

little maple
little maple
silk mauve
#

Was just searching through to see if I could find anything about bsn release date and I found this. It's enough to make a grown man cry

summer acorn
#

also given that 0.17 is behind schedule by a lot at this point lol

#

itll land when it lands, cant rush open source

silk mauve
#

If 0.18 were just BSN and it came out a month later I'm sure all the crate maintainers would be mad but I'd be happy

runic tinsel
vestal minnow
#

we did get relationships + a better spawn API in 0.16, which could be argued are a part of Cart's "next gen scenes"

#

and we do have BSN for people to play around with and experiment already, it's just in a PR, not landing for 0.17 :P

past cargo
#

What is BSN?

little maple
bold garnet
#

pronounced bee ess hen

cinder summit
#

-# Still better than B-Scene

spring loom
#

Be seen

fossil pendant
fossil pendant
#

ok I have a bit of a question, I copied the kinematic character controller and I want to make it stick to the ground. I ended up adding a system that modifies the position by the length of a shape cast, but that ends up giving it velocity so it ends up clipping through the ground

#

is there a better way to approach something like that?

viral goblet
#

Also- is there a way to make a collider apply recoil by resizing?
What I mean is
Let's imagine we have two cubes not touching one another
Now I scale up the transform for one of them until it touches the other cube and beyond
Is there a way to make the other cube affected by this scale change and actually move?

#

Guess I can apply velocity manually OnCollisionStart

little maple
#

what is the rigidbody type you're using?

viral goblet
#

The player is dynamic

#

For the "blast" I tried dynamic and static

vestal minnow
#

Some caveats

  • The collision won't consider the speed at which the scale is changing, because from the engine's POV there is no velocity there, it just sees that the penetration depth is suddenly larger.
  • There's a SolverConfig::max_overlap_solve_speed property that limits how fast overlapping objects push each other apart, for stability reasons. By default this is 4 units per second, but you can increase it if needed. Also make sure you have a reasonable PhysicsLengthUnit if you're using pixels for object sizes, since it scales the overlap solve speed.
viral goblet
#

I wonder what I'm doing wrong then

#

I know that the player's velocity works well, so it has to be the blast

#
    RigidBody::Static,
    Collider::circle(260.0),
    Mass(300.0),
    CollisionLayers::new(
        [CollisionLayer::Enemy],
        [CollisionLayer::Collectable, CollisionLayer::WorldCollider, CollisionLayer::Orb, CollisionLayer::Player],
    ),
    DebugRender = stone_head_blast_circle_debug_render(),
)]
pub struct StoneHeadBlastFinalCircle;```

Anything wrong with my setup?
vestal minnow
#

(see the player's collider's color remain dimmed out)

#

omg random aside, someone added Avian next to Bevy in Bévy on wplace

#

that is so cool

hidden hamlet
#

any best practices regarding performance tuning? I'm just spawning a lot of RigidBody:Static 1x1x1 cubes that are not colliding and just by virtue of existing my framerates go to ~2fps vs ~450fps without Colliders (both in release mode) - profiling tells me Avian BroadPhase system is the culprit (running on a AMD 9800x3d)

thin osprey
#

I'm finally getting around to switching to avian

hidden hamlet
# little maple how much is "a lot" ?

at around 48K colliders the FPS starts dipping below 60FPS, around 54K colliders it's below 10FPS
Ideally I would like to push the number much higher .. is 50K colliders doing nothing creating such performance overhead normal or is there anything I can tweak?

I'm also thinking I could enable collisions per entity dynamically since I dont need collisions on all entities at all times but I'd like to avoid frequently adding/removing components if possible

vestal minnow
#

The problem is the broad phase overhead since it's currently not very optimized and even does work for static bodies. It should be fixed with the new BVH broad phase coming Soon™

hidden hamlet
#

that sounds promising, yeah as I wrote in my first post profiling also identified BroadPhase as the culprit

#

is there any way I could mark colliders to be skipped/ignored for broadphase?

vestal minnow
#

But note that it'll also disable spatial queries like ray casts for it

viral goblet
#

It's worth it though

viral goblet
#

Why would it only detect collisions if I move?

#

I made the velocity optional in the query too, and of course both always have transform

vestal minnow
#

Does it work if you make the blast a kinematic body?

#

(also for pushback from a blast, I would personally maybe just manually apply a force/impulse/velocity to bodies inside the blast radius, since that might be easier and give you more control over things; but depends on what exactly you want of course)

golden python
#

Hello, dumb question, but I forgot if there was a component or way to make it so that a scene root will have trimeshes generated for all it's meshes. Or maybe I need to make it myself

viral goblet
#

Thanks!

viral goblet
#

I just want things to only knock back when they hit the blast and not right when it starts

vestal minnow
# golden python Hello, dumb question, but I forgot if there was a component or way to make it so...
echo parcel
#

solver_body.linear_speed shows values in m/s, right?

This is my code to write it on the screen:

pub fn print_debug_data(
    rocket_query: Query<(&SolverBody, &Transform), With<RocketTag>>,
    mut ui_query: Query<(&mut Speedometer, &mut Text)>
){
    for (solver_body, transform) in rocket_query {
        for (mut speedometer, mut text) in ui_query.single_mut() {
            text.0 = format!(" speed: {}\n altitude: {}",
                             solver_body.linear_velocity.y,
                             transform.translation.y
                             //transform.rotation.
                );

        }
    }

}

It prints e.g. 50, but the object doesn't look like its moving at 50m/s pace

sweet sundial
#

it's in units per second, in 2d that's pixels for the default camera

thin osprey
#

if an entity with collidingentities colliders with an entity that is the colliderof another entity, will the parent entity be added to the collider entities

vestal minnow
thin osprey
#

alright, if I write my own system to deal with it, what schedule should it go in?

vestal minnow
#

Either in FixedPostUpdate with .after(PhysicsSet::Sync) (note: on the main branch Sync was renamed to Writeback) or just in FixedLast

#

It should be pretty easy to map "colliding colliders" to "colliding bodies" with ColliderOf

thin osprey
#

shweat thanks

echo parcel
#

Does solver_body shows "net" speed, without e.g. any forces, or if I want to read it, after I added forces working in opposite direction to the speed in previos frames, it should show modified speed?

#

This rocket have height of 6.6m(units). There is no way that is falling at the speed of 138m/s.

The speed print is just printing linear_velocity's Y. Although the transform print looks ok, the size of the rocket to translation pace doesn't match

pub fn print_debug_data(
    rocket_query: Query<(&SolverBody, &Transform), With<RocketTag>>,
    mut ui_query: Query<(&mut Speedometer, &mut Text)>
){
    for (solver_body, transform) in rocket_query {
        for (mut speedometer, mut text) in ui_query.single_mut() {
            text.0 = format!(" speed: {}\n altitude: {}",
                             solver_body.linear_velocity.y,
                             transform.translation.y
                             //transform.rotation.
                );

        }
    }

}
#

Are bevy's shapes using same units as location in the space and avian's physics?

let mesh = meshes.add(Cylinder::new(ROCKET_DIAMETER / 2., ROCKET_HEIGHT));
    let leg_mesh = meshes.add(Cuboid::new(LEG_WIDTH, LEG_HEIGHT, LEG_THICKNESS));
thin osprey
thin osprey
#

Okay apparently the ColliderOf doesn't work how I thought it did at all. I thought it would mean that the collision event raised would contain the parent entity (colliding body).

So I ended up making a pretty scuffed couple systems.
One just reads all the collision events and then raises more collision events but with the colliding body instead.

Then I made a ManyCollidingEntities component that contains HashMap<Entity, u32> and keeps track of the colliding entities.
Needs to track the count since it now holds the colliding body, which may have many colliders with ColliderOf pointing to it - so the collision ending with one might not mean another isn't still active

it is fairly scuffed but now it all works :) so good stuff. I've finished my refactoring moving from rapier -> avian

agile drift
zinc talon
#

Jondolf is there a good way to handle objects colliding through portals? From my perspective an object will only collide with stuff on one side of the portal

#

I've been thinking a lot lately about the idea of "collision proxies", which would be collision shapes that mirror other objects modulo some transformation. Then collisions with that proxy are transformed and forwarded to the mirrored body instead. Very useful for applications where the world is not flat and continuous:

  • Portal/Superliminal
  • big_space cells
  • mixed reference frames
  • worlds that wrap at the edges
#

So I've got a couple questions:

  • what would it take to convince you this is something that should be in Avian, and
  • could you mentor me if I wanted to implement it?
zinc talon
# glacial nebula sensors?

Not exactly. Basically I want an object that says "when something hits me, apply the resulting contact resolution to this other body instead"

#

And ideally it would support transformations as well. I can try to give examples if it's still not clear wth I'm talking about 🙂

zinc talon
vague pebble
#

@remote oxide this seens to be your expertise

zinc talon
#

Here's an example of what I'm talking about. The ball wraps around at the edge of the screen. To handle this graphically, I introduce a "visual proxy" when the ball starts to overlap the edge. You can see though that when I move off the left edge and wrap to the right, the visual proxy starts to overlap the white rectangle. As far as avian is concerned, those two objects are 10 meters away. It's only when I actually wrap the object's position that it starts looking for collisions, at which point it discovers (to its chagrin) that they are deeply interpenetrating.

My hypothetical solution would allow you to spawn a relationship component onto the ball proxy that says "you are a collision proxy for the ball". The physics engine will look for collisions between proxies and external collision shapes, then generate contacts that act on the external bodies and the ball, not the proxies.

glacial nebula
# zinc talon Oh wait, are you suggesting a way to implement portals using sensors?

Was thinking you might be able to use sensors as collision proxies, because physics engines can provide that info from a sensor, but it is not a two-way interaction. This is one reason I've been working toward physics simulation islands for big space, trying to get things to behave reliably between cells with this kind of technique sounds painful.

#

Someone a while back mentioned they did this in the past with Unity(?), so it's definitely doable.

zinc talon
# glacial nebula Was thinking you might be able to use sensors as collision proxies, because phys...

Yeah, admittedly trying to use this for big_space cells does sounds very awkward considering you'd only have a handful of layers to work with. Tbh I only included that one because it's technically overlapping design space. On the other hand, simulation islands doesn't lend itself terribly well to what I'm trying to do with it (collisions interspersed throughout nested, non-inertial reference frames), so I think there's still a lot of value in this approach.

Interesting about the unity impl, I'll have to track that down maybe!

abstract tendon
#

i have a complex glb model and i need to give a collider to it. on blender i can add simple mesh and spawn it with

commands.spawn((
        SceneRoot(asset_server.load("models/complex-model.glb#Scene0")),
        ColliderConstructorHierarchy::new(None)
            .with_constructor_for_name("Collider_Mesh", ColliderConstructor::TrimeshFromMesh),
        RigidBody::Dynamic,
        Transform::from_xyz(0.0, 2.0, -3.0),
    ));

and it works. but i dont want to see this collider mesh, it only needs to be a collider. how can i do that? or is there a better way to add simple collider to complex model

visual sparrow
abstract tendon
#

yeah i thought about the second idea but that model kinda weird shaped so i wanted to give a custom mesh

snow urchin
#

How do you make a vertex based collider?

abstract tendon
#

just added a new mesh and changed its vertex positions to fit complex model

abstract tendon
golden python
#

Hello, I have just a flat plane and a low poly car, with both having trimesh colliders and the car being a rigidbody, and for some reason it just doesn't stop bouncing around, doing flips and stuff.
It doesn't bother me particularly but I thought it might be good to share. Might be something to do with the generated colliders or smth

visual sparrow
visual sparrow
snow urchin
#

without recreating it

visual sparrow
visual sparrow
abstract tendon
abstract tendon
visual sparrow
#

E.g. by its Name

snow urchin
#

Instead of making one with ConvexDecomposition

#

As in I still want to be able to edit the cube but not have to type out the parameters, with it still being something that can be downcast and edited

#

Whether it be a convexdecomposition or not

#

If not I can just type out the vertices and indices

visual sparrow
#

I do that in avian_rerecast, for example

echo parcel
#

I need a secret knowledge about creating collisions for procedurally generated meshes

crystal cosmos
#

It's there a way to have multiple physics worlds? For simulating multiple scenes at the same time

visual sparrow
echo parcel
visual sparrow
echo parcel
echo parcel
#

I've added TrimeshFromMesh into my chunk

let chunk_entity = commands.spawn((
                Mesh3d(meshes.add(mesh)),
                MeshMaterial3d(ground_material.material_handle.clone()),
                TrimeshFromMesh,
                Transform::from_translation(location),
            )).id();

And ColliderConstructor::Sphere {
radius: 1.,
}

into my player:

let player_entity = commands.spawn((
            Player {
                velocity : Vec3::ZERO,
                gravity : 9.8,
                speed : 20.0,
            },
            Transform::from_translation(Vec3::new(32., 32., 32.)),
            Visibility::default(),
            MovementMonitor::new(Vec3::new(32., 32., 32.)),
            MovementComponent {  },
            ColliderConstructor::Sphere {
                radius: 1.,
            }
    )).id();

    commands.entity(player_entity).add_child(camera_entity);

But the player can still move trough chunks. Fresh avian install, no other things done. Did I forgot about anything?

crystal cosmos
#

maybe give it RigidBody::Static?

echo parcel
snow urchin
visual sparrow
#

so you need to query Collider

snow urchin
snow urchin
visual sparrow
#

then call the correct function to get the mutable actual shape

#

In your case probably .as_convex_polyhedron_mut().unwrap()

#

or maybe you'll have a compound of polyhedra, dunno

#

How exactly you can then mutate the polyhedra I don't know

#

but it's something along these lines

#

Sorry if I'm vague, as I said, I haven't ever actually mutated a collider at runtime 🙂

snow urchin
#

What's the difference between .shape() and .shape_scaled()?

#

Also, there's only convex polygon that I can convert it to apparently.