#Avian Physics

1 messages · Page 27 of 1

vestal minnow
#

For spatial queries like shape casts, there's a BVH acceleration structure yeah

#

I'm not too familiar with how boids systems are typically implemented, but based on a quick look, spatial hashing (grids) and quadtrees seem pretty common? A BVH might be fine too though, could always start with that if it's the easiest and see if you end up needing something more specialized

silk mauve
#

I see a lot of quadtree/octrees/kdtrees

#

I have no idea what the performance implications are for choosing one over another.

vestal minnow
#

By state-based logic, do you mean components that are automatically added or removed depending on some state? I can't really think of anything other than Sleeping

#

There will likely be some more that are temporarily added and removed within the same frame though. For example, I'm adding a RecomputeMassProperties component that is added to queue entities for mass recomputation, and removed once it's done. Forces and impulses might also work similarly in the future, with components that are inserted and later removed after applying them, if not applied every frame.

sleek thicket
sand smelt
#

After updating my FPS game to bevy 0.15 and avian3d main stuff generally works, but shortly after I start moving the camera with the mouse my camera starts rotating wildly and shortly after it crashes with this:

Error: The vector given to `Dir3::new_unchecked` is not normalized. The length is 1.011216.
stack backtrace:
   2: bevy_math::direction::assert_is_normalized
             at /home/kris/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_math-0.15.0/src/direction.rs:63:9
   3: bevy_math::direction::Dir3::new_unchecked
             at /home/kris/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_math-0.15.0/src/direction.rs:402:9
   4: <avian3d::position::Rotation as core::ops::arith::Mul<bevy_math::direction::Dir3>>::mul
             at /home/kris/.cargo/git/checkouts/avian-b0a258754c9e72b0/d5b9634/crates/avian3d/../../src/position.rs:728:9
   5: avian3d::spatial_query::update_shape_caster_positions
             at /home/kris/.cargo/git/checkouts/avian-b0a258754c9e72b0/d5b9634/crates/avian3d/../../src/spatial_query/mod.rs:319:36
Encountered a panic in system `avian3d::spatial_query::update_shape_caster_positions`!
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`!

My character controller is a bit janky but it worked with 0.14.2 and avian 0.1.2. It looks like the same issue @formal galleon had a couple of days ago.

vestal minnow
#

I haven't gotten the panic in months :p

sand smelt
# vestal minnow A minimal reproduction would be nice

I'll see if I can extract something.

Did you decide if you wanted to do a small release first or wait until 0.3 is ready? I have some fixes on top of main I could PR, I needed the examples to build in order to test stuff.

vestal minnow
#

at this point I'll probably wait until the full release is ready since people seem to be fine with it / prefer it ^

#

main should compile though, I already merged a PR to make it work with the full 0.15 release

sand smelt
#

It's just small stuff like the bevy_mod_debugdump branch being merged, a few bevy_input fields being converted to methods etc

vestal minnow
#

yeah that's fixed on main

#

about 30 min ago :D

sand smelt
#

Fair, fixed since after I wrote my first message xD

sand smelt
# vestal minnow A minimal reproduction would be nice

I managed to find a reproducer, ShapeCasters don't like to spin apparently. If you add the following function to e.g. the kinematic_character_3d example then after some time the "Dir3::new_unchecked is not normalized" message will start appearing with slowly increasing length values. For faster repro you can do time.set_relative_speed with some high number in setup.

fn spin(mut query: Query<&mut Transform, With<ShapeCaster>>) {
    for mut transform in query.iter_mut() {
        transform.rotate_local_y(10.0);
    }
}

There are no controller examples with any rotation, so if the problem is that rotation needs to be handled differently than just setting Transform then it would be good to add an example for it.

river perch
#

Would be cool to be able to build these kinda ship physics with avian3d

https://youtu.be/9wJRqcVTxpI?t=232&si=q30509slCwJcHhWU

would the approach be have several engines that one can apply physics force to which are attached to a larger rigid body that’s the ship hull?

Adding in realistic spaceship physics is super complicated but also very rewarding. Check out some of the details in today's devlog.

Join our discord https://discord.gg/MnkX2acDrY

Watch the rest of the Devlogs here! https://www.youtube.com/playlist?list=PLCEllhcsdc7Yt7MxD1YIO2lM7ZaRJirCg

Game Collaborators:
Checkout Mr. Meteor https://prebenr...

▶ Play video
#

Or maybe that’s just overly complex what they’ve built. Could just apply angular velocity to the ship hull and let engines onboard just carry data for how much thruster force one is getting in forward and backward direction.

#

And then apply force to the sides, +x and -x

sleek thicket
vague pebble
#

@vestal minnow Is gravity some sort of persisten force? Or you just apply it directly to velocity?

vestal minnow
#

so yes, to the velocity directly

river perch
river perch
vestal minnow
#

you can make your own system that just applies forces based on Newton's law of gravitation or something similar

river perch
#

Or say, like a space base/station. Also need ships to slow down as they’re getting closer to a space station or another bigger object, so need a way to add friction to the ‘air’ around for the ship to slow down so it’s not too difficult for players to slow down upon arriving to the object. Could maybe call it like an artificial atmosphere. Or just like you now said, a system that takes over player control and helps apply the right forces to make things like say docking to the station easier.

river perch
#

I know multiplying anything by 0 does not much 🥴

vestal minnow
#

Generally though GravityScale is intended for specific entities that you want a stronger gravity for, or things like flipping gravity when in some specific area

#

Newton's law of gravitation already applies stronger forces for objects that are close to each other

#

(specifically the force is inversely proportional to distance squared)

river perch
#

Alright makes sense. Wanna try to make as little changes to the physics as possible since I want most parts of the physics behavior to be realistic. Thanks for answering my questions.

vague pebble
#

@vestal minnow An interesting phenomenon in lightyear is ocurring if I turn on gravity rollbacks seen to occur massively. Might be something with lightyear itself, that is why I asked if there was persistence like in external impulse

vestal minnow
#

I think I have everything working for the mass rework finally, I'm really happy with how it works now

#

Simplifies and cleans up internals a lot too, and lets us get rid of some unnecessary state like PreviousColliderTransform. I also got rid of the annoying zero mass warning, it should just be interpreted as infinite mass (almost every engine does this)

#

Just need to work on docs, and I'll make a PR

red shale
#

Cant seem to search here... What should I do to enable Avian colliders with new bevy picking?

#

Ah nevermind - found example

red shale
#

... I get this message when trying to use picking

2024-12-01T18:16:41.892769Z  WARN bevy_ecs::system::function_system: avian3d::picking::update_hits did not run because it requested inaccessible system parameter ResMut<SpatialQueryPipeline>
vestal minnow
#

Do you have the SpatialQueryPlugin?

red shale
#

Yes apparently I did not

#

Though if I add it without PhysicsPlugins::default() I get

thread 'main' panicked at /home/hexorg/Workspace/Public/avian/crates/avian3d/../../src/spatial_query/mod.rs:191:14:
add PhysicsSchedule first
vestal minnow
#

You also need PhysicsSchedulePlugin

#

The plugins are kinda hard to use individually atm, a lot of them are dependent on each other

#

I've been trying to minimize unnecessary dependencies though, and intend to cut them down more

red shale
vestal minnow
#

I think we should clearly define the scope and requirements (plugins or resources required to function) for each plugin, document them, and have integration tests set up to verify that the minimal setup always works

#

And also maybe set up sub plugin groups, like DynamicsPlugins, CollisionDetectionPlugins, etc.

#

this PR is becoming chonky lol

#

I still have a lot more docs to write

glacial nebula
#

@vestal minnow feel free to poke me when you are working on big_space support. We probably have different goals of how we want to support physics, but I'm more than happy to chat about the approach you want to take and help out.

vague pebble
#

Collisions (only if solver warm starting is enabled) @vestal minnow Is that enabled default, dont know where to look at docs?

vestal minnow
#

edited the issue to clarify the defaults

vestal minnow
# vague pebble Thanks, how do I disable it?

I think the relevant thing here is disabling contact matching in NarrowPhaseConfig. It matches contacts from the previous frame to contacts during the current frame, which is used for warm starting contact impulses

app.insert_resource(NarrowPhaseConfig {
    match_contacts: false,
    ..default()
});
#

We should probably have more obvious/discoverable docs for this stuff, although it's kinda low-level

#

You could probably just roll back the Collisions resource too, though it might be a bit expensive if there are lots of contacts

vague pebble
#

The issue weird right now it sometimes occurs sometimes it doesnt

#

I am wondering if it is something with system ordering

vestal minnow
#

could be

vague pebble
#

In my game for example rollback only occurs after i spawn other predicted entities, with sole client

vague pebble
#

this solved it + a little bit of system reordering you are a godamm savant

vestal minnow
#

haha nice!

vague pebble
#

Well he does still rollback when collision occurs but now he doesnt loop hahaa

vague pebble
vestal minnow
#

Warm starting takes contact impulses from the previous frame into account to help things stabilize

#

But without it, contacts shouldn't persist across frames

vague pebble
#

Lovely well in this state I am just gonna say more than good enough

vestal minnow
#

plus an entire new crate (bevy_heavy)

#

PR today or tomorrow

#

might take a while to write a proper description since I'm honestly not sure how exactly the mass properties even used to work 😂

#

I believe the old behavior was very strange, like for example setting CenterOfMass at spawn did nothing unless you also specified an initial Mass iirc

#

now I at least have a bunch of tests set up

sleek thicket
#

the proper description:
"I'm honestly not sure how exactly the mass properties even used to work. The old behavior was very strange."

rocky seal
vestal minnow
rocky seal
#

thanks! task on the top of my todo list depends on some Mass stuff

vestal minnow
#

TLDR of new user-facing behavior is

  • Mass, AngularInertia, and CenterOfMass can be used to set the mass properties of an entity. These are never modified by Avian. If they're not present, the mass properties will instead be computed from the entity's collider based on its ColliderDensity.
  • Mass properties of descendants contribute to the total mass properties of rigid bodies, which are stored in ComputedMass, ComputedAngularInertia, and ComputedCenterOfMass (updated automatically).
  • Automatic computation of mass properties based on descendants or colliders can be disabled with NoAutoMass, NoAutoAngularInertia, and NoAutoCenterOfMass, giving you full control to override them entirely.
  • There's a MassPropertyHelper system parameter for computing and updating mass properties manually. This will probably get more functionality later.
#

And a ton of internal changes, and a ton of new methods and helpers for constructing and computing mass properties

#

One kinda cool random thing I did is that you can set mass properties using Bevy's primitive shapes

let torus = Torus::new(0.5, 1.5);

// Spawn a rigid body with mass properties computed from a torus
commands.spawn((RigidBody::Dynamic, MassPropertiesBundle::from_shape(&torus, 2.0)));

// Equivalent to
commands.spawn((RigidBody::Dynamic, torus.mass_properties(2.0).to_bundle()));

// Use the mass of a sphere but the angular inertia of a torus (because why not?)
commands.spawn((
    RigidBody::Dynamic,
    Mass::from_shape(&Sphere::new(2.0), 1.0),
    AngularInertia::from_shape(&torus, 5.0),
));
rocky seal
#

if the scale of a collider is modified, is the ComputedMass updated to reflect the new size? i'm thinking in cases like the lightning bolt in mario kart - smaller karts get bounced around easier

vestal minnow
vestal minnow
#

(or at least, it should work; if not, let me know!)

rocky seal
#

RecomputeMassProperties is printed to the console..looks like once per collider

#

on this new branch

vestal minnow
#

Oh wow looks like I left that in haha, I was debugging an issue earlier

#

should be gone now @rocky seal

vague pebble
#

@vestal minnow Hmm might I ask how is friction currently applied

vestal minnow
#

(the actual friction constraint is in this file)

fathom cedar
#

forgive me if this has been covered, I did search with not much luck, I cannot figure out how to orient my player in a my top down game towards the direction of input. If I use transform.rotate_y I get a crazy spinning character. I realise this might be because of Avian has control (or should have control) but I only care to use linear velocity for movement. How do I go about this?

hidden girder
vestal minnow
#

Also, bevy_heavy 0.1! #crates message

astral smelt
#

so ready to levy bevy heavy to calculate the mass of my chevy

cinder summit
vague pebble
#

That can be extremely usefull to be honest

vestal minnow
#

the price you pay for decent APIs ig

#

to be fair probably over half of it is docs and tests

#

having to do this to have nice doc examples for 2D and 3D is fun

vestal minnow
#

omg retained gizmos got merged, I think they'll be sooo nice for physics debug rendering

#

thank you @pulsar bone 🙏

#

Does "static lines" mean just that the actual gizmo asset remains unchanged? I.e. I can change Transform without losing the perf benefits

pulsar bone
#

That should be the case

vestal minnow
#

okay nice

fathom cedar
clear dew
#

I just have to say that this is far and away the most pleasing, well documented crate I've ever worked with. It's been a pleasure reading the docs. I'm in love.

#

Thank you for your efforts

hidden girder
vestal minnow
# sand smelt I managed to find a reproducer, `ShapeCasters` don't like to spin apparently. If...

I was looking into this now, and I'm kind of torn on whether we should fix this on the Avian side. The problem here is just that you're performing tons of successive rotations, which naturally results in denormalization over time. That is not necessarily an Avian issue, it's just what happens if you're rotating entities like this, regardless of whether you are using a physics engine.

If you had any AngularVelocity instead, this shouldn't be an issue, since it renormalizes rotations after position integration. By modifying Transform directly, the entity has no velocity from Avian's perspective, and no renormalization is performed / it's left to the user.

I guess we could just perform the renormalization on Avian's side every time rotation is changed though, even if there isn't any AngularVelocity. It might ultimately be nice to provide that guarantee of rotations of all dynamic and kinematic rigid bodies staying normalized.

sleek thicket
sand smelt
# vestal minnow I was looking into this now, and I'm kind of torn on whether we should fix this ...

Thanks for looking into it. I'll try to use AngularVelocity instead. I looked at various example trying to build a character controller for a counter-strike esque game where you rotate the camera with pitch and the pawn with yaw, and I ended up doing it using the transform for the pawn. If AngularVelocity works for that use case then I don't think there's a problem. If there is a comment about Transform denormalizing somewhere and maybe an example that would also be good.

Another option is to add a debug assert that checks normalization and links the correct place in the docs?

void dragon
#

what to do when the wall normal and velocity dot is exactly -1 in a collide_and_slide?

velocity = project_on_plane * remaining * f32::sqrt(direction.dot(hit_data.normal1) + 1.);

I did it like this, and it scales the remaining velocity. However how would someone cleverer do it?

peak schooner
#

This might be an incredibly dumb question, but when spawning a triangle collider (avian2d), are we supposed to enter the vectors in CCW order? I was having issues with non-circle colliders clipping through triangles until I reordered the triangles to CCW. Maybe that's obvious to others, but it took me a min to realize that was my problem. I don't see any mention of CW/CCW order on the docs (tho I might have missed it somewhere)

severe urchin
vestal minnow
vestal minnow
peak schooner
vestal minnow
#

These are actually pretty good for preventing explosiveness for things like chains

urban flume
#

Jondolf be like

spiral nymph
#

are trimesh unable to perform event CollisionStarted ? or I misunderstood how to use it ?

vestal minnow
spiral nymph
#

Hum... I must be doing something wrong then

sacred frigate
#

Does anyone have an example of a vehicle controller using Avian3d?

vestal minnow
#

Finally added a check for cargo doc to CI (to detect dead links etc.)

#

Oh and also I merged the mass property rework and interpolation stuff

#

merged RigidBodyDisabled too

vestal minnow
#

Moves most settings for ray casts and shape casts into RayCastConfig/ShapeCastConfig, renames "time of impact" stuff to "distance", adds a few more configuration options for shape casts, and fixes a whole bunch of docs

#

It's unfortunate how Bevy 0.15 has RayCastSettings for mesh ray casts now, which overlaps with our names a bit. I made a PR to rename it on the Bevy side to MeshRayCastSettings though
https://github.com/bevyengine/bevy/pull/16703

#

My understanding is that Bevy tends to prefer FooSettings over FooConfig, so I might rename a lot of our FooConfig types to FooSettings for Avian 0.3

sleek thicket
#

and it's hard to predict which parts would change, so you could merge pos+rot into it to and use a builder pattern instead

vestal minnow
sleek thicket
#

for a more generic system max range might change often

#

and i guess it'd be possible to store config in component, in which case pos/rot wouldn't change either

#

you could keep cast_x functions as shorthand for xcast(config with all the old params), and let people test new approach without any concerns

#

and i just remembered that we concluded on making our own helper function 🤔

#

i completely forgot about it, but it seems like i arrived at exact same conclusion as before lmao

vestal minnow
#

I would be fine moving the filter out of the config, but otherwise I think the PR's current approach is fine

#

Hmm I might move the filter out, yeah

sleek thicket
#

i'm still not sure what it solves though

#

i'd understand keeping everything in 1 struct and using builder pattern for the ergonomics though

#

let me try to find the part about making custom helper...

#

oh, that was it

vestal minnow
# sleek thicket i'm still not sure what it solves though

I'm mainly thinking conceptually about the bigger picture.

If we consider a single shape cast against a single shape, it should be:

let hit = circle.cast_shape(rect, rect_pos, rect_rot, dir, config);

where config controls how the cast behaves.

If we're instead querying the world for a hit, we have introduced another layer, and we want to filter which entities to perform the shape cast on. This is the same as before, but with an additional filter:

let hit = spatial_query.cast_shape(rect, rect_pos, rect_rot, dir, config, &filter);

I feel like these two should use the same type for config. The filter is for filtering which entities are included, while the config is for controlling how the actual shape cast behaves for those entities.

#

It's also more consistent in the sense that other spatial queries like project_point and shape_intersections have the filter as an argument

sleek thicket
#

i think layer filter would be fine in config, the entity filter is more of a custom thing

sleek thicket
#

you could actually make things like .forward(&Transform) for this too, getting position and rotation in 1 step

vestal minnow
# sleek thicket

This is fine as a helper on the user side but in terms of first-party APIs, I definitely don't want to just put everything in a single struct. The ray origin and direction are what define the actual ray cast, and must be specified, so they should be arguments. The rest (max distance, "solidness", query filter) are extra options, not something that defines the core ray cast.

#

And the query filter is semantically different from the other configuration options

#

We could honestly even do spatial_query.filter(...).cast_ray(ray, &config)

#

The filter applies to all spatial queries

sleek thicket
#

wait a minute

#

you could do into ray

#

and it'd be able to take both (pos, rot) and Ray{pos, rot}

#

and ray from transform could be a helper for ray itself

vestal minnow
#

that'd be (origin, direction) but yeah

#

you could use a rotation too I guess but the direction at Quat::IDENTITY is ambiguous

sleek thicket
#

(position, direction) would make more sense

#

i'm not even sure if i like my own idea, it seems like it makes sense but wouldn't actually be nice in practice

#

getting ori+dir for ray from transform happens pretty often though

#

but something like physics.raycast(template_config.from_transform_z(&t).exclude([entities])); would be neat

vestal minnow
#

not for this release though

sleek thicket
#

mask in config though

vestal minnow
#

Why? It's not configuring how the ray cast behaves, it's adding a filter to the SpatialQuery. It's like adding more filters to Query

sleek thicket
#

i think for this release just do toi -> distance without the rest of it

#

i consider layers to be a part of config that is probably one of the easiest things to share

#

like if you have a damaging ray, you always know that it'll hit enemies and environment, but e.g. max range could change

vestal minnow
#

Sharing config is not really the point, and semantically mask makes no sense in config in terms of how I think about it, and from an internal perspective

vestal minnow
sleek thicket
#

in that case it's just breaking apart params for semantic reasons, and only making it harder to read

vestal minnow
# vestal minnow And with this the layers could be "shared" anyway

You could even do e.g. this

fn foo(enemies: Query<&Transform, With<Enemy>>, spatial_query: SpatialQuery) {
    let filtered_query = spatial_query.with_mask(GameLayer::Player);
    let config = RayCastConfig::from_max_distance(5.0);
    for transform in &enemies {
        let ray = Ray3d::new(transform.translation, transform.forward());
        filtered_query.cast_ray(ray, &config);
    }
}
sleek thicket
#

does that actually improve performance?

#

in that case it actually makes sense

#

but it's definitely harder to read

vestal minnow
#

It doesn't

#

But I don't understand why it'd be in config

#

from a semantic perspective

sleek thicket
#

this actually looks fine

fn foo(enemies: Query<&Transform, With<Enemy>>, spatial_query: SpatialQuery) {
    let filtered_query = spatial_query.with_mask(GameLayer::Player);
    for transform in &enemies {
        filtered_query.cast_ray((pos, dir), &config);
    }
}
#

but if it doesn't improve performance...

vestal minnow
#

yeah but you just removed the part where config and ray are created :P

sleek thicket
#
fn foo(enemies: Query<&Transform, With<Enemy>>, spatial_query: SpatialQuery) {
    for transform in &enemies {
        spatial_query.cast_ray((pos, dir), config.without([self_entity]));
    }
}
#

i've been assuming config is just a struct that can be a const or static

vestal minnow
#

it can, yeah

sleek thicket
#

actually wasn't there already a discussion about moving it to just cast

#

cast(ray, config)

#

cast(shape, config)

vestal minnow
#

no

#

you need the system param there anyway

sleek thicket
#

or was it ray.cast(config) and shape.cast(config)

#

i feel like i'm recovering after amnesia or something

#

you're working on too much stuff at the same time without merging, it's been 5 months now D;

#

but yeah i don't see how it'd actually be possible to make in any comfortable way

vestal minnow
#

I'll at least move the query filter out of the config (like it was before the config struct was even a thing). This is the same as what Rapier does, is more consistent with the other queries, and makes more sense both semantically and in terms of exposed types. Otherwise we will have duplicate config types with the only difference being that one has the filter and one doesn't.

#

I can revert RayCastConfig and have the options as separate arguments like they were previously / are currently on the main branch, but we definitely need ShapeCastConfig to exist.

#

Because this is miserable.

let hits = spatial.shape_hits(
    &Collider::sphere(0.5),
    Vec3::ZERO,
    Quat::default(),
    Dir3::ZERO,
    100.0,
    10,
    0.0,
    true,
    false,
    &default(),
);
sleek thicket
#

it definitely is, but the solution isn't really ideal either

#

would adding a spherecast make performance worse? i don't get why sphere needs a quat

#

oh i just realized you made it worse by adding target_distance and compute_impact_on_penetration, and i don't even know what they do

vestal minnow
#

That's exactly why we need ShapeCastConfig

#

Most people generally don't need to configure them and shouldn't need to specify them manually

#

Without the config types we also need to duplicate docs for all ray/shape cast methods

sleek thicket
#

this doesn't look that much different though

let hits = spatial.shape_hits(
    &Collider::sphere(0.5),
    Vec3::ZERO,
    Quat::default(),
    Dir3::ZERO,
    &config,
    layerTemplate.exclude([one_entity]),
);
vestal minnow
#

Every type is distinct there, unlike the earlier example

sleek thicket
#

let hits = spatial.bikeshedding_sphere(0.5, pos, dir, &config, [excluded_e]);

#

or

#

idk if it'd be possible

#

let hits = spatial.bikeshedding_sphere(0.5, pos, dir, &config).without([excluded_e]);

#

excluded entities just really feels out of place and shouldn't warrant a default anywhere

vestal minnow
#

That isn't, but

spatial.without([excluded_e]).bikeshedding_sphere(0.5, pos, dir, &config);

is, which is just my earlier idea

sleek thicket
#

same thing to me

#

everything non-essential except excluded entities stays in config

#

while keeping excluded entities easily accessible but omitted when unnecessary

vestal minnow
#

Then the different types of filters, i.e. "filter by layer" and "filter by excluding entities" are separated to completely different APIs

#

I would remove excluded_entities and have a predicate instead

sleek thicket
#

is there an internal reason why it had to be merged into 1?

sleek thicket
#

not separating it might eventually cause problems with the editor

#

yup

#

layers feel as much of a property as max range, but excluded entities don't

vestal minnow
#

godot specifically has both the layer mask and excluded entities in the same object

sleek thicket
#

ahhh i hate godot's java-brained get/set so much

#

doesn't seem like unity has excluded colliders at all

#

looking at unity docs i realized

#

config makes sense if treated as a replacement for unity's overloading

#

it'd actually be less confusing than 9 raycast variants where you don't know how parameters move around

vestal minnow
# sleek thicket doesn't seem like unity has excluded colliders at all

I would probably remove it too, except maybe keep it for RayCaster/ShapeCaster for convenience. There's no point paying for the (small-ish) memory and performance overhead of the hash set for every spatial query, when you can easily do the same thing manually with a predicate anyway

#

looking at other engines, they don't tend to have it either, except Godot

sleek thicket
#

i'm using it to exclude self for now but i guess with that fixed it wouldn't be as important

#

it wouldn't make sense to create a whole new layer just to exclude 1 entity though, so maybe it's better to keep it

vestal minnow
#

again, you'd just use your own predicate for that

#

same overhead (or might even be smaller)

#

just |entity| entity != my_entity

sleek thicket
#

how do you continue ray/shapecast after that though

vestal minnow
#

it's a predicate you give to the ray cast, it just ignores entities that don't match and keeps going

#

it's a filter, not an early-exit

sleek thicket
#

is that already here?

vestal minnow
#

or the existing API doesn't allow this ig

#

or it kinda does

#

You can use ray_hits_callback and manually respond to each hit, which is essentially what e.g. Box2D has

sleek thicket
#

you'd need figure out a way to explain it in docs because i wouldn't know what to do if excluded entities were removed and i needed them D;

vestal minnow
#

Hmm random thought, I don't love the naming inconsistency and ambiguity between cast_ray and ray_hits, or cast_shape and shape_hits

#

We could do cast_ray (many hits) and cast_ray_closest (only the closest hit), which also makes the behavior clearer

#

Box2D has this naming

sleek thicket
#

unity has raycastAll

#

i don't really like any of those names though

#

cast_xray maybe? xD

vestal minnow
#

ew

sleek thicket
#

wouldn't work with shapes though

#

actually, couldn't it just be done as a predicate too?

vestal minnow
#

I like that cast_ray_closest makes it explicit that it's specifically the closest hit (with the version that gives many hits, they're not ordered)

#

the traversal algorithm is different

sleek thicket
#

what are they both called

vestal minnow
#

The traversal? Afaik the closest hit version uses a best-first traversal, the other one uses depth-first

#

getting a single arbtrary hit with depth-first is more efficient than getting the closest hit iirc

sleek thicket
#

but it could e.g. pass through walls, right?

vestal minnow
vestal minnow
sleek thicket
#

from what i've seen in unity people either used -all and sorted by distance, or used raycast only vs environment first, then did second ray or sphere cast with that distance

#

i think some consistent naming with bikeshedding_sphere and shapes would make the most sense for it

#

i keep forgetting how it's called in avian

#

in unity it's overlapsphere/box

vestal minnow
#

shape_intersections

sleek thicket
#

yeah

#

still didn't settle in my brain

vestal minnow
#

Unity got the OverlapFoo naming from Box2D

sleek thicket
#

ray_intersections doesn't sound right at all

#

overlap_ray could work

#

ray intersections makes me assume it'd give me points where it intersects with other shape

vestal minnow
#

ray_intersections gets entities intersecting the ray, rays overlapping sounds weird to me

sleek thicket
#

i guess shape intersections is confusing for the same reason

#

maybe something like test_shape and test_ray?

vestal minnow
#

It's also ray_intersections because it's called e.g. a ray-capsule intersection test, and the method for a single shape would be shape.intersects_ray(ray)

sleek thicket
#

that one does make sense

#

cast_ray / ray_cast

overlap_ray / ray_overlap
intersect_ray / ray_intersections
test_ray / ray_test


cast_sphere / sphere_cast

overlap_sphere / sphere_overlap
intersect_sphere / sphere_intersections
test_sphere / sphere_test


cast_shape / shape_cast

overlap_shape / shape_overlap
intersect_shape / shape_intersections
test_shape / shape_test

i think overlap is more intuitive (but it might be a unity bias), but as long as they follow a common pattern it's all good

#

i'd also prefer removing the underscore, but that makes overlap and intersections really bad

vestal minnow
#

Rapier also uses intersections_with_ray

#

This should be consistent with whatever point intersection/containment tests use too

sleek thicket
#

raycast/spherecast/shapecast
raytest/spheretest/shapetest

#

both ending with -st makes them confusing so it has to be something else =/

vestal minnow
#

Hmm random thought, we could technically replace solid with an enum (name TBD) that has an Ignore variant

#[derive(Default)]
enum InteriorHit {
    /// If the query starts inside the collider, stop immediately, and return the result.
    Solid,
    /// If the query starts inside the collider, return a hit at the boundary.
    Hollow,
    /// If the query starts inside the collider, ignore the hit entirely.
    #[default]
    Ignore,
}
#

IIRC that's the default behavior in Unity and Godot

#

It's the same as solid: true and checking if the distance is zero though

#

Okay I reverted RayCastConfig for now, so the ray casting methods are the same as before. I kept ShapeCastConfig though since there's way too many niche parameters otherwise (and it matches Rapier and Parry)

#

I want to get this PR merged since the renames, documentation fixes etc. are valuable on their own

#

We can continue bikeshedding the other things later

#

Merging once CI passes

hexed veldt
#

@vestal minnow I'm getting this warning from avian, I wonder if this would cause FPS to drop. I'm seeing my game have sudden FPS drop randomly for a few seconds once a while. I wonder if the warning is related to the issue

2024-12-08T06:45:39.531002Z  WARN avian3d::collision::narrow_phase: Entity { index: 1119, generation: 5 } (rock) and Entity { index: 1896, generation: 66 } (ammo) are overlapping at spawn, which can result in explosive behavior.
#

All my rigid bodies are set to RigidBody::Kinematic BTW. So I suppose I won't see anything explosive visually

hexed veldt
#

x-post here: not sure if it's related to avian physics

#

i'm using bevy 0.14.2 btw

sleek thicket
sleek thicket
# hexed veldt

yup, fixedupdate can be executed 0 or multiple times per frame

vestal minnow
#

and check if the collisions are expected, like in this case, are the rock and ammo expected to be overlapping?

#

That actual warning doesn't exist on the main branch anymore though, since it was mostly causing unwanted spam for people

sleek thicket
vestal minnow
hexed veldt
#

I'm not sure if the fix schedule explains the issue fully. Here is a frame where the physics schedule ran 15 times per frame. Around that frame, there were total 10+ frames where physics schedule executed multiple times per frame. Seems like a cascading effects causing physics schedule to run many times

hexed veldt
# vestal minnow Could be, it's hard to tell. Make sure you're not spawning a ton of overlapping ...

I'm recycling entities in my game for reuse later. If a rock get destroyed, I will remove RigidBody (as well as Position/Rotation) from the entity (keeping the collider on it still), then move the entity to a Transform::IDENTIY and make it Visible::Hidden. When I reuse the rock entity, I will move the object's transform to the specified spawn position and re-add the RigidBody back to the entity to activate the collision check. Could this cause the issue above?

bold garnet
#

The ecs is already very very good at recycling memory.

hexed veldt
#

i didn't want to do that. my game is running fine on desktop, but suffer from spawning objects containing materials on mobile. based on tracy profiling, i found that every time bevy spawn entities containing materials, or update the uniforms in the materials, the FPS might drop. i'm optimizing my game by

  1. reduce spawn frequency
  2. reduce material uniform update frequency
glacial nebula
#

That should really only happen on first spawn with shader compilation afaik.

hexed veldt
glacial nebula
#

If you are reusing them, you might want to hold on to a strong handle to the materials in a resource, e.g. rock: Handle<StandardMaterial>, and it should stay loaded as you despawn/spawn entities.

hexed veldt
#

Yeah, I have preloaded all my materials into a resouce that contains all the strong handles

glacial nebula
#

In that case, I don't see why this would be an issue after it is spawned at least once.

#

If it is, would be good to report that over in rendering-dev so more knowledgable people can look into it

hexed veldt
glacial nebula
#

Entity pooling is an antipattern though, if you have to do that, something has probably gone wrong. Pooling large allocations is still useful sometimes though.

#

It's almost inevitably going to lead to issues like you are seeing here. Entities should be truly unique, and spawning new ones and handles to things should be cheap.

hexed veldt
#

Some update after test/profiling: Yes, pooling is unnecessary, only the first time spawn is slower. Also after disabling pooling, the FPS sudden drop issue seems gone, although I haven't tested it for extended time.

vestal minnow
#

I think this'll be the last thing for 0.2, aside from maybe some doc tweaks

stuck ember
#

Hey, i'm trying to have a ShapeCaster pointing directly down at all times to detect when the player is on the ground. Currently my player collider is a sphere so it is always rotating. Is there a way to decouple the shapecaster's rotation from the collider's rotation?
here's my player code for reference:

fn setup_player(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    let sphere_radius = 0.5;

    let mut caster_shape = Collider::sphere(sphere_radius);
    caster_shape.set_scale(Vector::ONE * 0.99, 10);

    commands.spawn((
        Mesh3d(meshes.add(Sphere::new(sphere_radius))),
        MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
        Transform::from_xyz(0.0, 1.5, 0.0),
        RigidBody::Dynamic,
        Collider::sphere(sphere_radius),
        LinearDamping(1.5),
        Player,
        Name::new("Player"),
        CharacterController,
        ShapeCaster::new(
            caster_shape,
            Vector::ZERO,
            Quaternion::IDENTITY,
            Dir3::NEG_Y,
        )
        .with_max_time_of_impact(1.0),
    ));
}
vestal minnow
stuck ember
#

Awesome, thanks @vestal minnow ! I was considering manually setting the position of the shapecaster every frame, but SpacialQuery looks like a nicer approach 🙂

#

do you think adding an option to ShapeCaster to decouple it's rotation from the collider would be a useful feature? I wouldn't mind trying to make a contribution if you think it would be desirable

tulip prism
#

Why does this warning start getting spammed after I walk around for a bit with my character controller? I don't use Dir3::new_unchecked without explicitly normalizing, so I don't think it's on my end. The more I move around, the bigger the length number in the warning becomes

#

Using main branch on 0.15 btw

vestal minnow
tulip prism
#

Yes, mouse movement in a system

vestal minnow
#

If you remove that, do you get the warning anymore?

tulip prism
#

Nope

#

So I guess it's cause of the rotation

#

Oh wait it just gave me that error again and panicked

vestal minnow
#

Hmm weird

#

In general if you're rotating something constantly, it's accumulating error over time and you should normalize or renormalize the rotation occasionally

#

physics does this automatically if there's some AngularVelocity, but not for manual rotation changes

tulip prism
#

So just rotation = rotation.normalize()?

vestal minnow
#

Yeah

tulip prism
#

Hmm

#

I'm doing that and it still goes kaboom

#

Maybe it's something else

vestal minnow
#

Is the panic from avian3d::spatial_query::update_shape_caster_positions like this issue?

tulip prism
#

I just spent like 5 minutes trying to get it to panic and realized I didn't set backtrace 1 🤦

sand smelt
#

@tulip prism we've been multiple people further up with the same issue, I think you simply can't reliably rotate the transform on a physics-enabled object atm. My plan is to try to use AngularVelocity for my character controller instead, but I haven't ported to it yet.

#

It would be nice to have rotation in one of the character examples, I think it'll be a common stumbling block

tulip prism
#

Nvm I think it's cause I have debug=0

vestal minnow
#

RayCaster and ShapeCaster are also kind of intended to be equivalent to Godot's RayCast2D/3D and ShapeCast2D/3D nodes, which are also relative to the transform

tulip prism
vestal minnow
#

this is the kinematic character example, modifying Transform rotation directly with a basic slerp

#

(in debug mode)

sand smelt
#

But even though it's hard to trigger you can't really rely on a player not rotating the character enough, especially not in a mouse look game

sand smelt
vestal minnow
#

This should only be a problem with debug_assertions enabled, so the warning and panic shouldn't happen for people actually playing the game. Regardless you should generally renormalize if you're changing rotation frequently, that's what fast_renormalize is intended for (I just realized it actually wasn't added for Quat since the perf difference is small, but normalize does the same)

vestal minnow
sand smelt
#

Nice, is it easy to do from outside avian? Because if I can just opt in to that for my player controller shapecaster that would be ideal

vestal minnow
#

I mean it's just

fn spin(mut query: Query<&mut Transform, With<ShapeCaster>>) {
    for mut transform in query.iter_mut() {
        transform.rotate_local_y(10.0);
        transform.rotation = transform.rotation.normalize();
    }
}
sand smelt
#

Oh, it's just on the affected transform, I somehow thought it was an internal quaternion or something. Awesome, thanks for looking into it

vague pebble
little berry
#

Is anyone working on avian in VSCode?
I can't figure out a way to switch Rust Analyzer highlight between 2d and 3d.

#

I tried some combinations of feature settings in RA, but it felt bugged.

peak marsh
little berry
#

Tried restarting RA server and VSCode

#

Same result

#

Also tried setting rust-analyzer.check.features

vestal minnow
#

I rarely do that though

little berry
#

Oh yeah, I remember doing that in the past.
Thanks.

little berry
#

Has syncing transforms been improved?
I remember it doing some "redundant" propagations in the past.

rocky seal
vestal minnow
#

It does still do several propagation passes per physics tick though, and I think that's (currently) necessary to let people use Transform directly

bold garnet
#

(Btw there is building interest in IK constraint solving infrastructure in #engine-dev . Since that would also need its own propagation loop, maybe we should think about a common mechanism for use by IK and physics.)

vestal minnow
# rocky seal do you use vs code typically? do you just live in 2d mode?

I use VSCode, yeah. I don't feel like I need to use a specific dimension often, since a lot of things aren't dimension-specific, and I usually still get errors and linting even for the inactive dimension. It's mainly stuff like autocomplete, go to definition, and other context-aware things that don't work for the inactive dimension

vestal minnow
#

and then this custom propagation is done in specific parts of the physics schedules

bold garnet
vestal minnow
#

I'm not sure what that would look like / what implications it'd have

#

For a lot of the propagation stuff I think it'd be enough to propagate just from the rigid body entities

bold garnet
#

The hierarchy hooks changes is going to make caching ancestors information possible, which will let us determine m disjoint subtree roots given n changed transforms.

#

So that we can do within-tree parallelism.

#

This is something I def want to try, but I have no idea how your prop stuff works. Don’t want to break it.

vestal minnow
#

I mainly need to do propagation right before physics (to make sure that body and collider positions are up-to-date before simulation) and right after physics (to make sure that the movement of rigid bodies is applied to their descendants).

#

Currently I also have an extra propagation pass right after physics to consider Transform changes that users made during the physics step, but I might remove that and just disallow changing Transform in the middle of physics, not sure yet

#

Also I currently have two types of propagation, one is basically a clone of Bevy's transform propagation, and updates GlobalTransform for trees with physics entities, and the other computes ColliderTransforms for colliders, which is like GlobalTransform but relative to the rigid body, not the world origin

rocky seal
vestal minnow
#

Yeah, it's not great

little berry
#

Could symlinking the primary crate into 3d and 2d crates work?

#

And then separate the 2

vestal minnow
#

Maybe, I vaguely remember someone trying that in the very early days of bevy_xpbd

#

Again the least scuffed approach in terms of crate structure would be to just have a unified avian with 2D and 3D in the same crate (behind feature flags) and separate types for each dimension where relevant

#

It's just a lot of work, and somewhat challenging to do without tons of duplication

#

A lot of things are almost the same between 2D and 3D, with small differences here and there

#

needs a lot of traits at least

rocky seal
#

in the absence of that a documented way to switch between the two that plays nice with r-a would help. maybe just a comment in the toml file mentioning the cursed method

true hearth
#

are forces (e.g. ExternalForce) given in units of force or units of acceleration?

#

nvm just looked into the code, forces are multiplied by inv_mass (so they are given in units of force)

#

in that case I am doing something quite wrong in my code lol

#

i am guessing gravity is just in units of acceleration tho

vestal minnow
urban flume
#

any tips for doing terrain with avian3d? I'm using heightfields and a 1024x1024 field slowed my computer to a crawl, but 256x256 works fine. I haven't added more yet but I'm wondering if I should break it down even further

urban flume
#

debug

rocky seal
#

i wouldn't make performance decisions based on debug builds

urban flume
#

well I'm just looking for general pointers on how to break down the colliders

rocky seal
#

roger. can't help you there i'm afraid - woefully ignorant myself 😛

urban flume
#

just feels like it might be too big but idk what the physics engine is doing in the background

peak schooner
#

Posting an issue that is very similar to what @tulip prism was dealing with above, but with a notable difference. I had a panic due to a spinning physics body, however, this body was not spun by player input or user code. It was a dynamic collider, with locked translation, and no angular damping. Another collider would bump into it, and it would spin endlessly. For me, this issue disapeared once I added an AngularDamping component.
@vestal minnow I see your comment above that this is from a debug_assert (in this case, in Rot2::from_sin_cos), so it wouldn't panic in a release build anyways, and also that this can be corrected by renormalizing rotation (I'll remember fast_renormalization for future use). But that doesn't apply in this case, right - since it's not being spun by any user code?
Obviously I'll avoid endlessly spinning bodies in the future - I was just testing a bunch of random things. Should we include a sentence in the docs warning about this - maybe something saying if you're going to use LockedAxes::TRANSLATION_LOCKED, that you should add AngularDamping? Dummy-proof it for users like me lol
Also possible that I'm completely misunderstanding this error.

void dragon
#

Can I update to bevy 0.15 with avian? The main branch is not compatible right?

vestal minnow
#

(also with translation locked)

peak schooner
# vestal minnow Yeah this looks like a slightly different issue than the earlier one. Do you hav...

Ok here is a gif of it occuring. I can consistently get this panic everytime. When I add a AngularDamping component to the pentagon, I don't get the panic (pentagon goes to sleep). I could go more minimal if you'd like, make a new project and drop a random collider on it (as opposed to the capsule which has character controller code).
Also of note - there is global gravity in this demo, .insert_resource(Gravity(Vector::NEG_Y * 250.0))

peak schooner
#

Update: I went ahead and got rid of the player character controller. I instead am now just dropping a same-size capsule on top of pentagon, no player input. Still same panic.

peak schooner
#

Now trying to go as minimal as possible - will see if I can still reproduce

peak schooner
#

@vestal minnow Super minimal reproduction here: https://github.com/dylanafterall/panic_test
Will usually get the panic in first minute or two.
I tried to keep the collider dimensions and gravity magnitude the same, but now using default camera settings.
Running on a M1 macbook.
I usually assume I'm doing something stupid - still the most likely cause.

GitHub

Contribute to dylanafterall/panic_test development by creating an account on GitHub.

little maple
#

I updated my game to bevy 0.15 and am using main avian (e23d070)

I noticed that... while my truck movement is smooth, the smaller objects in the truck bed aren't.. but they have the TransformInterpolation component added. This wasn't happening to me on 0.14 with the
bevy_transform_interpolation crate.

I'm going to keep digging into it, just wanted to see if anyone knows something obvious I might be missing

little maple
#

it does seem less noticeable at 60fps vs 120

rocky seal
#

i have anecdotally also noticed choppier movement using the interpolation built-in to avian (choppier than when i was using the crate separately before its integration)

#

i have added some other systems that run every fixedmain too tho, so it's not a perfect comparison case. but i didn't add that much and i have a fairly powerful machine

#

this is in debug - it's smooth in release

true hearth
#

is there a way to get the effective forces that have been applied to a rigidbody during the solving constraints step? Or should I just go ahead and calculate themselves by measuring the change of velocity?

little maple
rigid flare
#

are there any other known causes of jitter using bevy_panorbit_camera and camera following code?

assuming I've got this

            .configure_sets(PostUpdate, PanOrbitCameraSystemSet.after(PhysicsSet::Sync))
            .add_systems(
                PostUpdate,
                Self::camera
                    .after(PhysicsSet::Sync)
                    .before(TransformSystem::TransformPropagate),
            )

#

(note the jitter seems to be non-deterministic depending on the run of the executable)

little maple
rigid flare
#

what's really weird is that some runs it's smooth, some runs it's jittery

little maple
rigid flare
#

it's not like the jittery turns on and off, it's just either always on, or always off

rigid flare
little maple
rigid flare
little maple
rigid flare
#

now I just need to get tracy to work on nixos with X11

vestal minnow
vestal minnow
#

Also do you happen to manually modify their transforms anywhere?

#

(currently bevy_transform_interpolation treats that as teleporting if done outside the fixed timestep schedules, which could potentially cause some jitter or other weirdness if done repeatedly)

vestal minnow
vestal minnow
#

both run after physics and before transform propagation, but it looks like their relative order is left ambiguous atm

rigid flare
vestal minnow
#

Not sure, I haven't implemented camera following with bevy_panorbit_camera

#

whatever doesn't jitter :P

rigid flare
#

yeah I think I'm gonna end up just writing my own orbiting camera, I was just being lazy and putting things together that I'll need

#

last time I was making a game (a decade ago) I started from the game engine with glium and shiet, and I ended up not making the game at all stuck writing dependencies, so I'm trying to force myself to do the entire opposite :P

vestal minnow
#

impulses are only stored for each individual constraint and contact

true hearth
#

I see, thanks. Guess it wouldn't be too hard to just get them from the velocity change

vestal minnow
#

yeah, that's probably a fine estimation

rocky seal
little maple
little maple
void dragon
#

Love you Jondolf, no need to clone the filter anymore

#

(shape_cast filter parameter)

little maple
urban flume
#
commands.spawn((
    RigidBody::Dynamic,
    Collider::trimesh_from_mesh(&mesh),
    CollisionMargin(0.05),
));
little maple
silk mauve
#

Am I good to update to 0.15? I see that avian supports the RC

vestal minnow
#

Ah the README still says 0.15 RC, it's supposed to be the actual 0.15 release

#

I'll fix that

#

But yeah I'm not adding any more significant breaking changes or features for Avian 0.2, mainly working on release notes and the migration guide

hidden hamlet
#

since updating bevy to 0.15 and avian3d to main branch, my logs are endlessly filled with

Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.9997351.
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.9997351.
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.99948585.
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.99948585.
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.9995516.
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.9995516.
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.99973494.
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.99973494.

I use transform.look_to() to rotate my entities and if I remove the transform.look_to() the warning goes away.
The system runs during FixedUpdate. Tried using both RigidBody::Kinematic and RigidBody::Static as I currently move the entities via transform.translation.move_towards().

Normalizing the rotation after transform.look_to() also does not help:

transform.look_to(direction_norm, Vec3::Y);
transform.rotation = transform.rotation.normalize();
assert!(transform.rotation.is_normalized(), "Failed to normalize rotation");

(The assert never triggers, so I'm fairly certain the rotation is normalized 😄)

Any ideas?

urban flume
rocky seal
#

will a body's angular velocity make its ballistic trajectory curve like it would in air?

#

and if not, any idea how i could impl that?

vestal minnow
#

It won't be in 0.2. I want to properly explore this area and try various different APIs and approaches first, I just haven't had time for it yet.

#

There's a ton of different ways to approach character controllers, from both an API and implementation perspective, especially in an ECS context like ours. If we ship a built-in character controller, or even just tools for creating one, I want it to be polished and robust

urban flume
#

darn I might just roll my own then

#

tnua is a bit jumpy and I switched from rapier to avian because the rapier controller wasn't detecting "grounded" state like it should have

#

I sort of like rapier's API but didn't play around with it that much. I like having full control and having to implement my own gravity and such because it makes it easy to switch off gravity for swimming, climbing etc

vestal minnow
# rocky seal will a body's angular velocity make its ballistic trajectory curve like it would...

You mean like how a spinning ball curves in the air? No, that's very shape-dependent and not something we could realistically implement in a general way. I think this would be the Magnus effect

The Magnus effect is a phenomenon that occurs when a spinning object is moving through a fluid. A lift force acts on the spinning object and its path may be deflected in a manner not present when it is not spinning. The strength and direction of the Magnus effect is dependent on the speed and direction of the rotation of the object.
The Magnus e...

vestal minnow
# rocky seal and if not, any idea how i could impl that?

For balls specifically, intuitively I think you could get a rough approximate version of the effect by simply applying a force perpendicular to the movement direction and the axis of rotation

// Something like this maybe?? Scale the magnitude until it feels right
let f = lin_vel.cross(ang_vel);
#

(I have not tested this)

rocky seal
rocky seal
#

is there any way for me to temporarily turn off all of the physics for an object (including collisions) and move it myself by mutating the Transform, and then turn it back on to have it start interacting again from wherever i've placed it?

#

i know there's Sleeping but the docs say that gets cancelled whenever there is something that would affect it physically

vestal minnow
rocky seal
hidden hamlet
zinc grove
#

Is it possible to have multiple systems running in the same app, but running at different time frequencies? From what I see in the examples it all runs off of the app's global FixedUpdate interval. I'm trying to optimize some very taxing simulations involving tens of thousands of entities with a lot of collisions. I want to break up the simulation into coarser resolution parts that can run update much less frequently. So basically several unconnected collision systems running at different frequencies that I can connect manually myself where necessary.

hexed veldt
little berry
hexed veldt
#

Are there any planned release for 0.15?

rocky seal
zinc grove
# rocky seal you could use Res<Time<Fixed>>> and early return except at some cadence

For sure, but what I'm wondering is how to stop Avian from recalculating ALL collisions on every fixed update. I just thought of a potential solution, actually, using collision groups, if I duplicate my entitie's translation components into different groups and then only update their positions at my desired lower frequency, then even though Avian is still running at its normal frequency I imagine that if none of the entities in a collision group have changed position then there must be an optimization in Avian that prevents it from recalculating collisions for that group.

vestal minnow
# hexed veldt Are there any planned release for 0.15?

I'm just writing release notes and the migration guide now, I'd expect the release to be ready within 2-6 days. The main branch won't have any large changes before the release, apart from maybe documentation improvements or small bug fixes, so you can use that in the meantime

vestal minnow
# zinc grove Is it possible to have multiple systems running in the same app, but running at ...

Currently, not really, since the engine uses the ECS directly, so the systems operate on all active physics entities and use the same schedules. I can potentially see us making things more flexible in the future though, perhaps making the core simulation systems take generic query filters and providing some system parameters or other tools for stepping physics manually for entities with specific marker components. We could also add something like Rapier's AdditionalSolverIterations once we have simulation islands, allowing you to roughly control simulation fidelity for specific entities. Not sure what kinds of things we can reasonably support, but these things are definitely worth exploring

cinder summit
#

Cause the current sleeping implementation is the archnemesis of my rollback library 😂

vestal minnow
#

that, and the joint rework ideally

#

(i.e. impulse-based joints with motors, servos, nicer limits, nicer stiffness configuration, local frames, and other improvements)

vestal minnow
#

I wonder how well simulation islands as entities would perform lol

cinder summit
#

Only one way to find out 🧠

vestal minnow
#

Technically it would kinda make sense, assuming we're going for persistent islands; islands need identifiers (Entity), you want to be able to mark them as sleeping or as candidates for splitting (marker components), and you want parallel iteration over them

#

could even use relations if we had them :P

#

but it'd still involve a lot of spawning and despawning

#

and I would assume that it'd probably have more overhead than just having islands chucked in a resource

#

I guess I'll have to try both lol

rigid flare
#

okay, I rewrote the camera stuff myself, and even when it's not following anything I get jittery movement on some runs, and not jittery movement on others, any other ideas of what might be going on?

glacial nebula
#

that sounds like system ordering

#

there is some system you depend on that you need to explicitly order against

#

my guess is it needs to be before transform prop if you are doing this in PostUpdate, or after some physics system. I don't know the full context though, just a drive by.

rigid flare
#

could this be happening from movement stuff? just changing velocities or dampening without proper ordering?

#

the example didn't seem to use any ordering stuff for that kinda thing

glacial nebula
#

Possibly.

rigid flare
#

I think it's something else, if I disable the damping, and touch the move once, the thing keeps moving but also keeps jittering without input coming from anywhere 🤔

rigid flare
#

found it, it was the TransformInterpolation thingy

keen ridge
#

hello

#

im using avian2d and creating a world with vec2::zero gravity, when i create a rigidbody dynamic entity with a collider, and update linear velocity briefly (like a tap the button and increase velocity for a few updates) it goes back down to 0 velocity. but if i increase it enough it stays moving with constant velocity. what happening?

rocky seal
#

getting this panic:

thread 'main' panicked at /home/ty/.cargo/git/checkouts/avian-b0a258754c9e72b0/b47c30c/crates/avian3d/../../src/collision/collider/mod.rs:369:9:
assertion failed: b.min.cmple(b.max).all()
#

it happens in collision::collider::backend::update_aabb

#

not sure if it's my messy hacking or not

#

possibly relevant details: i'm adding RigidBodyDisabled and ColliderDisabled to a ball and then manually updating its transform.translation to be equal to the ball carrier's transform.translation each tick until the ball carrier throws it somewhere

#

at which point i'm setting the ball's translation to somewhere well outside of the collider for the ball carrier and then removing those components

#

oh i wonder if this happens when i set its translation to somewhere inside a different collider 🤣

vestal minnow
# keen ridge im using avian2d and creating a world with vec2::zero gravity, when i create a r...

This is likely due to Sleeping, which stops simulating rigid bodies when they're moving slow enough for some time, until woken up by some interaction. How slowly are the bodies moving with those small taps?

#

(also see the docs of the component if you want to disable or tune the sleeping behavior)

vestal minnow
rocky seal
#

time for me to learn about AABBs

vestal minnow
#

an axis-aligned bounding box is just the minimum and maximum extents of the collider along X, Y, and Z

#

like a sphere with a radius of 1 positioned at [2.0, 1.0, 2.0] would have an AABB like

ColliderAabb::from_min_max(Vec3::new(1.0, 0.0, 1.0), Vec3::new(3.0, 2.0, 3.0))
rocky seal
#

gotcha. i don't think i am manipulating any collider extents

vestal minnow
#

It's in global space so it changes as your colliders move

#

so the position or rotation could be NaN somehow

#

which would cause the AABB to be invalid

#

for debugging it could be useful to log the AABB, position, and rotation of the entity that seems to be causing the crash

#

(right before the crash if possible)

rocky seal
#

there aren't that many entities and this happens fairly quickly so i'll just log all of them. brb

#

ok the position of the ball is Vec3(NaN, NaN, NaN)

rocky seal
#

ok i think i know what the problem is:

commands.spawn((
    Ball::default(),
    SceneRoot(assets.load(GltfAssetLabel::Scene(0).from_asset("ball.glb"))),
    ColliderConstructorHierarchy::new(ColliderConstructor::TrimshFromMesh),
));
#

using ColliderConstructorHierarchy to attach the Collider components to a child of the entity rather than the entity itself makes using ColliderDisabled slightly not obvious

#

i suspect applying ColliderDisabled to the parent entity doesn't do what we want?

vestal minnow
#

If it's a rigid body, you could use RigidBodyDisabled instead?

rocky seal
#

i'm using both

#

moving the collider onto the parent entity seems to work at least to prevent the Position from becoming NaN

#

but it still panicked on the same assert, later on

#

still investigating

vestal minnow
#

hmm

urban flume
#

is it possible to tick the physics simulation manually?

#

I want to do server-authoritative multiplayer with prediction/reconciliation, so when I get an authoritative state from the server I need to rewind the state of things and re-run physics to catch up to the current frame

rocky seal
#

ok i've resolved the panic. definitely my error. but i do think it was fruitful to identify the ColliderDisabled gotcha

keen ridge
#

should i be creating rigid bodies with a transform component or should i use the position and rotation already included?

true hearth
#

they definitely need a transform to be rendered at least (not sure if required), and I think the library is intended to be used so position and rotation could be ignored by the user, since they are automatically synced to the transform

#

@keen ridge

keen ridge
#

ok

#

so theres no difference if im querying for transform::translation or rotation and rigidbodyqueryonly::position and rotation? it feels kind of redundant

vestal minnow
#

Position and Rotation are global physics positions, and have different representations for 2D and 3D. Transform is local and relative to the parent.

#

In general, I consider using Transform to be more idiomatic, and Position and Rotation are more for physics internals

#

But you can use them directly too if you want, some people prefer that

urban flume
#

and thanks !'

vestal minnow
#

you can also pause the clock if you only want to advance it manually

urban flume
#

that makes sense, keep the clock paused and advance it manually like in the example

#

I'm guessing I should advance that during FixedPostUpdate if my game logic is all in FixedUpdate

urban flume
#

hm I might have to rewind the time if that's even possible - run_physics_schedule seems to override the default Time resource which I'm guessing would mess up my other systems that use the Time resource

true hearth
#

my project compiles with bevy 0.15 👍 now onto the speedrun challenge of figuring out why the physics are broken before the migration guide is out 😛

true hearth
#

the docs now say that the ShapeHitData.point2 and point1 are given in world space, but I'm pretty sure they are given relative to the respective shape positions. So, to get the world position, you would need hit_data.point2 + shape2.position

#

in practice, you would probably do something like
hit_data.point2 + cast_origin + cast_dir * hit_data.distance

#

to get the contact point in world space

#

ok I now tested with a rotated shape, and it actually affects the results (despite the shape being a sphere), so maybe the point2 is given in local space after all

#

but I'm pretty sure at least normal1 is given in world space

sleek thicket
true hearth
#

ah yeah, definitely missed that

#

but it doesn't solve everything for now

crimson crest
#

... forgot to filter out my entity from the spatial query rookie mistake

crimson crest
#

Anyways, I'm experimenting with moving the solver logic into avian's collision detection and keeping the actual sliding plane solving logic separate

warm oracle
true hearth
keen ridge
#

is there a way i can access a rigid bodies "acceleration"? like isntead of accumulating linear velocity, i just set an acceleration value, like on button press, i give it an external force, and remove it on release? so that i can query for it and implement behaviour depending on its acceleration ts

hidden geyser
#

Is it possible to get the current angle of a revolute joint?

vestal minnow
#

Alright, I had to take a couple of days off to de-stress from stuff, but I have the release notes and migration guide pretty much ready now

#

I intend to release 0.2 tomorrow 🪶

vestal minnow
#

We'll probably have an API to get this from the joint directly after the planned joint rework

hidden geyser
hidden hamlet
#

quick question regarding timings: if I change the Transform (or Position?) of an Entitiy with a Collider could a SpatialQuery detect the new collision before the next PhysicsTimeStep?

vestal minnow
#

the update is currently relatively expensive though

hidden hamlet
#

good to know, thank you! 🙂

severe urchin
vestal minnow
severe urchin
vestal minnow
#

Avian uses whatever schedule is given to it (FixedPostUpdate by default on main). If that matches lightyear, it should have the correct ordering

#

If lightyear and avian use different schedules then yeah it'd be wrong, but at that point the system configuration in general would be wrong since it'd be for the wrong schedule

severe urchin
#

ok yeah i think it's probably ok. there's some older code still using FixedUpdate and doing app.add_plugins( PhysicsPlugins::new(FixedUpdate)... but in that case it sets up the ordering correctly anyway i think.

#

thanks 🙂

floral acorn
#

This is quite likely to be user error, but I'm seeing

error: cannot find macro `round_op` in this scope
   --> /Users/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wide-0.7.30/src/f64x2_.rs:652:36
    |
652 |         Self { sse: round_m128d::<{round_op!(Nearest)}>(self.sse) }
    |                                    ^^^^^^^^
error: cannot find macro `round_op` in this scope
   --> /Users/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wide-0.7.30/src/f32x4_.rs:683:35
    |
683 |         Self { sse: round_m128::<{round_op!(Nearest)}>(self.sse) }
    |                                   ^^^^^^^^
error: could not compile `wide` (lib) due to 2 previous errors
warning: build failed, waiting for other jobs to finish...

on MacOS builds in CI. The wide dependency seems to be from avian via bevy_heavy. Just an FYI, I'm not really sure if Mac support is high on the list at the moment! (I don't particularly need it, was just setting up a new project).

vestal minnow
#

I think it can only come from simba through Nalgebra

#

since that does use wide

floral acorn
#

ah, yes maybe I didn't look far enough up the tree 👀

#

let's see...

#

yep you got it

vestal minnow
urban flume
keen ridge
#

holy skibidi

severe urchin
#

looking good! the bit about debugging to find a flipped sign made me wince 😬 I wonder if physics engines have the highest ratio of time spent debugging to patch fix size

keen ridge
#

here is my spaceship. 2024-12-21T11:57:28.570342Z INFO space_game::spaceship: Applying force: Vec2(-7071.0684, -7071.067) from: Vec3(7.5, 12.5, 0.0) 2024-12-21T11:57:28.570356Z INFO space_game::spaceship: Applying force: Vec2(7071.068, 7071.068) from: Vec3(-7.5, -12.5, 0.0)
i apply forces from the top right and bottom left of the rectangle, both inwards at 45 degrees. shouldnt this make the spaceship rotate? because it isnt

fiery mortar
keen ridge
#

does this not make it spin around

fiery mortar
#

I believe they are canceling eachother out. if they were parallel it would spin

keen ridge
#

they are parallel

junior rock
#

He means "if the lines were going at 180 degrees both (but in different directions)"

hidden hamlet
#

Congratz on the 0.2 release!

Just noticed two warnings on my derive(PhysicsLayer) after updating:

unexpected `cfg` condition value: `2d`
no expected values for `feature`
using a cfg inside a derive macro will use the cfgs from the destination crate and not the ones from the defining crate
try referring to `PhysicsLayer` crate for guidance on how handle this unexpected cfg
the derive macro `PhysicsLayer` may come from an old version of the `avian_derive` crate, try updating your dependency with `cargo update -p avian_derive`
see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
`#[warn(unexpected_cfgs)]` on by default

the second warning is the same but with "3d" instead of "2d"

did not find anything in the 0.2 release notes or in the docs regarding this, any clue?

vestal minnow
#

Have you run cargo update?

hidden hamlet
#

yep, and cargo clean. did also try cargo update -p avian_derive to no avail

vestal minnow
#

Hmm I'm not getting it with a fresh setup

hidden hamlet
#

I just tried compiling with rust stable v1.83 and there are no warnings, so this seems related to the current rust nightly (I used nightly v1.85 before)

peak marsh
#

Yeah, I'm getting this warning too and I'm on nightly.

#

It looks like that the macro expands to:

#[cfg(feature = "2d")]
use avian2d::prelude::PhysicsLayer;
#[cfg(feature = "3d")]
use avian3d::prelude::PhysicsLayer;
impl PhysicsLayer for FooBarLayer {
    ...
}

It seems like a reasonable warning to me, so I'm surprised that it doesn't warn on stable

#

The macro currently works because the user is likely to have PhysicsLayer in scope from the prelude. But if you do:

#[derive(avian2d::prelude::PhysicsLayer, Default)]
pub enum FooBarLayer {
    #[default]
    Foo,
    Bar,
}

It'll fail: cannot find trait `PhysicsLayer` in this scope. It'll probably also fail if there's a 2d/3d feature actually present.

turbid mango
#

👋 Just updated my game to use 0.2.0, and noticed that now occasionally the player character seems to noclip through the floor of specific portions of the level. This seems to:

  • Happen consistently for the same floor pieces every time it happens
  • Only happen for floor pieces with relatively thin colliders (I'm using convex hull colliders)
  • Only happen for some of the app runs
  • Happen far more often on my laptop which has a 120hz display than on my desktop which has a 60hz monitor
  • When the debug gizmos are enabled, the colliders are displayed normally, even when the noclip happens

Is it possible that this is related to the schedule changes and my character controller? I originally adapted it from the kinematic character controller example, while still under 0.1, and this wasn't happening

turbid mango
#

Tweaked my spectator camera setup to allow teleporting the player entity back to inside the map, so I can try falling through the same collider multiple times. Looks like for whatever reason, after upgrading to 0.2, for some of the entities the Collider component is registering but the RigidBody::Static is not having any effect, the same "broken" floor piece is also intangible for the concrete crumbs that I spawn whenever the player shoots the walls/floor, but is a valid target for shapecasts

vague pebble
#

As it gives more time, for the get out of me systems to act

urban flume
turbid mango
#

Okay I think I've figured it out, though I don't fully understand it. It isn't the collider size or the velocity of the character, as I was able to find larger colliders in the stage with the issue, and tried very slow velocities. I have a system in place to remove/add colliders and rigid bodies to entities on the map based on proximity to the player/other character entities, to reduce the overall number of rigid bodies in the scene. When I disabled that system, the issue went away. (Even if the app ran much slower)

I did some further experimentation, and turns out if I remove an entity's Collider but not it's ColliderAabb, and then add the collider back, it seems to occasionally corrupt/desync the acceleration structure used by the broad phase, so even though the entities still have all the components, the collisions fail for them. When I modified my system's logic to remove the ColliderAabb and re-add it along with the Collider, the issue went away.

(This system runs in Update schedule, so I thought maybe there was potentially some weird timing/sequencing interaction with the system that updates the acceleration structure. I changed it to FixedUpdate and the bug didn't go away)

Something I don't understand is that we now have ColliderDisabled, and I tried to modify the system to use that instead of removing the Collider, as perhaps that would be a less error prone method of getting this to work, and the noclip bug persisted. However, the system that adds entities back to the acceleration structure specifically seems to handle this case so it should work?

urban flume
#

is it really necessary to remove the colliders? I thought avian did a lot of that work for you

turbid mango
#

I did a very naive "buckets" setup, tuned to my specific map size/scale where each rigid body can be in one or more buckets on a grid and the buckets can be flagged as active or not, to stash and unstash the rigid bodies and colliders, and that brought it up from 20-30 FPS to 120+ FPS

#

But there's probably a better way of doing this, it's very hacky

#

ColliderDisabled and RigidBodyDisabled are probably parts of a more proper solution now that they're available (until simulation islands at least? at which point maybe the 50k+ rigid bodies will be totally fine without any extra work) but I tried using them and still hit the same spurious noclip bug

cinder summit
# turbid mango `ColliderDisabled` and `RigidBodyDisabled` are probably parts of a more proper s...

I think having 50k rigid bodies will always end up having some cost over having say 500 relevant ones. Especially since afaik Jondolf didn't actually finish that rework to a BVH broadphase, nor swap out parry for something with more reliable performance characteristics. I'd imagine anything doing change detection also gets expensive at 50k, and there are some optimizations bevy could do for that

#

I'd imagine simulation islands don't actually affect how static bodies affect scaling however, since if they did the whole world would just have to become one big island

turbid mango
#

but overall adding and removing the rigid bodies has been very straightforward, even if it occasionally requires tweaks, like in this case I had work around this ColliderAabb issue

cinder summit
#

Even skipping them would require some lookup, which I guess optimally would be a BVH, so 500 vs 50k ends up maybe doubling the depth instead of requiring 100x as many iterations

#

Ah yea the broadphase rework is in the "whats next"

#

Also can't find any details on switching to the "driver component" approach (StaticBody, DynamicBody, etc deciding the requires instead of RigidBody) to avoid adding components to static/kinematic bodies that they don't need, but doing so could reduce the number of entities that match a query and also speed up any change detection that happens 🤔

vestal minnow
cinder summit
#

Could make it so that users can't ever construct a RigidBody 🤔

vestal minnow
#

I guess it could also be called RigidBodyMarker or similar to make it more explicit that it's just a marker component and not a "driver component" but it's still not entirely clear

cinder summit
#

Calling it RigidBodyMarker could definitely be clearer (and simplify migrations since the errors would make sense)

vestal minnow
#

Another option would be to make RigidBody default to a dynamic body, and make KinematicBody and StaticBody require it, but then everything requires the components of a dynamic body again

cinder summit
#

Also wouldn't get the cool benefit of finally being able to query only the types you want

vestal minnow
#

You could technically, just a bit more annoying for dynamic bodies

  • Dynamic: Query<Entity, (With<RigidBody>, Without<KinematicBody>, Without<StaticBody>)> (could have a type alias for the filter)
  • Kinematic: Query<Entity, With<KinematicBody>>
  • Static: Query<Entity, With<StaticBody>>
#

but yeah I think I'm leaning towards DynamicBody, KinematicBody, StaticBody, and a shared RigidBodyMarker

sleek thicket
vestal minnow
#

a Collider currently doesn't have collision response

#

i.e. other things can't bump into it

sleek thicket
#

is that behavior required for kinematic or something else?

vestal minnow
#

not really

sleek thicket
#

then wouldn't it make sense to just assume collider is static, unless dynamic/kinematic/sensor is added?

vestal minnow
#

I think that is an option, yeah

sleek thicket
#

on the other hand static marker might be really useful for other stuff

vestal minnow
#

In general, all your physics objects that participate in the simulation are rigid bodies, and you attach collision shapes to them; if we get rid of explicitly marking static bodies, you kinda lose that "thing that shapes are attached to"

#

but I think that may be fine for static geometry

sleek thicket
#

immutable by default 😤

lethal oasis
#

what do I need to make this plugin work? I've implemented it like so:

app.add_plugins((
    DefaultPlugins,
    PhysicsPlugins::default(),
    PhysicsDebugPlugin::default(),
));

Added the player:

#[derive(Component)]
pub struct AvianRigidBody(pub RigidBody);

#[derive(Component)]
pub struct AvianCollider(pub Collider);

#[derive(Bundle)]
pub struct PlayerBundle {
    pub _marker: Player,
    pub rigid_body: AvianRigidBody,
    pub avian_collider: AvianCollider,
    pub sprite: SpriteBundle,
    pub linear_velocity: LinearVelocity,
}

pub fn setup_player(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
    texture_info_cache: Res<TextureInfoCache>,
) {
    commands
        .spawn(PlayerBundle {
            _marker: Player,
            rigid_body: AvianRigidBody(RigidBody::Dynamic),
            avian_collider: AvianCollider(Collider::rectangle(0.5, 0.5)),
            sprite: SpriteBundle {
                sprite: Sprite::default(),
                texture: /* ... */,
                transform: Transform::from_xyz(0.0, 0.0, 300.0),
                ..default()
            },
            linear_velocity: LinearVelocity(Vec2 { x: 10.0, y: 0.0 }),
        });
}

Then ran a simple system to display its position:

for (velocity, transform) in players_query.iter() {
    println!("linear velocity: {}", velocity.0);
    println!("pos: {}", transform.translation);
}

result:

linear velocity: (10, 0)
pos: (0, 0)
linear velocity: (10, 0)
pos: (0, 0)

It's not affecting the Transform at all. What did I do wrong? It's not displaying any debug info either, no errors. I am on bevy 0.14 and avian 0.1.2.

vestal minnow
#

Your entities don't have RigidBody or Collider components, only your own wrappers

sleek thicket
#

@marble cradle are meshe colliders simplified and have a convex hull? is terrain and everything else large in chunks? those are the only knobs i know, maybe someone here knows more

marble cradle
#

yes and yes. it runs pretty well on my pc now that i upgraded it but struggles on my laptop stiill which is weird

#

at least i can work w it now for development

vestal minnow
#

Got an initial implementation of a contact graph working 👀

#

It's a modified version of petgraph's UnGraph (undirected graph) along with an entity index to map Entity IDs to node indices in the graph. Largely similar to what Rapier has with its Graph, Coarena, and InteractionGraph.

#

Box2D seems to handle the contact graph by maintaining doubly linked lists on each body directly, but I feel like it'd be trickier to make that work nicely API-wise, and it seems less flexible

#

Still need to make a bunch of changes to handle edge addition and removal properly and emit collision started/ended events as part of the narrow phase, instead of the current scuffed way it's handled

#

Also need to try changing the narrow phase to maintain bit arrays for edge addition/removal, like Box2D

#

After that stuff is done, simulation islands should hopefully be easier to implement. I already have the core logic and wiring for island merging and splitting, but got blocked on needing this contact graph

little berry
#

What is the contact graph for?

#

Coloring collisions?

vestal minnow
#

It's just a graph where nodes are bodies/colliders (entities) and edges are contact pairs. For a lot of things, like island splitting, you need efficient look-ups for all contacts associated with a body, and with a graph that is trivial. The old/current storage for Collisions on the other hand is just an IndexMap, which requires you to iterate over all contact pairs just to find contacts associated with a specific entity

#

The current Collisions::collisions_with_entity is also very slow because of this, since it's O(n), where n is the number of collisions in the world. With a graph you can just directly look up the edges associated with the entity

#

We'll also want a constraint graph for joints, it's needed for at least simulation islands and it will let us efficiently handle disabling collisions between bodies attached via joints

abstract tendon
#
pub fn m4_shooting(
    mut m4_props: Single<&mut M4>,
    mouse_input: Res<ButtonInput<MouseButton>>,
    mut shooting_event_writer: EventWriter<ShootingEvent>,
) {
    if mouse_input.just_pressed(MouseButton::Left) && m4_props.okay_to_shoot {
        shooting_event_writer.send(ShootingEvent);
    }
}

pub fn ball_contact_checker(
    ball: Query<Entity, With<Ball>>,
    crosshair: Query<Entity, With<CursorCrosshair>>,
    mut hit_event_writer: EventWriter<HitEvent>,
    mut shooting_event_reader: EventReader<ShootingEvent>,
    mut collision_event_reader: EventReader<Collision>,
) {
    let ball_entity = ball.single();
    let cross_entity = crosshair.single();

    for _event in shooting_event_reader.read() {
        for Collision(contacts) in collision_event_reader.read() {
            if contacts.entity1 == ball_entity && contacts.entity2 == cross_entity {
                info!("test");
                hit_event_writer.send(HitEvent);
            }
        }
    }
}

i have this basic system when i click left mouse button, it sends shooting event. if two collisions are touching eachother when shooting event happens, a hit event send. for some reason sometimes it sends two hit events and sometimes it send one hit event. i tested this with info!("test") is it something with avian or am i doing something wrong?

lavish cedar
abstract tendon
#

I guess i can but i wanna learn why its not consistent

vestal minnow
#

not sure though

abstract tendon
#

well i guess its a good guess but i cant put those systems in fixedupdate

crimson crest
#

Working on updating the WIP kinematic character controller draft

#

Using the latest iteration of vidar's version

#

Example doesn't seem to want to build though

#

... Not related to avian though, wgpu-hal being wgpu-hal pain

lyric sorrel
#

Hey, I've noticed an issue with change detection, wanted to check if it's already on your radar here before opening a PR or anything: because the functions in semi_implicit_euler take their mutable inputs as lin_vel: &mut Vector etc., the systems in integrator call them using &mut body.lin_vel.0 etc., which immediately triggers change detection and the "has this actually changed" checks inside the integration functions don't have the desired effect (the Mut from the query has already been deref_mut()-ed). Changing those functions to accept the whole body: *IntegrationQueryItem structs would fix change detection, but break being able to call them easily in tests

#

I've done some messing around and found that changing the parameter types from e.g. lin_vel: &mut Vector to mut lin_vel: impl DerefMut<Target=Vector> does the trick - passing a &mut ref in tests still works and using body.lin_vel.as_deref_mut() in the systems works to project out the inner type from newtype components (more generally, mut_component.reborrow().map_unchanged(|c| &mut c.field) can project out arbitrary fields as well)

#

I've got a branch where this should be fixed (at least in the cases I've found, I might be missing some) that I can send in a PR from if that'd be helpful

crimson crest
#

Major notes from the original implementation attempt: Split pass system, (gravity and movement are done in separate passes, meaning gravity can be constantly applied. This does come with the sideeffect that jumping needs to set gravity instead of the velocity), it has a backout during a gravity pass to only prevent sliding behavior. Basic depenetration.

I need to rename all the component names still.

Also, didn't end up using linearvelocity though I probably should. It was mainly not done for the take of simplicity, there's probably several components that could be rewritten to use avians instead

sleek thicket
vestal minnow
# crimson crest <@545959292281552928> https://github.com/Jondolf/avian/pull/606 Merry christmas,...

Thanks, feels a lot better than the original! IIRC that one got stuck very easily when I tested.

Some initial things I noticed based on a quick test (I haven't reviewed the actual code properly yet)

  • If I jump at a ceiling, the character hovers in the air rather than stopping and falling down
  • Sometimes, walking down slopes is jittery
    • When the character is in this "state", walking off of a ledge will make the character fall at an abnormally high speed, implying that there's some built up gravitational acceleration
  • There's some jitter and other weirdness when walking into a crevice with two unclimbable surfaces
  • Landing on the floor feels "softened", it's not an immediate stop
crimson crest
#

Landing on the floor is softened to avoid doing a floor snap, but I can maybe come up with a better way to do that

#

Maybe only start applying the gravity reduction if you're grounded for two ticks

#

The ceiling issue might be fixed by adjusting gravity velocity after the collide and slide pass if gravity is going backwards from its application direction

#

The intent of the soft landing was to prevent situations where you just downwarp cause you're building up speed as you're on the ground without having the character controller float at a variable height due to the ground detection

#

If you have a better solution let me know

vestal minnow
#

Right, makes sense

#

Btw lemme know if you want this demo scene, I just whipped it up in Blender a few days ago. Dunno if you already have a better one

#

it should also have a checkerboard ground shader but idk how to make it show up in Bevy :P

crimson crest
#

Would make a much better test scene yeah

#

You can add it to the pr if you want

#

I also need to figure out why the macos compile breaks due to expecting dvec3, is the test runner running with both the single and double precision features enabled?

vestal minnow
vapid monolith
vestal minnow
#

The AABBs are just sorted along the x axis with the current impl. Checking for disjoint x intervals is the primary pruning mechanism and needs to be done first. The order was originally different, but checking x first is a 10x improvement
https://github.com/Jondolf/avian/pull/219

vapid monolith
#

Oh i guess its so that the user can define custom interactions between multiple layers

vapid monolith
vestal minnow
#

To be clear the current broad phase is super basic and just always sorting along x isn't good :P the plan is to switch SaP to separate BVHs for dynamic, kinematic, and static bodies

#

with support for incremental updates

vapid monolith
#

I suppose SaP is prob the most used in other game engines so it makes sense to have that as a default

vestal minnow
#

It's just a plugin so it should be replaceable either way, dunno if there'd be first-party alternatives though

vestal minnow
#

Rapier is the only one I know uses SaP, though it's not traditional SaP but its own unique "Hierarchical SaP" with grids and stuff

#

ah PhysX also used to use SaP, it's different now though

vapid monolith
crimson crest
#

When did physx move off sap?

vestal minnow
#

Hmm, or I might be partially wrong 🤔 PhysX does have SAP as an option, but also has several "box pruning" algorithms that are bounded to "regions of interest", I just haven't found anything about what it does inside those regions

  • sweep-and-prune (SAP)
  • multi box pruning (MBP)
  • automatic box pruning (ABP)
  • parallel automatic box pruning (PABP)
  • GPU broadphase (GPU)
vestal minnow
#

okay yeah the box pruning algos do seem to be just SAP applied to bounded regions, where the automatic variants compute those bounds automatically

vapid monolith
vestal minnow
#

Ooh nice, my new narrow phase seems to be a decent amount faster than the old one already, based on some quick tests. Very WIP though, and not even parallelized yet

#

Hmm I do need to figure out contact callbacks/hooks, I'm not sure if I can keep a whole schedule like PostProcessCollisions in between contact computation and contact event stuff

arctic fulcrum
#

I want to make my terrain into a collider; it's currently a patchwork of triangle meshes [since I intend to have some holes and overhangs, a heightfield unfortunately won't work for my purposes]. My question is: to what extend does the resolution of the trimesh collider impact performance? For large, static meshes, are they automatically treated with some kind of spatial lookup, or is there something I can do to help avian accelerate collisions with the terrain mesh(es)?

#

or, for example, is it better to have one larger trimesh collider, or to split it into, say, 16 smaller patches which are each their own trimesh collider?

vestal minnow
#

The main caveats are:

  1. You can only have one of each type of hook in the world (a contact filter hook, a pre-solve hook, and maybe some others)
  2. There are a few specific components and resources you cannot query for, at least not mutably. You get a runtime panic if you do.
    It's very similar to bevy_rapier's physics hooks. It's a shame you can only have one of each hook, but I think the limitations are probably acceptable, they're similar in most engines I know (Rapier, Box2D, Jolt...)
vestal minnow
arctic fulcrum
#

Ahah, I see - it turns out that this isn't actual Avian-specific, but it's consistently happened to me when I've tried to integrate avian into my Bevy project, and now I know the cause/fix: I was having a weird issue where for the first ~5 to ~10 seconds after starting the app, the game was running at like 2-5FPS. And then, over that time period, it gradually improved until it ran completely smooth.

The problem is that my setup function is really slow. On its own this would be fine, but it creates a big time debt in the Time<Fixed> resource, which means that FixedUpdate needs to run many times in order to catch up. But when all of these physics objects spawn, that takes a while, so it's barely able to catch up, so there's still a big time debt. My desktop is a bit faster, so it's eventually able to make up for the lost time, but it takes several seconds (and many iterations) to do this.

The fix is to just cap the amount of FixedUpdate time delay (at least initially) - I added app.insert_resource(Time::<Virtual>::from_max_delta(std::time::Duration::from_millis(60))) and now it catches up basically instantly, so it runs smoothly.

void dragon
#

Is avian keeps track of collider's shapes? For example capsule, cylinder etc.

crimson crest
#

@vestal minnow Early morning question, should I have been using shape_hits instead of cast_shape in the kinematic controller?

crimson crest
#

Seems to be a no, rewriting it to use shape_hits seems to introduce ghost collisions, hm

#

Jondolf can you send me that better physics testing ground you have

#

I think I might have made a noteworthy improvement here, using shape_hits and computing a weighted average normal I think might have made it more reliable

#

Its pretty expensive to do though

cinder summit
cinder summit
crimson crest
# cinder summit Really depends on what you want. shape_hits gives you all the hits without any m...

In short, what I ended up doing is this:

let hits = spatial_query.shape_hits(
    &controller.collider,
    transform.translation,
    transform.rotation,
    velocity_dir,
    4,
    &config,
    filter,
);

if !hits.is_empty() {
    // Use the closest hit for safe movement distance
    let closest_hit = &hits[0];
    let safe_distance = closest_hit.distance;
    let safe_movement = current_velocity * safe_distance;

    transform.translation += safe_movement;
    total_movement += safe_movement;
    current_velocity -= safe_movement;

    if let Some(aggregate_normal) = compute_weighted_normal(&hits) {
        last_hit_normal = Some(aggregate_normal);

        if is_gravity_pass && should_stop_on_slope(slope, floor_detection, aggregate_normal) {
            continue;
        }

        current_velocity = calculate_sliding_velocity(
            &mut collision_planes,
            aggregate_normal,
            current_velocity,
        );
    }
} else {
    transform.translation += current_velocity;
    total_movement += current_velocity;
    current_velocity = Vector::ZERO;
    break;
}
#

Its fairly expensive

#

Don't have an exact benchmark, but it seems more reliable than all my approaches so far

cinder summit
#

I think the way shape_hits works does make it more expensive yea

#

Sadly with character controllers it's rare that getting "the first hit" (which often isn't even accurate) is correct

#

With ground detection for example getting 1 hit makes you slide when you're standing on the wedges in Jondolf's demo scene 🤔

crimson crest
#

I'll need to think some more on the design here though still

#

Though also need to rework the entire gravity system in general

cinder summit
#

Hmmm ... That might not even be enough if it's one collider with multiple pieces of geometry that clash like that 🤔

crimson crest
#

Hmmm

void dragon
void dragon
cinder summit
floral acorn
#

Just an FYI in case anyone else strikes this: the MacOS-only issue with Avian builds was down to the use of a feature-gated macro in wide (a dependency of simba). They've fixed the issue, so probably doing the likes of cargo update -p wide or generating a new Cargo.toml will sort things out. https://github.com/Lokathor/wide/issues/186

dreamy lion
#

My child collider sensor is one step behind its parent rigid body position. Is this expected or am I maybe missing something?

cinder summit
#

I remember there generally being an issue with some gizmos being behind a step, tho I can't remember why

vestal minnow
#

The rigid body axes seem to be at the right spot and only the collider is behind, so it seems like an actual bug

#

Hmm, for collision hooks, I don't think I can allow mutable ECS access, just read-only access

#

because it's iterating over the contacts in parallel

#

Okay I can provide access to Commands with ParallelCommands so that you can at least queue commands inside the hooks and handle deferred changes that way, though the execution order will be arbitrary

#

Yeah I think these limitations are acceptable

  • Only read-only ECS access, but can queue commands, and modify contact data directly
  • Only one set of hooks per narrow phase and broad phase
#

It's about the same caveats as in bevy_rapier, Box2D, etc.

#

I'll probably make PRs for these things I'm working on roughly in the order of

  1. Collision hooks
  2. Contact graph
  3. Rework contact pair logic (more persistence, bit sets, reworked event handling, contact flags, etc.)
  4. Simulation islands?
    Before merging 2-4, I want diagnostics and better stress tests though, to both see how things improve and to see how it compares against Box2D, so I'll have to work on that
cinder summit
#

You forgot this one:

  1. Driver components
vestal minnow
#

Got some more cool stuff cooking up: contact tangent velocities (for e.g. conveyor belts), per-manifold friction and restitution (for e.g. non-uniform material properties for terrain), and some renames and refactors for contact data types

#

Rapier has configurable friction, restitution, and tangent velocities for each point in a given manifold, but that seems somewhat overkill imo, and engines like Jolt also just seem to have per-manifold material properties

#

I feel like it makes sense to think of it like contact manifold == contact surface, and each surface has a configurable material, not the points

little berry
#

And not what it "feels" like it should be.

#

It "feels" that the manifold should just be a bunch of points on a plane.

#

But idk how it actually works out with weird objects colliding.

vestal minnow
#

It is basically just a bunch of points on a plane, often limited to 2 points in 2D and 4 points in 3D (though we don't / Parry doesn't limit 3D atm)

cinder summit
#

Surely you need that for uh ... a collision between a sphere and a torus where the torus has a gradient of friction properties going one way and a gradient of restitution properties along the perpendicular axis ferris_spooky

#

Every point you sample has different properties bavy

little berry
vestal minnow
little berry
#

is this a possible manifold?

#

or is it convex only?

vestal minnow
#

Those would be two different manifolds

#

A manifold describes a contact surface, I would consider those to be two different surfaces

cinder summit
#

I mean usually things that aren't convex are also separated until they become convex for performance too, which would probably guarantee they will always yield separate manifolds 🤔

vestal minnow
#

For example for a trimesh, each triangle has its own manifold, even if it's just a plane

little berry
vestal minnow
#

If a cuboid is resting on a plane formed by two triangles, the contacts for each triangle belong to a different manifold, even though they have the same normal

little berry
#

Yeah, that makes sense. Thanks for clarifying.
Manifolds were this weird thing I saw in parry that stores contacts that I wasn't really sure about what it is exactly.

lyric sorrel
quartz heart
#

I noticed something strange when upgrading my project to avian 0.2.0, simple cube colliders started randomly rotating.

I managed to reproduce it in the example repo:

#

Its hopefully possible to see, some of the cubes just continously rotate.

#

here is the slightly modified cubes sample where I could reproduce it.

(yes the colliders are smaller than the mesh)

quartz heart
#

In my project I can remove the random rotations if I increase the mass of the cubes by 10x.

vestal minnow
vestal minnow
#

I'm wondering though if we even want the current checks 🤔

#

If a body is sleeping, it shouldn't run integration for it at all, and otherwise it's being simulated and I would probably expect it's velocity and position to be updated every frame

#

The only case where that might not be true is if all translational and/or rotational axes are locked (but it would start sleeping), or for position integration when a kinematic body has zero velocity. Or an edge case where a dynamic body has no velocity at zero gravity, but then it should also get marked as sleeping. I'm not sure if these special cases are worth handling, except maybe the kinematic case

vestal minnow
#

with zero friction it's fine

vestal minnow
#

Thanks again for the repro, this was an important thing to fix

#

I'll make a PR

#

I'll probably also make a patch release in a few days

#

I like how all of these critical fixes that massively improve stability are one line changes

cinder summit
vestal minnow
#

The 3D friction is partially based on Rapier's implementation, but the math is handled slightly differently, since Rapier stores angular inertia as the inverse square root and we just use the inverse, and I didn't consider that correctly in this case :P

#

In Rapier the inertia term should be twice here to get rid of the square root, but we just want it once

#

Hopefully now the friction should be correct 😂

#

though we still just straight up don't handle static friction separately from dynamic friction (same as most engines) even though Friction has a static coefficient (unlike most engines)

#

I should probably try incorporating it again, last time I tried it caused it to be an unstable mess but that might've been because of the other issues, which are now fixed

crimson crest
#

Hm, that reminds me, I should implement friction into the character controller

#

Would (probably) remove the need for separate gravity passes and such if the materials you slide upon have friction

vestal minnow
#

@grizzled depot There may be some things there that could be useful for Rapier/bevy_rapier too. E.g. I figured out a (mildly scuffed) workaround to specify hooks without requiring unnecessary generics like PhysicsPlugins::<()>::default() for the cases where you don't need hooks (you might remember my issue on this). I think it's nicer especially for new users.

#

I also feel like bevy_rapier's API for hooks overall isn't exactly great, it's pretty low-level and uses Rapier and Nalgebra types. Not sure if there's too much you can do there without significant changes or extra overhead though

#

Something that may be nice is to expose Commands like I do, since mutable ECS access isn't otherwise allowed in hooks

#

Oh and small detail, BevyPhysicsHooks in bevy_rapier should probably have a bound on ReadOnlySystemParam, not SystemParam, since it doesn't allow mutable access anyway. It might be more explicit and give errors earlier that way (didn't test in bevy_rapier, just in Avian)

urban flume
#

anyone have example code of spawning a gltf and creating a trimesh from it?

#

I got something working but it feels janky

#

I'm loading the mesh and material in a Startup system like this

    let tree_mesh = server.load(
        GltfAssetLabel::Primitive {
            mesh: 0,
            primitive: 0,
        }
        .from_asset("tree.glb"),
    );
    let tree_material = server.load(
        GltfAssetLabel::Material {
            index: 0,
            is_scale_inverted: false,
        }
        .from_asset("tree.glb"),
    );

then storing those handles, and in an Update system I check if any of the handles are loaded then spawn the mesh and collider etc

hazy orbit
#

this may be a dumb question, but is there a way i can visualize the collider heightfield? my mesh is displaying properly but i keep falling through the floor

peak marsh
vestal minnow
# urban flume anyone have example code of spawning a gltf and creating a trimesh from it?

You can use ColliderConstructorHierarchy on the scene root entity. See the collider_constructors example

vestal minnow
vestal minnow
#

Of course you can access the Collisions resource in any system (almost) anywhere, but filtering and modifying contacts only really works in hooks

#

The returned bool just determines if the contact pair should be kept. If you return false, that contact is removed. Similar to doing .iter().filter(...)

vestal minnow
hidden hamlet
#

awesome! thanks!
also noticed in your newest PR the mention of improved "one-way platforms" - I think I asked a few months back for one-way colliders, if I understand this right this would enable this as well?

vestal minnow
#

They're already possible with custom systems, the PR just adds hooks which will be the new recommended place to handle it. But yeah you can implement colliders that only allow collision from one side, like what many 2D platformers have

#

The one_way_platform_2d example demonstrates one way to do it (this is the old version, it's slightly different in the hook PR)

hidden hamlet
#

yeah I looked at the old and new example, was just looking for confirmation I understand it correctly 🙂 thank you!

cinder summit
hazy orbit
golden python
#

I have a rigidbody dynamic with a ExternalForce with a non zero force and persistent set to true but it's not moving, any ideas ?
I also added the plugin ofc

hazy orbit
#

hmmm well now after looking, first off, i thought the params for the heightfield were the spacing between points, so my collider was tiny lol, but now it seems like my heightfield is rotated o.O

urban flume
#

if you're using the plane builder to make your mesh it's probably 90 degrees off, the columns/rows are backwards IMO

hazy orbit
#

I figured it out. My mesh is made with data[z][x] and height field expects the opposite

#

I have no idea how to make games btw

#

lol

golden python
subtle epoch
#

Excuse me, for the EventReader<CollisionStarted> , when it listens for a collision event between two entities, there is no specific order,right? For example, when a player collides with the ground, sometimes the player is entity1 and sometimes the ground is entity1🤔

vestal minnow
#

IIRC at least in contact data like Contacts, the order is practically arbitrary

subtle epoch
vestal minnow
#

Yeah I think #480 made it like that

vestal minnow
#

Huh, TIL that Jolt has enhanced internal edge removal for arbitrary compound shapes, not just trimeshes and heightfields like Parry/Rapier 🤔

#

This would make tilemaps and such without ghost collisions possible without specialized collider shape implementations

#

The dream would of course be that it wouldn't be limited to compound shapes, and it'd also work if each collider was on a different body, but I'm not sure if that's possible

lyric sorrel
# vestal minnow If a body is sleeping, it shouldn't run integration for it at all, and otherwise...

Yeah, that's fair enough - maybe the checks are more trouble than they're worth. The thing I had in mind was that it means the world-space angular inertia is recalculated every frame (because Changed<Rotation> always passes) for all bodies that are moving, even if they have zero angular velocity. With lots of rotation-locked objects moving around I could see that being a problem, but it probably wouldn't be an issue in most cases

vestal minnow
#

Yeah, I suppose rotation-locked dynamic objects moving around isn't too rare, given that a lot of dynamic character controllers might be like that 🤔

vestal minnow
vestal minnow
vestal minnow
#

Huh, I realized we can/should make ContactManifold store just a world-space normal instead of a separate normal1 and normal2 in local space

#

In XPBD it was necessary to recompute transformed normals everywhere, but now we just use the world-space normal computed before the substepping loop for contact constraints, so there's no point storing local normals in the manifold

#

It'll also make contact modification nicer since you can just modify a single world-space normal

#

The contact points need to remain in local space though, unless we store a DeltaRotation/AccumulatedRotation for applying rotation changes like Box2D does 🤔

light vessel
#

I'm trying to get the width and height values of a rectangular collider. I thought I could do that by querying for the size of the ColliderAabb, but it returned the Vec2: [-inf, -inf]. Any ideas on an alternative to get these values? Should I be using the entities transform?

vestal minnow
#

You can get the actual collider's size by accessing the raw Parry shape though, it's just a bit annoying

// This is a Nalgebra vector type!
let half_size = collider.shape_scaled().as_cuboid().unwrap().half_extents;
// Convert to Glam and scale to full size
let size = 2.0 * Vec2::from(half_size);
#

purely an abstraction thing, I think it technically doesn't need any internal changes

light vessel
errant dome
#

Hey, quick question: Are there any debug-tools available for avian? I'm thinking in the direction of gizmos outlining a collider.

willow ice
#

@errant dome

errant dome
golden python
#

Anyone know of an example of observers used for collision detections with Avian ?

jolly rover
#

Does anyone know what schedule and set ordering is required for a system to have access to snap an entity to a given target position when the current physics step would result in arriving or overshooting the target position? But without disrupting any of the other systems. For example, using avian to interpolate grid based movements and maintain proper collision detection? Like I don't want to create a false collision if it traveled the full overshoot distance. And I don't want to snap it if there's something in the way that would have otherwise prevented it.

jolly rover
hidden hamlet
floral acorn
#

I'm looking at ways of implementing collision with an uneven, non-tilemapped, non-rectangular surface in 2D. So for example a sprite walking across an undulating platform. It seems that I might be able to make the platform a bitmask, but I'm not sure if Avian already provides a method to do this or if I'd need to look at a custom collider perhaps?

floral acorn
#

I'm watching the original creator of Lemmings, Mike Dailly do this and they were basically translating each individual pixel in the mask into a 2D array and checking each lemming to see if they were in contact with the mask! Not sure how sustainable that would be, I guess Noita probably did it to some extent also 😆

#

I know we have LayerMask in Avian but I'm thinking that's not quite the same thing...

floral acorn
#

I think the difficulty with heightfield would be complex shapes with overhangs, etc.

formal heart
floral acorn
#

mind you that also appears to use heightmaps. Have to experiment with a more complex image 🤔

golden python
#

Hey, I want to do stuff only if a laser and an asteroid collide, right now it looks like this but this feels a bit innefficient

pub fn collisions(
    mut collision_event_reader: EventReader<CollisionStarted>,
    laser_q: Query<Entity, With<Laser>>,
    asteroid_q: Query<Entity, With<Asteroid>>,
) {
  let mut maybe_laser = None;
  let mut maybe_asteroid = None;
  
  for CollisionStarted(e1, e2) in collision_event_reader.read() {
      if laser_q.get(*e1).is_ok() && asteroid_q.get(*e2).is_ok() {
          maybe_laser = Some(e1);
          maybe_asteroid = Some(e2);
      }
      if laser_q.get(*e2).is_ok() && asteroid_q.get(*e1).is_ok() {
          maybe_laser = Some(e2);
          maybe_asteroid = Some(e1);
      }
      let Some(laser) = maybe_laser else {continue;};
      let Some(asteroid) = maybe_asteroid else {continue;};
       //do stuff with laser and asteroid
  }
}

Is there a better way to do this ?

rustic bone
#

Hey, is there a way for bodies to stop jumping/hitching when crossing over seams in ground/wall colliders?

fiery mortar
#

Is there a way to have a second larger collider on an object. I still want the one that matches the size for updating the mesh but would like a seperate one for raycasting that is larger so objects are easier to point at

cedar ermine
# golden python Hey, I want to do stuff only if a laser and an asteroid collide, right now it lo...

I have a query_collision function which determines which query item is involved in a collision.

pub fn query_collision<'a,D,F>(query: &'a mut Query<D,F>, collision: &CollisionStarted)
    -> Option<QueryItem<'a, D>>
where
    D: QueryData,
    F: QueryFilter,
{
    let CollisionStarted(entity1, entity2) = collision;
    if query.contains(*entity1) { return query.get_mut(*entity1).ok(); }
    if query.contains(*entity2) { return query.get_mut(*entity2).ok(); }
    None
}

Use it like this.
It'll work with any query data, not just the Entity.

fn collisions(
    mut collision_events: EventReader<CollisionStarted>,
    laser_query: Query<Entity, With<Laser>>,
    asteroid_query: Query<Entity, With<Asteroid>>,
) {
    for collision in collision_events.read()
    {
        let Some(laser_entity) = query_collision(&mut laser_query, collision) else {
            continue;
        };
        let Some(asteroid_entity) = query_collision(&mut asteroid_query, collision) else {
            continue;
        };

        // do stuff with the collision entities
    }
}
cedar ermine
fiery mortar
#

Ohhh I forgot about collision layers thank you

#

Do u happen to also have a solution for shaking objects when they are small

#

No worries if not ofc but figured I'd ask

cedar ermine
cedar ermine
fiery mortar
little maple
# rustic bone Hey, is there a way for bodies to stop jumping/hitching when crossing over seams...

your question sounds like what I ran into here

#1124043933886976171 message

back then I did some digging and I found there wasn't a good solution at the time and... I read enough stuff referencing other engines that made me think this is a common, inherent problem. I followed a raycast vehicle tutorial to solve my problem and it works really well (and also reduces collisions which is great)

but there might be other ways to tackle the problem. I'm not an expert on it, just dug into it over time since asking that question

formal galleon
#

Is it possible to exclude some CollisionLayers from the PhysicsDebugPlugin? I use different CollisionLayers for different RenderLayers, because I have multiple scenes, but I always see all Colliders, which is a bit disturbing.

#

Or any other way to handle this?

golden python
#

I have a lot of situations where I want to delete objects on collision (bullets for example) but for every one of these I often get a warning that I tried to delete an already deleted entity:

pub fn asteroid_collisions(
    mut commands: Commands,
    mut collision_event_reader: EventReader<CollisionStarted>,
    laser_q: Query<Entity, With<Laser>>,
    asteroid_q: Query<Entity, With<Asteroid>>,
    mut health_manager: HealthManager
) {
    let mut maybe_laser = None;
    let mut maybe_asteroid = None;

    for CollisionStarted(e1, e2) in collision_event_reader.read() {
        if laser_q.get(*e1).is_ok() && asteroid_q.get(*e2).is_ok() {
            maybe_laser = Some(e1);
            maybe_asteroid = Some(e2);
        }
        if laser_q.get(*e2).is_ok() && asteroid_q.get(*e1).is_ok() {
            maybe_laser = Some(e2);
            maybe_asteroid = Some(e1);
        }
        let Some(laser) = maybe_laser else {continue;};
        let Some(asteroid) = maybe_asteroid else {continue;};

        commands.entity(*laser).despawn();
        health_manager.damage(*asteroid, 10.);
    }
}
Could not despawn entity 94v3#12884901982 because it doesn't exist in this World. See: https://bevyengine.org/learn/errors/b0003

Anyone know of a good workaround ?

vestal minnow
golden python
#

thanks

vestal minnow
#

you can disable the global gizmos with e.g. this, and use DebugRender to override it for the entities you want

app.insert_gizmo_config(PhysicsGizmos::none(), GizmoConfig::default());
#

I might split the component at some point like ColliderDebug, RigidBodyDebug, JointDebug, etc.

vestal minnow
#

I'll probably do a patch release soon

fiery mortar
#

Yay! Thanks I don't mind switching to main

vestal minnow
fiery mortar
#

Yeah I was planning on trying that just havent yet

vestal minnow
#

Whoa, cool!

vestal minnow
#

Is anyone using Contacts::total_tangent_impulse or Contacts::total_tangent_force()? I realized they technically might not be accurate since the tangent directions can change between substeps, and the contact data also doesn't store the tangent directions anyway, so it's unclear which way the impulses are pointing, especially in 3D where there's more of a friction cone

#

so I'm thinking I might remove them

#

you can still manually compute them by going through the contact data and getting tangent_impulses

vestal minnow
#

I can't decide if ContactData should be ContactPoint or ManifoldPoint (like Box2D), or something else

#

In Rapier it's TrackedContact, I guess because it can store feature IDs? I don't love that name though

#

I'm also tempted to rename Contacts to ContactPair like in Rapier, since it specifically represents contacts between two entities, not all contacts in the world

little maple
#

I know this is a really "it depends" question, but like.. within an order of magnitude, how many dynamic colliders hitting each other should I be able to sustain before stuff gets choppy? like, are people typically doing single digits, 10s, 100s? 1000s?

fiery mortar
#

Does the crate calculate velocity for objects transforms that are set else where? Like if i were to move a cube with a function does linearvelocity get updated even if i directly set the transforms?

willow ice
#

nah I don't think so

cedar ermine
#

I have a problem with fast moving objects (avian3d), where there seams to be a border around the colliders proportional to speed that objects bounce off. Anyone know what's going on with this?

cedar ermine
cedar ermine
#

Never mind - I've found the culprit. It's speculative CCD (enabled by default).

jolly rover
#

is there a way to have a collider ignore another collider? I'm having a issue similar to https://github.com/Jondolf/avian/issues/615 where im guessing from the profiling is the contact reporting is having a field day reporting all the static entities that are touching. If there is a way I wanted to test first before commenting.

GitHub

Hi there, I added a static collider to every tile in this example from bevy_ecs_tilemap. My FPS slowed down to a crawl. Is this a known limitation to Avian when dealing with high numbers of static ...

thin hare
#

Having trouble finding a clear answer in the docs, but can a parent entity have different CollisionLayers from their child entities?

jolly rover
#

so that doesn't exactly answer your question as it follows this paragraph:

Colliders can be arbitrarily nested and transformed relative to the parent. The rigid body that a collider is attached to can be accessed using the ColliderParent component.
which doesn't clarify if collision layers will matter for nested. but id assume the collision layer would apply for that specific collider. and id also assume the parent ignores child colliders?

probably worth just testing clean room

thin hare
#

Yeah I'm gonna give it a go haha, this is exactly what tripped me up a bit, Initially I was just going to attach a Sensor to the parent but that turned out to be inherited

jolly rover
thin hare
#

Yeah it's looking like that is the case in my testing so far, perfect!

jolly rover
#

as long as they arent part of the same ColliderParent they will interact fine i think parent1 == parent2

            // No collisions between bodies that haven't moved or colliders with incompatible layers or colliders with the same parent
            if (*inactive1 && *inactive2) || !layers1.interacts_with(*layers2) || parent1 == parent2
            {
                continue;
            }
#

so a child collider wont interact with anything in the hierarchy of that specific entity unless you can get them to have different ColliderParents somehow

thin hare
#

I can't think of one off the top of my head, but I wonder if there is a usecase where you would want to enable collision between siblings in the same hierarchy

jolly rover
thin hare
#

Yeah, or you could maybe use a joint for something like that

hot osprey
hot osprey
#

Seems like it's coming out of the walls, but I'm not entirely sure how

jolly rover
hot osprey
#

They shouldn't interact with each other at all, even tiled, right?

#

It's an inefficient way of setting up a collision system, to be fair, but I'm only doing it unoptimised to play around with avian's backend for bevy picking

jolly rover
hot osprey
#

It's a top down RTS set up. The floor's just tiled until I replace it with a big plane lump

jolly rover
#

gotcha, then wouldnt the floor have 0 colliders?

#

but yeah your setup would in theory not have walls interacting with each other

hot osprey
#

The only thing the floor would do would be to interact with the picker in this case

#

Yeah, which has me concerned

jolly rover
#

whats your concern or symptom you are trying to diagnose?

hot osprey
#

Walls are switched back on now. It's the floor

jolly rover
hot osprey
# jolly rover but whats your issue? or did you fix it?

Sorry, the problem was:

  • my setup's a really primitive replacement for bevy_ecs_tilemap which just has a bunch of meshes representing floor and wall tiles
  • those floor and wall tiles had colliders
  • the floor tiles were set to run as Sensors to avoid interactions with anything
  • this generated a ton of collisions
#

It shouldn't have interacted with anything. Turning off the collision stuff for the floor got me my fps mostly back, but I'm still not entirely sure why it slowed everything down so much

jolly rover
hot osprey
#

The filter should have prevented it though right?

#

It was set to not interact with itself. unless memberships always interact with each other

jolly rover
#

in theory, maybe there's a bug with sensors not honoring collision layers (i dont know if it shares the same code paths as normal collisions)? try just using RigidBody::Static ?

hot osprey
#

I did. Had the same issue

#

Also, oddly, I had the same issue even if the colliders for the floor were too small to interact with each other

jolly rover
hot osprey
#

Thanks for the help in either case

jolly rover
hot osprey
#

Tbh given what I'm doing, having a mesh for every part of the floor is overkill. But I started with a basic tilemap written in a csv because I wanted to do as much of this as I could in rust alone as a learning experience, and stretched to the physics engine to have some fun 🙂

#

I can probably solve the problem by just planar meshing the floor

jolly rover
hot osprey