#Avian Physics

1 messages Β· Page 41 of 1

visual sparrow
#

but I guess it's probably hard to judge by eye

vestal minnow
#

Subject to change, but yeah it's the maximum linear or angular velocity allowed for the body to start sleeping

#

If it is above that for even a single tick, the sleep timer resets

pseudo mirage
#

I guess I should make a minimum reproduction example because this is some really janky behaviour

vestal minnow
#

If the RigidBody is on a child entity, then that is (currently) subject to wonkiness, bodies should typically be at the root of the hierarchy

#

The behavior of child bodies is not very well defined or tested atm

visual sparrow
pseudo mirage
#

My usecase is a hitbox that moves with the player

#

Not sure if I even need a Rigidbody component on that

vestal minnow
#

The player should have a RigidBody, but the child collider should not

pseudo mirage
#

I see, in that case I need to figure out why the child collider without the Rigidbody is causing massive lagspikes on collision (it has a sensor component on it if that matters)

vestal minnow
#

Adding the PhysicsDiagnosticsPlugin and PhysicsDiagnosticsUiPlugin (requires diagnostic_ui feature) may be useful so that you can see where the time is being spent on Avian's side

pseudo mirage
#

Thanks! Will see what I can find with it

vestal minnow
#

If you haven't already, it's also a good idea to also enable some optimizations for debug mode, at least for external dependencies

# Enable a small amount of optimization in the dev profile.
[profile.dev]
opt-level = 1

# Enable a large amount of optimization in the dev profile for dependencies.
[profile.dev.package."*"]
opt-level = 3
#

or alternatively run in release mode

#

optimizations can improve perf like over 100x in a lot of cases

pseudo mirage
#

Already did that, I am also on a fairly powerful machine so that should also not be the issue

little maple
#

was this in the simulation island branch?

vestal minnow
#

Yup, just for the dev profile

#

It mostly slowed down the narrow phase since it ran island validation whenever contacts were created or destroyed

visual sparrow
#

I think I can emulate what I need by doing a sphere cast around the collider and then sorting the hit distances so I get the smallest

#

but is there a more direct way?

#

Also, there is nothing like aabb_intersections_with_aabb for spheres, right?

#

ideally I would use aabb_intersections_with_sphere

#

But looks like parry doesn't support that as far as I can tell

#

oh I just saw that aabb_intersections_with_aabb doesn't accept a filter, so I'd have to manually go through the collision layers to filter them by hand hmm

vestal minnow
visual sparrow
vestal minnow
#

(unless that input shape is a sphere, then you can just treat it as a point and subtract the radius)

visual sparrow
#

hmm

#

I wonder how important that fact is

vestal minnow
#

If you specifically want the distance from a collider to any other collider, I'd probably just get the entities within some AABB or sphere using aabb_intersections_with_aabb or shape_intersections, and then manually calling contact_query::distance for each of those colliders

visual sparrow
#

The specific application is for calculating an object's exposure

#

with the rationale that the closer something is to the wall, the harder it is to spot

#

again, copying the design from Thief

#

since relevant objects are either humanoid capsules or small grabbable objects, approximating them with a sphere could be alright

visual sparrow
visual sparrow
#

Oh hey I just saw we have shape_hits

#

that also looks relevant

#

nvm that requires a direction hmm

#

are intersection callbacks ordered by distance? It says in the docs for hits that they're ordered, but I can't spot such a remark for intersections

snow urchin
#

How do you integrate layermasks/collisionlayers with spatialqueryfilter?

sweet sundial
#

does the field with a LayerMask in it not work?

vestal minnow
#

wowee 40k messages

#

mm can we change that bevy_xpbd link in James's original message lol, it has always bothered me after the avian rebrand

#

Hey @chilly wadi could you edit your original message here #1124043933886976171 message to something like:

vestal minnow
vestal minnow
#

Thank you!

tough zealot
#

Is it expected that the debug physics are lagging one frame behind or am I holding it wrong somehow? I played around with the schedule for PhysicsDebugPlugin but that didn't help.

vestal solstice
#

is the collider on a child entity?

#

compared to the RigidBody

tough zealot
#

yes the colliders are child entities

#

I guess this is a case where the global transform has not been updated yet?

vestal minnow
#

I think it might be because the global physics position and rotation of child colliders is only updated before physics, not after

#

This should be fine for the actual physics, but makes them visually lag behind in debug rendering

#

Although I suppose for spatial queries it'd also be good to update the global position after physics, so that colliders aren't at an outdated position for things like ray casts πŸ€” hmm

tough zealot
#

outdated GlobalTransforms are a major footgun in my experience

#

earlier today I was debugging an issue where forces were applied incorrectly when the framerate was low and more than one physics update ran per frame. turned out I was calculating them based on GlobalTransforms which are outdated by the time the physics schedule runs a second time

vestal minnow
#

The debug rendering is (currently) not using GlobalTransform, it's using Avian's own Position and Rotation components that are used internally for physics

#

This has the downside that if you're using transform interpolation, you'll also see the debug rendering not always match the visual position, because it's rendering the physics position, not the interpolated rendering position

#

Which may or may not be what you want, I haven't quite decided which one it should render

wet niche
#

This is a bit of a tangent, but @Jondolf could you update the main and bevy-0.17 branches to publish the next expected version, rather than the old version 0.3.0 for the avian crates? As it stands, cargo refuses to honor the [patch.crates.io] section (to use the git version) since other projects I'm using reference the last Avian version 0.3.1 due to semantic versioning being a thing. πŸ™‚

vestal minnow
visual sparrow
wet niche
visual sparrow
vestal minnow
#

Fair, yeah might be better to just render the interpolated version even if it's not technically accurate to the actual physics position

#

I guess one caveat is that then you can't do debug rendering for entities without GlobalTransform

vestal minnow
visual sparrow
#

We could even have the current system behind a toggle

vestal minnow
#

I suppose we could also have some GlobalOrPhysicsTransform helper query data

vestal minnow
visual sparrow
vestal minnow
#

I think I would, yeah

#

mm I'm wondering what bevy_rapier does here, I don't think it uses transforms but also I haven't seen people complain

visual sparrow
#

Is that alright?

vestal minnow
visual sparrow
#

Hmm I suppose I need to PR 0.17 anyways

#

Since that is what I use

vestal minnow
#

Hmm it's possible to retarget to another branch later right? Targetting bevy-0.17 is fine for now but I'd prefer to merge it without a lot of unrelated changes like that

#

I think I'll merge it tomorrow anyway

visual sparrow
#

Or

#

I PR against main

#

And just depend on my own 0.17 fork

#

That way you don’t have to pollute your 0.17 branch

#

But I still get to use it

vestal minnow
#

yeah that works too

#

crawls back to drawing a million fricking ER diagrams for an SQL course

wet niche
#

@vestal minnow sorry to pull you out of your SQL hole, but it seems like there are some leaking dependencies from main (bevy 0.16) into bevy-0.17.rc.2 via bevy_heavy: ```
$ cargo tree -i [email protected]
bevy_reflect v0.17.0-rc.2
β”œβ”€β”€ bevy_heavy v0.2.0 (https://github.com/Jondolf/bevy_heavy.git#7331b214)
β”‚ └── avian3d v0.4.0-dev (https://github.com/Jondolf/avian.git?rev=e05eec460b5e53af18ca46d4f2bc18e49b05c0d7#e05eec46)
β”œβ”€β”€ bevy_math v0.17.0-rc.2
β”‚ └── bevy_heavy v0.2.0 (https://github.com/Jondolf/
└── glam_matrix_extensions v0.1.0 (https://github.com/Jondolf/glam_matrix_extensions#c57bc2eb)
β”œβ”€β”€ avian3d v0.4.0-dev (https://github.com/Jondolf/avian.git?rev=e05eec460b5e53af18ca46d4f2bc18e49b05c0d7#e05eec46) ()
└── bevy_heavy v0.2.0 (https://github.com/Jondolf/bevy_heavy.git#7331b214) (
)

(this is making my build fail with messages like ```490 |     fn unit_principal_angular_inertia(&self) -> Vec3 {
    |                                                 ^^^^ expected `glam::f32::vec3::Vec3`, found `bevy_math::Vec3`
    |
    = note: expected signature `fn(&collision::collider::parry::Collider) -> glam::f32::vec3::Vec3`
               found signature `fn(&collision::collider::parry::Collider) -> bevy_math::Vec3````
#

(This seems to have been a problem even before the version bump)

visual sparrow
#

While I'm on it, Chris and I both would appreciate an event that is triggered when collider constructors are done

#

I'll do a PR for that

#

I think SceneInstanceReady is only triggered when the scene was successfully initialized, right @knotty thicket ?

vestal minnow
#

(and check that a collider exists)

snow urchin
#

How do I use collisionlayers to set something to a certain layer?

vestal minnow
vestal minnow
#

I'll see if I can fix that somehow later

visual sparrow
vestal minnow
#

fair

wet niche
visual sparrow
#

ah heck

#

Since there is no published RC of avian, every dependency of mine points to the git source

#

which means that I cannot patch it

#

which means I have no good way of testing my Avian changes in production

#

;-;

#

is chain_3d supposed to have like 3 FPS in debug mode and crash when enabling the debug plugin hmm

visual sparrow
#

Or was that changed?

#

Or did I always get it wrong lol

#

Also, am I reading it wrong that I'm supposed to enable use-debug-pluginon an example and it should just enable the debug visualization? Because that's not happening for me

wet niche
tough zealot
wet niche
#

The code in the examples only adds the plugin, it seems.

snow urchin
wet niche
wet niche
# snow urchin ```rs CollisionLayers::new(LayerMask(2), CollisionLayers::ALL_FILTERS.filters), ...

In any case, I'd recommend making your own enum and relying on the Into<LayerMask magic to help. e.g.:

#[derive(PhysicsLayer, Clone, Copy, Debug, Default)]
pub enum GameLayer {
    #[default]
    Default,
    Player,
    World,
    Projectiles,
}
``` (or whatever)
and then you can use arrays like so: ```
CollisionLayers::new(GameLayer::Player, [GameLayer::World]),
``` or ```
CollisionLayers::new(GameLayer::World, [GameLayer::World, GameLayer::Projectiles]),
``` -- then you don't need to bring any unrelated constants into your code.
visual sparrow
knotty thicket
knotty thicket
visual sparrow
#

Also, for PR 2, here's the before:

#

And here's after:

#

@tough zealot this solves your issue πŸ™‚

tough zealot
#

πŸ₯³ thanks so much!

snow urchin
visual sparrow
wet niche
dreamy viper
#

Is the migration guide on the 0.17 PR up-to-date? I seem to recall that the SyncPlugin was changed

vestal minnow
# dreamy viper Is the migration guide on the 0.17 PR up-to-date? I seem to recall that the Sync...

It only includes changes that were made in that PR. The sync plugin refactoring was here
https://github.com/Jondolf/avian/pull/785

GitHub

Objective
There&#39;s a lot of cleanup work we can do for physics transform management.
Solution

Remove the PreparePlugin and PrepareSet
Rework the SyncPlugin into a simplified PhysicsTransfor...

vestal minnow
wet niche
wet niche
vestal minnow
#

Nice!

#

@visual sparrow I think I'm going to merge the bevy-0.17 branch in a sec, as soon as CI passes

#

I'll then test your remaining PRs properly and get them merged, hopefully I can change the base branch to main without messing things up too badly

#

Right now CI on the bevy-0.17 branch is failing on this, but only on some platforms thonk

#

Ubuntu passed, MacOS did not

#

It's happening consistently too

wet niche
#

Hmm, I'm not having a smooth time updating to 0.4. This one is a bit confusing, as I'll show. Err, dunno how to make a thread...

#

I'm getting a mysteriously unsatisfiable Query after migrating to Avian 0.4.0-dev. In this query: ```
player_q: Query<(Forces, &mut Transform, &ColliderAabb), With<Player>>,

I always get `QueryDoesNotMatch`, even though it does (see pic). 
`# invalid player entity 103v2: QueryDoesNotMatch(103v2#8589934695, ArchetypeId(74))`

Actually, I reduced the query down to _only_ `Forces` and it still fails. Wut?

mut player_q: Query<Forces, With<Player>>,


BTW there is no `Debug` impl on `Forces` so it's quite difficult to use `expect()` or `unwrap()` on the result since `Result` wants `T: Debug`. I needed to use ```
let res = player_q.get_mut(input.player_entity());
let Ok(mut forces) = res
        else {
            let e = unsafe { res.unwrap_err_unchecked() };
            warn!("invalid player entity {}: {:?}", input.player_entity(), e);
            continue;
        };

``` to even print the error πŸ™‚
vestal minnow
#

Hmm πŸ€” yeah if it's a dynamic body then it should work

#

I think one caveat is that it might not work in an observer right after spawn since some components may not be fully set up yet, not sure

wet niche
# vestal minnow Hmm πŸ€” yeah if it's a dynamic body then it should work

Oh, it's continuously occurring, not just at spawn. But this may be related to another thing I did and had to work around. I used to have a situation where I'd spawn things using RigidBody::Static because otherwise they'd fall through the floor, which was being loaded asynchronously. So I'd change to RigidBody::Dynamic later using Query<&mut RigidBody, ...>.
But that's not legal now, so I was EntityCommands.insert()'ing the changed RigidBody. I suppose that's not kosher?

vestal minnow
#

Reinserting RigidBody should be fine, but I haven't tested it specifically for the force APIs

wet niche
#

Well, I just tried not doing RigidBody changes (leaving at Dynamic the whole time) and still no go.

#

(BTW this is all bevy 0.16.1)

vestal minnow
#

Hmm, maybe try a simpler rigid body setup first to verify that it's working for at least a basic case, and then work from there to try and locate what's causing the problem?

#

We do have some unit tests in the repo for forces so in theory it should work

wet niche
#

OK. My player has two Colliders in a combined collider, as well as child colliders. But I changed all of that to a simple capsule Collider, and same issue. πŸ™

#

(IIRC, I did try this migration a month or two ago and it did work. But things have changed on both sides, Avian and my project, so....)

#

▢️ OK, uh, it seems that the responsible component is Sleeping, which I add at init time. Heh. I can remove that... but I suppose I was relying on the 0.3.1 behavior where applying forces woke it up.

visual sparrow
#

Secret form on non-determinism unlocked?

wet niche
#

Also, as I've seen reported here before, I am also seeing avian3d::dynamics::rigid_body::mass_properties: Dynamic rigid body 95v2#8589934687 has no mass or inertia. This can cause NaN values. Consider adding a 'MassPropertiesBundle' or a 'Collider' with mass. even though I do just that -- i.e. in this case I was adding Mass(8.0) and Collider::from_sphere(0.1) (for example).

MassPropertiesBundle{ mass: Mass(8.0), ..default() } results in the same warning, presumably because the defaults for other fields aren't sane?

I can use MassPropertiesBundle::from_shape() but then I have to reverse-engineer the Mass I want πŸ™‚

vestal minnow
# visual sparrow Secret form on non-determinism unlocked?

Oh 🀦 It works on linux because it doesn't run on linux lol

#[test]
#[cfg_attr(
    target_os = "linux",
    ignore = "The plugin setup requires access to the GPU, which is not available in the linux test environment"
)]
fn collider_constructor_hierarchy_inserts_correct_configs_on_scene() {
#

The problem seems to be just that Name for glTF mesh primitives is now in the form of MeshName.MaterialName instead of just the mesh name, which the test was not expecting

#

needs to instead use GltfMeshName afaik

vestal minnow
wet niche
vestal minnow
#

It's new in 0.4 because of the simulation island stuff that overhauled all the sleeping logic, but yeah they could be made more prevalent in the docs. I'll first try if I can just make the old way of simply adding/removing Sleeping work

visual sparrow
#

ping me when you made it work on macos

visual sparrow
vestal minnow
#

oh heck I believe this also affects APIs like ColliderConstructorHierarchy::with_constructor_for_name

#

i.e. the name you're meant to provide is in the form of MeshName.MaterialName, which feels very unexpected to me

#

I would expect "name an object in Blender -> load glTF -> refer to the mesh with the name used in Blender"

visual sparrow
#

-# good thing I've never used that feature

wet niche
#

IIRC there's a migration note about this explaining the reasoning.

vestal minnow
#

yeah it's this

visual sparrow
#

So we need GltfMeshName?

vestal minnow
#

I guess I'd need to use GltfMeshName here too, but the system shouldn't necessarily be glTF specific I think?

dreamy viper
#

Is there some comprehensive changelog for migrating to the new avian version

vestal minnow
#

Not yet, but there will be later

#

I think mainly these PRs have breaking changes this cycle

#

From a networking POV I think the biggest things are that you may need to also roll back the ConstraintGraph resource, and also simulation islands might cause some problems (at least when I was trying them with Nise's stuff) but you can disable them by disabling the IslandPlugin

visual sparrow
vestal minnow
#

just as a dev dependency

visual sparrow
#

that's crappy design on Bevy's part hmm

#

you shouldn't have to know the scene origin asset to get the scene-authored name

vestal minnow
#

yeah

#

this will also break bevy_rapier's AsyncSceneCollider which has a similar thing

#

mm perhaps for now we just roll with it, it's a change on Bevy's part, and the MeshName.MaterialName version is the canonical Name for glTF meshes now, even if I dislike it

#

one could argue that using something other than Name would be unexpected here

wet niche
#

BTW aside from the small issues I mentioned (and some I didn't) the update to 0.4.0 went smoothly!

little maple
#

dang, I didn't realize the release was so soon

vestal minnow
#

(I just updated the tests and stuff to include the material in the name for now)

visual sparrow
#

I'll try to fix it in a few minutes

visual sparrow
#

also, I left my pre-existing PRs targetting 0.17 because I saw that main is still on 0.16

#

let me know if you want me to retarget them

visual sparrow
#

Welp nevermind, CI says no

#

Closing again

vestal minnow
#

Merged the bevy-0.17 branch πŸ™‚

#

Hmm @visual sparrow do you know any git-fu to neatly retarget your two PRs, I tried with GitHub's button but it exploded the diff

#

I guess worst case just open another PR? There's probably a proper way tho

vestal minnow
#

uhhh wut, the collider_constructors example hangs with the PhysicsDebugPlugin enabled (on main too, not just with your PR)

#

oh there's an infinite loop sometimes, that's why

visual sparrow
dreamy viper
#

Can i add an extra component ApplyPosToTransform which would make an entity apply the PosToTransform sync even if it does not have a RigidBody?

dreamy viper
#

Another thing I would need is control to be able to add PhysicsTransformPlugin in multiple schedules, with different controls for each of them.
Would that be ok with you? Something like HashMap<ScheduleLabel, PhysicsTransformConfig>

#

If config.propagate_before_physics is enabled,then TransformPropagation runs twice per frame?

vestal minnow
dreamy viper
vestal minnow
#

No, it also applies if for example you have sensors that are not attached to a rigid body, but are a part of some hierarchy, and some ancestor is moved

#

In that case you need to propagate down that hierarchy or otherwise the sensor will be at an outdated position from the POV of collision detection

vestal minnow
vestal minnow
dreamy viper
#

I replicate Position and that's what I used to run prediction and interpolation

PostFixedUpdate:

  • TransformToPos
  • StepSimulation
  • UpdatePredictionHistory (using Position)

PostUpdate:

  • VisualInterpolation (on Position)
  • ApplyPredictionSmoothing (on Position)
  • PositionToTransform
  • TransformPropagate

I want to run only TransformToPos in PostFixedUpdate and only PositionToTransform in PostUpdate

vestal minnow
#

I feel like instead of generalizing PhysicsTransformPlugin to work across multiple schedules and with multiple configs, it may be simpler to just make a custom plugin for your networking use case, adding the systems and system sets exactly where needed

dreamy viper
#

I might be able to sync Pos to Transform after StepSimulation in PostFixedUpdate and do the interpolation/correction using Transform

dreamy viper
vestal minnow
#

Yeah, queued that PR for merge now

vestal minnow
visual sparrow
#

tangential: we don't have any builtin way to create a sphere sector collider, right?

vestal minnow
#

we don't, no

#

(for vision cones? :P)

visual sparrow
visual sparrow
vestal minnow
#

yeah

#

(I'm off to bed, I need to get up in uh, four hours)

visual sparrow
#

sleep well πŸ™‚

silk mauve
#

Has there been any progress on an off-the-shelf avian 3d kinematic character controller?

winged frost
#

What's the standard way to offset a collider's position?
Edit: Collider::compound does what I wanted

vestal minnow
#

first I need to get the Avian 0.4 release done

sweet sundial
#

i've got two bodies i apply a relative force to (ie, one goes down, other goes up), and i'm migrating to Forces, which i've just noticed has a private global_center_of_mass() which would be perfect for using as the apply_force_at_point world_point on the other body
is that worth giving a public interface or should i have an entire extra query on position, rotation, and center of mass for this one operation
(don't want one of them to spin as much, so it uses regular apply_force; want to make that consistent between them, so i pretend it's an at_point at the CoM)

visual sparrow
#

@vestal minnow does collider-from-mesh make sense without default-collider?

#

I just ran into an issue without default because the collider cache requires both, but the code that uses the collider cache only checks collider-from-mesh

#

from a glance, it seems to me like collider-from-mesh should imply default-collider

#

Hmm although there are some collider constructors that work without default-collider

#

I'll try gating the collider cache only on collider-from-mesh instead nope

#

I'll fix the feature gate instead

golden python
#

Hello, anyone know the status of a release for avian that would be easier to manage than pointing to git main ?
Also curious if there is a migration guide kinda deal already for things like ExternalForce and others, maybe a little write up or something because idk where to start with the new force api.
Edit: I think applying forces might be rebranded under the forces component now.

visual sparrow
vestal minnow
#

-# (I saw nothing)

#

-# (I'm guessing you got it fixed lol)

vestal minnow
visual sparrow
visual sparrow
visual sparrow
grave quest
#

Hey, I have recently replaced rapier with avian (rapier has some panic bugs) and I have noticed the big decrease in precision of very basic collision detection. Basically the case is like this - a projectile (kinematic circle collder, size 1) hits the rock (dynamic, circle collider, size 30), destroys itself and spawns effect where it did so. Rapier would cause effect to appear roughly about the edge of rock collider as expected. Avian does it it some other places, which appear to be somewhat random, close to truth but not quite as good as rapier. I managed to find configs that help with it slightly - I have disabled entirely speculative margin (SpeculativeMargin::ZERO) on projectile and I am also using observer instead of event reader (i.e Trigger<OnCollisionStart> instead of EventReader<CollisionStarted>). Now those two things made stuff better to some effect, but still far from rapier precision, at least to my eye (I can probably collect precise data.. if needed).
Anyone knows any other tricks to make avian more accurate?

sweet sundial
#

could use a shapecaster instead of a collider
could make the projectile dynamic, so it stops when it hits something
could try turning speculative collision back on and reading the ContactPair off the graph

grave quest
#

could make the projectile dynamic, so it stops when it hits something

huh, this is interesting take. I have been thinking of collisions as kinetic, because I wanted not to apply to any forces to them, so they just remove themselves on same frame as when collision detected. Was I missing something?

could use a shapecaster instead of a collider

I will see what it is.. never heard of this before

could try turning speculative collision back on and reading the ContactPair off the graph

I actually thought that speculative collision also applies to results of what is stored on the graph, but I did not really read the respective PR that deeply

sweet sundial
#

you could also just increase the physics tickrate

#

or put a system in the substepping loop

grave quest
#

Regarding speculative collision, there is this bit:

Speculative CCD: Contact points are predicted by the narrow phase for fast-moving objects before they actually touch. Speculative collision response is handled by pushing back the part of velocity that would cause penetration.

in here ,which made me think that I should not be able receive from contact graph anything different from what was "speculated", because speculation sounds like something that works on narrow phase. But it is possible that I misunderstand something in this..

#

or put a system in the substepping loop
you mean my system that looks at collisions? I use observer, it seemed to work better

#

The weirdest bit is that result somehow depend on the angle at which one circle moves to another

#

somehow from the bottom left it looks the worst πŸ™‚

sweet sundial
#

my approach for projectiles is to just have them as dynamic bodies i delete after they hit something, i don't even have effects yet (damage is applied by the force it exerts)

#

if you want something with minimum unpredictability though, just don't give it a collider at all
can handle its collision manually

grave quest
sweet sundial
#

... that looks like just a kinematic-kinematic collision

#

are you manually keeping the rocks in place

grave quest
#

... that looks like just a kinematic-kinematic collision

pretty sure only one of them kinematic, lemme check

sweet sundial
#

also speculative collision helps prevent that

#

it just can't do anything if the bodies aren't free

grave quest
#

Rock has this:

avian2d::prelude::RigidBody::Dynamic,

projectile this:

avian2d::prelude::RigidBody::Kinematic,
#

are you manually keeping the rocks in place

no, they spawn with 0 velocity and then have no reason to move, no forces are applied, cause projectile is kinematic

#

Oh, projectile is also Sensor

sweet sundial
#

that's not how that works

#

yeah there's the reason

#

the projectile steps forward, records a collision, and does nothing else

#

if you want it to not penetrate either make it solid (and dynamic) or add a way to find out when it collided, ie a shapecast

grave quest
#

For dynamic projectile not so different:

#

find out when it collided, ie a shapecast
ooh, sounds cool , sort of like rollback?

#

Though I still do not have speculative margin on, lemme try dynamic projectile with speculative margin

#

hm, no, this is worse

#

It is not cool to hit rock not on its edge, but liveable, hitting it outside of hitbox is definitely no go

sweet sundial
#

get the data off the graph and make sure it's actually collided

grave quest
#

But, say what I do if the answer is no (they do not yet collide)? Do I ignore that event? Then when I would know when it actually does collide?

sweet sundial
#

oh right observer

grave quest
#

I guess I can still capture OnCollisionEnded, then interpolate, but it sounds like an awful lot of workarounds πŸ™‚

sweet sundial
#

i just read the graph in a schedule system

#

OnCollisionStart says "when two colliders start touching"...
where are you reading the objects' positions from?

grave quest
#

I honestly thought that collision_events: EventReader<avian2d::prelude::CollisionStarted> also only tells me which collisions have started on this frame

sweet sundial
#

a reader gives all events that have happened since either last time it was read or two Updates ago, whichever is more recent

grave quest
#

Hm, still sort of not quite consistent

#

This is the system:

fn projectile_hits_by_avian(
    mut commands: Commands,

    // avian stuff:
    mut collision_events: EventReader<avian2d::prelude::CollisionStarted>,
    contact_graph: Res<avian2d::prelude::ContactGraph>,

    // some other stuff:
    projectile: Query<(&Transform, Entity), With<Projectile>>,
    damageable_targets: Query<Entity, With<DamageableTarget>>,
    bullet_hit_effect: Res<BulletHitEffect>,
    projectile_assets: Option<Res<ProjectileAssets>>,
    mut damage_event_writer: EventWriter<damage::ApplyDamageEvent>,
) {
    for collision_event in collision_events.read() {
        let e1 = collision_event.0;
        let e2 = collision_event.1;
        let actually_colliding = contact_graph.entities_colliding_with(e1).any(|e| e == e2);
        if !actually_colliding {
            continue;
        }
        if let Some(((projectile_transform, projectile_entity), damageable_target_entity)) =
            (&projectile, &damageable_targets).get_both(e1, e2)
        {
            process_hit(
                &mut commands,
                &bullet_hit_effect,
                &projectile_assets,
                &mut damage_event_writer,
                projectile_transform,
                projectile_entity,
                damageable_target_entity,
            );
        }
    }
}
#

Projectile is this (from avian related stuff):

            avian2d::prelude::RigidBody::Dynamic,
            avian2d::prelude::Collider::circle(1.0),
            avian2d::prelude::LinearVelocity(direction * speed), // Set initial velocity
            avian2d::prelude::Sensor,
            avian2d::prelude::CollisionEventsEnabled,
            avian2d::prelude::GravityScale(0.0), // No gravity effect
#

Rock is this

            avian2d::prelude::LinearVelocity(velocity),
            avian2d::prelude::Collider::circle(27.0),
            avian2d::prelude::Friction::new(0.7),
            avian2d::prelude::Restitution::new(0.3),
            avian2d::prelude::GravityScale(0.0),
            avian2d::prelude::RigidBody::Dynamic,
#

(rock velocity is zero, which is not obvious from this here..)

#

Projectile used to be kinematic, I haven't tried kinematic without observer yet

sweet sundial
#

if it's a sensor you can't prevent penetration unless you start before the objects overlap

#

at most you can have less penetration

grave quest
#

I don't really mind a bit of penetration, just not half the object

#

haha, nice, yes dynamic non sensor projectile gives kind of best final pic

#

But it has another issue.. now projectile has knockback

#

So rock actually moves πŸ™‚

#

The weirdest result I got one shot that rickosheted πŸ™‚

sweet sundial
#

give it negative dominance

#

and maybe zero restitution or something

grave quest
sweet sundial
#

yeah, imo the physics should dictate the behavior entirely for this kind of thing

grave quest
#

I need to test how often they ricochet like this, but I might actually just keep this like it is! Thanks for all your help!

#

Ok, the only issue is that after ricochet, projectile (which is long yellow line to imitate bullet) starts rotating (get angular velocity), which looks weird for a "bullet". I suppose I can make it a small circle and add particle system instead for trail, but maybe there is cheaper way of fixing rotation in the velocity direction or smth?

#

Ah, I remember now why I wanted projectiles to be Sensor, there is another weird effect if projectiles are dynamic bodies - they can hit another projectile, which looks kind of weird from gameplay perspective. They also then start rotating wildly not in a way that bullet with trail should

sweet sundial
#

can use collision layers to prevent bullet-bullet collisions

grave quest
#

Yeah, that sounded like it should help, but I must be missing some context, cause I thought I put bullet in same layer with target, which makes all bullets in same layer as other bullets

#

Oh, I see, I make them members of same layer, but then use different filters

sweet sundial
#

CollisionLayers::new(0b11u32, !0b10u32)

grave quest
#

I tried to do something like this:

pub(crate) const PROJECTILE_MASK: u32 = 0b0001;
pub(crate) const DAMAGEABLE_TARGET_MASK: u32 = 0b0010;

#[derive(Component)]
#[require(Health)]
// damageable targets can be hit by projectiles and other targets
#[require(avian2d::prelude::CollisionLayers::new(DAMAGEABLE_TARGET_MASK, PROJECTILE_MASK & DAMAGEABLE_TARGET_MASK))]
pub(crate) struct DamageableTarget {

#[derive(Component)]
// projectiles collide with damageable targets, but not with other projectiles             
#[require(avian2d::prelude::CollisionLayers::new(PROJECTILE_MASK, DAMAGEABLE_TARGET_MASK),)]
pub(crate) struct Projectile;

But I think I missed something somewhere, this causes projectiles not to hit targets

sweet sundial
#

default is already 0b1

grave quest
#

I might have done & instead of |, but doing | also makes projectiles not to hit damageable targets..

sweet sundial
#

don't have to give targets a specific mask, ... but i also made a mistake

sweet sundial
grave quest
#

got it, this is simpler - projectiles do not hit each other and that is all this is saying. Looks nice, thanks!

gaunt girder
#

I think I fonud a bug in the new implementation of JointDamping. Both bodies need to have the same RigidBody component, otherwise the damping does not occur. This is because, in src/dynamics/solver/plugin.rs on line 768, the call to get_many_mut requires that both bodies have the same components. Otherwise, it returns Err::QueryDoesNotMatch. I'm not sure what the right way to get both bodies would be as I'm still fairly new to bevy. I can create a github issue if needed.

sweet sundial
#

doesn't that just mean they both have to match the query? they shouldn't need to be in the same archetype

gaunt girder
#

And yet get_many_mut fails if they arent in the same archetype

#

If you dig into the function, you eventually get to this

    pub fn get_inner(self, entity: Entity) -> Result<D::Item<'w, 's>, QueryEntityError> {
        // SAFETY: system runs without conflicts with other systems.
        // same-system queries have runtime borrow checks when they conflict
        unsafe {
            let location = self
                .world
                .entities()
                .get(entity)
                .ok_or(EntityDoesNotExistError::new(entity, self.world.entities()))?;
            if !self
                .state
                .matched_archetypes
                .contains(location.archetype_id.index())
            {
                return Err(QueryEntityError::QueryDoesNotMatch(
                    entity,
                    location.archetype_id,
                ));
            }
#

Or at least, the archetype of the second body isn't in the matched archetypes of the query. Again, new to bevy so I could be misunderstanding, but the only difference between the left and right cubes is whether or not one has a Static or Dynamic RigidBody. I was able to trace it down to that method returning an Err and that being where the Err was returned

sweet sundial
#

are you on avian main? because different body types aren't different components yet there

gaunt girder
#

I am on main

sweet sundial
#

does it work with kinematic instead of static bodies?

gaunt girder
#

Well, I used dynamic bodies and yes. In my example code, I have 2 cubes on the left where both are RigidBody::Dynamic and they work as expected. The two cubes on the right, one is RigidBody::Static and the other is RigidBody::Dynamic and it does not call inside of the joint_damping function past the get_many_mut.

#
pub fn joint_damping<T: Component + EntityConstraint<2>>(
    mut bodies: Query<(&RigidBody, &mut SolverBody, &SolverBodyInertia)>,
    joints: Query<(&T, &JointDamping)>,
    time: Res<Time>,
) {
    let delta_secs = time.delta_seconds_adjusted();

    for (joint, damping) in &joints {
        if let Ok([(rb1, mut body1, inertia1), (rb2, mut body2, inertia2)]) =
            bodies.get_many_mut(joint.entities())
        {
            ...
        }
    }
}
sweet sundial
#

not an expert on the internals but static rigidbodies probably don't get SolverBodys inserted

gaunt girder
#

Ah, I think you're right. Just tried with one Kinematic and the other Dynamic and it works as expected. That makes sense

#

It just wasn't a thing in the previous version of avian where the damping was part of the joint instead of a separate component

sweet sundial
#

this might still be a bug, if you want to file an issue about it

gaunt girder
#

Will do. At the very least, it's a regression in features

vestal minnow
#

Ah yup that's a bug, it should use a "dummy" SolverBody for static bodies like some of the other solver systems

#

I'll fix that later today

gaunt girder
#

Should I still throw together an issue?

vestal minnow
#

Sure, good to have an issue for it in case I forget

#

Just some short description of the problem is enough

gaunt girder
#

Alright. Will do

#

Filed. Thanks! Really like the library in general btw. Really fun to code with

fiery mortar
#

I seem to have this bug where I collide with the middle part of a mesh, no trimeshflags seems to fix it really, do you have any tips for dealing with it?

#

In the video you can see that i slide down the slope well, but then when it hits that cross section, it collides with it, and the player is able to climb all the way back up on it (on 16.1 btw)

dreamy viper
#

I have a ball collider defined with

    collider: Collider::circle(BALL_SIZE),
    collider_density: ColliderDensity(0.05),
    rigid_body: RigidBody::Dynamic,
    restitution: Restitution::new(0.5),

On collision it used to move away, but not anymore. Do i need to change anything?

dreamy viper
#

Also I got this panic:

thread 'main' panicked at /Users/charles/.cargo/git/checkouts/avian-5a22c167119f3550/465b513/crates/avian2d/../../src/dynamics/solver/islands/mod.rs:650:9:
assertion failed: island.contact_count > 0
vestal minnow
#

If yes, you may want to disable the IslandPlugin (or help me figure out how to make it play nice with networking)

#

If not, it's most likely a bug

lyric sorrel
#

Just ran into the same issue as ChaosCat did yesterday with version of slab in updating to Bevy 0.17 and avian main - I think the version of slab named in avian's dependency lists needs updating from just 0.4 to 0.4.11 (the earliest non-yanked version with the get_disjoint_mut method), which should fix that without requiring downstream users to cargo update first

dreamy viper
# vestal minnow Is this with networking

It's with deterministic replication; so it should work fine as long as everything that needs to be rolled back is.
Is there some sleeping/island specific resource to rollback?

vestal minnow
#

I believe also the ConstraintGraph resource which I mentioned earlier iirc

#

Note that I couldn't get Nise's networking stuff properly working with islands yet, which is why I added the option to disable them, but maybe your networking setup is different and it works there

vestal minnow
#

It should (in theory) fix ghost collisions with internal edges like that, at least for the edges of a given mesh, not necessarily at mesh boundaries where two different meshes meet

vestal minnow
fiery mortar
fiery mortar
#

This is the repo just in case you want to take a look, the scene spawning code is inside examples/lol.rs and the character collision sutff is all in src/character_controller.rs

dreamy viper
#

Could the Prepare step run in RunFixedMainLoop instead of FixedPostUpdate? or it is dangerous because other things in FixedUpdate might update Transform?

#

I tried applying TransformToPosition in FixedPostUpdate::Prepare, and PositionToTransform in PostUpdate
But it seems to break stuff and I don't really understand why.
My guess is that something might be modifying Transform in FixedPostUpdate, which means that TransformToPosition is getting re-applied if multiple FixedPostUpdate are running in a frame

little maple
#

finally finished updating to 0.17 with avian and no bugs so far super_bevy

wary ferry
#

There is a relatively simple way to implement a TPS camera interacting with physics to prevent clipping trough RigidBody ? Something like SpringArm3D in godot ? https://youtu.be/ZCb12AHKMfE?si=W7GNy7lggEN2cC0d

I have tried playing with joints but without any success for now

To try everything Brilliant has to offerβ€”freeβ€”for a full 30 days, visit https://brilliant.org/Octodemy . You’ll also get 20% off an annual premium subscription.
How to make a good third person camera in Godot 4 from scratch that you can use with your character controller.

Here is how to make a camera that has collisions and smooth movemen...

β–Ά Play video
sweet sundial
#

weird name for just a raycast?

visual sparrow
sweet sundial
#

in the video it's instant

visual sparrow
#

It's simple to have it follow a raycast distance, but it will be fairly disorienting in practice unless you smooth the movement

visual sparrow
#

that's bad then

visual sparrow
sweet sundial
#

that's specifically added halfway through

#

the "springarm component" was just a raycast

visual sparrow
sweet sundial
#

pretty sure the state of the art is unsmoothed anyway, unless the entire camera assembly is smoothed

#

for controller-targeted games there's usually systems to move the camera away from obstacles (there was a talk about Journey's impl of that) that relax the load on the distance-slider line-of-sight preservation

visual sparrow
#

last thing that comes to mind for me was Super Mario Odyssey, which is smoothed as fuck, but that might be exactly what you mean by "camera assembly"

sweet sundial
sweet sundial
#

meanwhile my game's camera controller is literally as rigid as i could possibly get it (with an extra velocity drag)

vague ether
#

hey, got a weird issue with sensor colliders that's driving me nuts. hoping someone can point out what i'm missing here.

so i'm working on a portal system and have sensor colliders on each portal to detect when the player enters/exits the boundary. player has a capsule collider (radius 0.4, height 1.6), sensor is a sphere with radius 6.0. i'm using CollisionEventsEnabled and observing CollisionStart/End events.

wall portals work perfectly fine, collision starts when entering, ends when exiting, everything makes sense. but floor/ceiling portals are completely broken. CollisionEnd fires way too early even though the player is clearly still inside the sensor volume.

here's what i'm seeing when falling through a floor portal:

COLLISION START: boundary with player
Player at Y=1.13 (distance from portal: 1.125)
Player at Y=0.89 (distance: 0.891)
Player at Y=0.77 (distance: 0.766)
Player at Y=0.64 (distance: 0.637)
Player at Y=0.51 (distance: 0.504)
Player at Y=0.37 (distance: 0.365)
COLLISION END: boundary with player  <-- wtf?

portal center is at Y=0.0 and the sensor radius is 6.0 units. player at Y=0.37 should definitely still be inside the sphere but collision just ends anyway.

i've tried making the sensor absolutely massive (cuboid 10x10x10, sphere radius 6.0), removed any debouncing, verified the entities aren't being despawned, tried both sphere and cuboid colliders. same issue every time with floor/ceiling portals.

the only difference i can see is the orientation. floor portals have their normal pointing up (0, 1, 0), walls are horizontal. the sensor is a child entity so it inherits the portal's rotation.

is there something weird about how sensor/capsule collisions work with different orientations? or am i just completely missing something obvious here? this has been bugging me for hours lol

using bevy 0.17 and avian from main branch gh

vague ether
#

i added CollidingEntities to the sensor and logged both the distance and whether avian still thinks they're colliding when CollisionEnd fires:

COLLISION END: player with sensor - distance: 0.910, still_in_CollidingEntities: false

so when CollisionEnd fires:

  • player is 0.91 units from sensor center
  • sensor is a sphere with radius 6.0
  • CollidingEntities component says they're NOT colliding

this happens consistently. the player is clearly still inside the sphere (0.91 < 6.0) but avian's own collision tracking thinks they've separated. it's not just the events being wrong ,the internal collision state is wrong too.

the only difference i can see is the orientation. floor portals have their normal pointing up (0, 1, 0), walls are horizontal. the sensor is a child entity so it inherits the portal's rotation. wall portals work perfectly, floor/ceiling portals have this bug every time.

dreamy viper
#

@cinder summit I don't know if you have thoughts on this. When only using Position, it should be fine to sync from TransformToPosition only once in RunFixedMainLoop before the fixed loop, no? What would be the use case to do the TransformToPosition every time in FixedPostUpdate (Prepare)?

Also when I insert a Bundle; if I understand correctly it adds Position::PLACEHOLDER because of required components, which adds Transform::Default because of required components. Then the first TransformToPosition sync will convert from Transform::default() to Position::default()

cinder summit
#

In my game I never do transform->position, but if you were using Transform outside the simulation I guess you'd do Transform -> Position once before the loop yes. And ofc you need the hooks to set up the position properly if you spawn something in the simulation

vestal minnow
dreamy viper
cinder summit
#

Imo if you don't need what the transform sync plugin does, you're better off disabling it and applying changes as needed in your own system

vestal minnow
#

Running preparation systems in the same schedule as physics is run in ensures that the state is up-to-date, running it elsewhere seems a bit sketchy

dreamy viper
#

yes that's what i'm doing, I disabled the plugin, but by default the plugin runs TransformToPosition runs in FixedPostUpdate so I'm trying to understand if I can get away with running it somewhere else.

#

I tried doing TransformToPosition in RunFixedMainLoop::BeforeMainLoop and PositionToTransform in PostUpdate, which seems to work

#

I guess it works under the condition that the user doesn't touch Transform during FixedMain or Update and instead relies on Position.

cinder summit
#

If you know what your simulation will and won't do then you can move them, yes

#

I personally only use a system to sync Position/Rotation -> Transform in RunFixedMainLoop::AfterMainLoop

willow elbow
#

Hello, I updated my project to 0.17 and I get this warning:
Dynamic rigid body 79v1 has no mass or inertia. This can cause NaN values. Consider adding a MassPropertiesBundle or a Collider with mass
which goes away only if I add MassPropertiesBundle, not sure what a Collider with mass refers to.
The problem is I want to set the angular inertia but I can't see how to set it with MassPropertiesBundle within spawn

vestal minnow
#

MassPropertiesBundle has an angular_inertia field for this

#

The warning though is a bug somewhere, which I'm hoping to fix soon, you shouldn't be getting it unless the body has no collider or the mass properties have been manually configured to invalid values

willow elbow
#

thanks for your help. That means that I have to first spawn the entity and then query the MassPropertiesBundle to change its field, I can't do it directly at the time of spawning, right?

vestal minnow
# willow elbow thanks for your help. That means that I have to first spawn the entity and then ...

No you can just set it at spawn

commands.spawn((
    RigidBody::Dynamic,
    MassPropertiesBundle {
        mass: Mass(MY_MASS),
        // Note: In 3D, this has a principal inertia and orientation
        angular_inertia: AngularInertia(MY_INERTIA),
        ..default()
    },
    // ...other components
));

Or better, just use the raw components and not the full bundle

commands.spawn((
    RigidBody::Dynamic,
    Mass(MY_MASS),
    AngularInertia(MY_INERTIA),
    // ...other components
));
#

The MassPropertiesBundle mainly exists because of the from_shape helper, for computing all the mass property components based on a given shape and density. If you're manually specifying the mass and angular inertia, it's cleaner to just use the components directly

willow elbow
#

Unfortunately both solutions do not get rid of the warning. It goes away only by using MassPropertiesBundle::from_shape, I guess it's due to the bug you were referring to

dreamy viper
#

Should AccumulatedLocalAcceleration also be rolled back? Is it used for one-time forces? Does it every get persisted past one PhysicsStep?
I see there is also VelocityIntegrationData

vestal minnow
#

i.e. the state doesn't persist, it's recomputed every tick

dreamy viper
#

Thanks.
Another issue I have is that I had a system that queried Position, Mass, etc. and ExternalForce

#

but now i can't query Position along with Forces because of access conflicts

#

I'd rather not use a ParamSet or anything like that; would it be possible to make the fields inside Forces public?

#

oh i see helper methods are provided ..

#

I guess it's not exactly the same because you cannot mutate 2 fields at once if you have to go through the helper methods, as opposed to accessing the field directly. But maybe it's fine

#

Oh those helper methods are internal only

tall willow
fiery mortar
# tall willow nice this is bevy_fps_controller right. I couldn't really get sloped terrain to...

yes its based on bevy_fps_controller but i rewrote a great deal of it. i made it fixedupdate and it now uses force impulses instead of manual transform translation mutation. also uses avian gravity and damping instead of the old gravity and friction system, as well as other minor changes .

I really appreciate you making bevy_fps_controller, would've been difficult for me to get the base yaw/pitch/accel stuff working. bhop is king!

#

yeah slopes at first were very finnicky but i made it a floating controller and slopes are pretty good now, the current issue im having isnt due to the controller, but due to a ghost collision, as far as i can tell. it happens occasionally on flat ground as well

tall willow
#

Cool

#

What is floating controller?

fiery mortar
# tall willow What is floating controller?

instead of the collider being on the ground, there is a force pushing it up constantly, making it slightly above the ground. for me this gave me free walking up stairs, and i dont slide down slopes.

chilly wadi
#

@vestal minnow I haven't had too much time to look into Avian's implementation but I'm curious how much allocation Avian is doing in its systems.

#

I've been investigating if it's a good idea to introduce support for low level scratch space for efficiently managing ephemeral allocations.

#

And physics and rendering are the two areas where it seems to be a good match.

vestal minnow
#

I think constraints would be the biggest thing where that may be helpful

#

Most other data is more long-lived and persisted, and not as perf-critical

chilly wadi
#

At least that's what I'm thinking right now

#

The intent would be to allow for some cheap scratch space that can be shared between systems

#

Mostly to avoid the churn of moving entities and components around on short timescales.

vestal minnow
#

What Box2D does is it allocates a bunch of things to a global arena allocator on the world, distributes some data there, and then frees them after the solver. For example here it allocates some space for SIMD contact constraints
https://github.com/erincatto/box2d/blob/cfa9ef1b76256f92ec3e26a1a20521e50dddac19/src/solver.c#L1468
that it distributes to graph colors
https://github.com/erincatto/box2d/blob/cfa9ef1b76256f92ec3e26a1a20521e50dddac19/src/solver.c#L1494
and later uses in a thread-local context in the solver
https://github.com/erincatto/box2d/blob/cfa9ef1b76256f92ec3e26a1a20521e50dddac19/src/contact_solver.c#L1807

#

I'm guessing this would probably be a bit different in Rust land

chilly wadi
#

Yeah I'm a bit conflicted since this would require either some intricate lifetime weaving

#

or require fallible handles instead

vestal minnow
#

In my case, I currently just have this for the "graph color"

pub struct GraphColor {
    pub body_set: BitVec,
    pub manifold_handles: Vec<ContactManifoldHandle>,
    // This is the relevant part
    pub contact_constraints: Vec<ContactConstraint>,
}

Each constraint within a given graph color can be solved in parallel. In Box2D's case, it doesn't store a vector, but points to some chunk in the arena allocator, unless I'm misunderstanding what it's doing

#

Also the graph colors in my case are stored in a ConstraintGraph resource currently, it's just a Vec of graph colors

chilly wadi
#

since you're doing this in parallel, this is all just allocated up front, right?

vestal minnow
#

The constraints are, yes

dreamy viper
dreamy viper
chilly wadi
vestal minnow
#

Or you may be able to use a ParamSet, though it's more annoying

dreamy viper
#

Would making RigidBodyForcesInternal public work?

vestal minnow
#

I don't really want to expose literally everything there, that trait exists primarily to allow internally sharing logic between ForcesItem and NonWakingForcesItem

#

I would be fine exposing getters for position, rotation, and velocity (velocity already exists), the rest feel more niche to access mutably in the same system as you're using Forces

#

exposing more fields than necessary risks cluttering up autocomplete and making the API more confusing

dreamy viper
dreamy viper
#

oh wait could i also add ComputeMass? my forces often rely on the mass of the entity

vestal minnow
#

Shouldn't you be able to just query for it? It's only borrowed immutably in ForcesItem, so unless you're querying mutably for it for some reason, it shouldn't conflict afaik

dreamy viper
#

oh you're right, didn't know you could query multiple immutable components in the same query; it makes sense

sweet sundial
#

there's an automatically generated ReadOnlyForcesItem that's kinda a footgun if you try to forces.get(e).unwrap().angular_velocity()

golden python
#

Hello, new forces querydata is sick, thanks for the work.
Would it be possible/make sense to have this kind of function directly integrated ?

fn get_point_velocity(linear_velocity: Vec3, angular_velocity: Vec3, point: Vec3) -> Vec3 {
    linear_velocity + angular_velocity.cross(point)
}

I find myself needing it often.
I'm also curious why there isn't a apply_linear_acceleration_at_point

vestal minnow
# golden python Hello, new forces querydata is sick, thanks for the work. Would it be possible/m...

Added apply_linear_acceleration_at_point now. I originally just wasn't sure if it's useful, but I agree it probably is, and it's good to have for consistency / API completeness
https://github.com/Jondolf/avian/pull/846

GitHub

Objective
We have an _at_point version of applying forces and impulses, but not linear acceleration.
Solution
Add apply_linear_acceleration_at_point.

vestal minnow
#

We could consider combining LinearVelocity and AngularVelocity under a Velocity component too

#

Honestly I'm not entirely sure which API I prefer

#

Spawning with linear velocity

// Before
commands.spawn((
    RigidBody::Dynamic,
    LinearVelocity(Vec3::X),
));
// After
commands.spawn((
    RigidBody::Dynamic,
    Velocity::from_linear(Vec3::X),
));
#

Spawning with linear and angular velocity

// Before
commands.spawn((
    RigidBody::Dynamic,
    LinearVelocity(Vec3::X),
    AngularVelocity(Vec3::Y),
));
// After
commands.spawn((
    RigidBody::Dynamic,
    Velocity {
        linear: Vec3::X,
        angular: Vec3::Y,
    },
));
// Or alternatively
commands.spawn((
    RigidBody::Dynamic,
    Velocity::new(Vec3::X, Vec3::Y),
));
#

Using linear velocity in a system

// Before
fn accelerate_linear(mut query: Query<&mut LinearVelocity>, time: Res<Time>) {
    let delta_secs = time.delta_secs();
    for mut linear_velocity in &mut query {
        linear_velocity.x += 2.0 * delta_secs;
    }
}
// After
fn accelerate_linear(mut query: Query<&mut Velocity>, time: Res<Time>) {
    let delta_secs = time.delta_secs();
    for mut velocity in &mut query {
        velocity.linear.x += 2.0 * delta_secs;
    }
}
#

I think I might actually slightly prefer a single Velocity component

#

And it'd solve the point velocity API problem

golden python
vestal minnow
#

Mm we could add that too

vestal minnow
willow elbow
#

I just found this message about a camera interpolation artifact and I was wondering if you got this after updating to 0.17? I get a similar problem when moving the camera interpolating between two positions which I didn't get in 0.16. Is this a known problem in 0.17?

golden python
visual sparrow
willow elbow
visual sparrow
#

But I may be wrong

#

Maybe ask #math-dev

dreamy viper
#

I think I almost have rollback working for islands. The main problem I have is on the BodyIslandNode::on_remove observer.
On rollback, I start by reverting BodyIslandNode, PhysicsIslands and Sleeping to their state at the start of the rollback tick.
The problem is that I don't have a specific order for the reverts, so I might get something like:

I guess a solution would be to have a way to disable this observer during rollback, but I don't really have a way to do this.
I guess another way could be to call return instead of panic at that line, but that's not ideal either because in non-rollback cases you probably do want to panic.

For now I will simply disable the Island plugins

GitHub

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

sweet sundial
vestal minnow
sweet sundial
#

one's just a few vector calculations and the other's that plus collision reading, so not very

#

it's honestly more about how i want to make them independent mechanically, and the ambiguity checker tells me when that might stop being the case

vestal minnow
#

In general I would put DX and overall API "niceness" over optimizing for possible system parallelization for things like this. Bevy has kinda the same thing with Transform, where it could be split into three different components (and originally it was) but is a single component, which arguably is better at least for that case IMO

#

to me the question is mainly if the DX is better with a single Velocity component or split components

#

I've been intending to combine Position and Rotation under a PhysicsTransform for a while now, which is kind of a similar case

#

If both of them were combined then we could also have some more nice helpers for position and velocity integration and whatnot

#

(in addition to point velocity)

sweet sundial
#

could make a just-the-velocities querydata

bleak wadi
#

I've encountered this error in @visual sparrow's 0.17 branch of bevy_tnua, has anything changed here?
Encountered an error in run condition `<bevy_tnua_avian2d::TnuaAvian2dPlugin as bevy_app::plugin::Plugin>::build::{{closure}}`: Parameter `Res<'_, Time<Physics>>` failed validation: Resource does not exist If this is an expected state, wrap the parameter in `Option<T>` and handle `None` when it happens, or wrap the parameter in `If<T>` to skip the system when it happens.

bleak wadi
#

ok i've fixed this, but i've got some more issues

#

it seems like collider has been changed to not have mass by default?

#

Dynamic rigid body 254v32 has no mass or inertia. This can cause NaN values. Consider adding a MassPropertiesBundle or a Collider with mass.

#

and the weapon hitbox which this is talking about is affected by gravity now

#

adding mass doesn't seem to fix it

bleak wadi
#

and it says MassPropertiesBundle isn't a component

maiden charm
#

The performance improvements in 0.4 are very nice, thanks!

#

Mainly for debug builds. It was fast enough in release before, but debug mode performance is nice for productivity

bleak wadi
maiden charm
#

It doesn't help avian too much for some reason, possibly too many generics

light vessel
#

Im also getting the Dynamic rigid body has no mass or inertia bug. For my use case it happens when I use Disabled + entity cloning (prefab design pattern) which may be where the bug lies? I've found missing Clone on a component can really bork up entity cloning in hard-to-detect ways.

bleak wadi
light vessel
#

It looks like this bug is also messing with transform position and rotation for me and I suspect avian's involved since I use LinearVelocity and avian has the interpolation stuff. Not entirely sure could also be a change bevy made to entity cloning or disabled 😒

vestal minnow
#

Yeah I'll try to debug the mass problem today, definitely a bug

vestal minnow
bleak wadi
#

@vestal minnow i'm having this issue with ldtk; the visuals work fine but all the avian hitboxes spawn at 0.0 for some reason? i'm assuming it's a change upstream from bevy, or maybe i messed something up with the migration, but it could be possible there's something in avian breaking it?

vestal minnow
#

Not sure why that'd be happening, but I can probably take a look later

vestal minnow
#

I'm not sure why this wasn't a problem before though, I don't think I've touched this code

#

lol, specifically this returns NaN

let mat = SymmetricMat3 {
    m00: 5.3333335,
    m01: 3.4465857e-23,
    m02: 0.0,
    m11: 5.3333335,
    m12: 0.0,
    m22: 5.3333335,
};

but this does not

let mat = SymmetricMat3 {
    m00: 5.3333335,
    m01: 0.0,
    m02: 0.0,
    m11: 5.3333335,
    m12: 0.0,
    m22: 5.3333335,
};
vestal minnow
#

@light vessel @bleak wadi @visual sparrow (any others?) I fixed at least one bug that was causing the mass property warning, I'm curious if it's fixed for y'all if you cargo update

#

(the problem was that there's a check that tests whether the matrix is diagonal to avoid pathological NaN cases, but it was checking for exact equality to 0.0 rather than having some epsilon)

vestal minnow
#

rip

visual sparrow
#

did you forget to push?

vestal minnow
#

no the bug was in glam_matrix_extras

visual sparrow
#

uuuh

#

oh I see you edited

vestal minnow
#

typoed, extras not extensions

visual sparrow
#

that commit looks correct

#

so nope, does not solve it in Foxtrot at least

vestal minnow
#

mm I'll just run foxtrot and try to debug there

visual sparrow
#

because that's the case when using a RigidBody::Dynamic in combination with a ColliderConstructorHierarchy

#

(for exactly one frame in my case)

vestal minnow
visual sparrow
#

maybe the check didn't fire back then

#

I suppose I could listen for the new event we added, but that seems a bit boilerplatey

#

Could that check just have a Without<ColliderConstructorHierarchy>?

vestal minnow
#

I guess a simple fix would be to just skip the warning if the body has ColliderConstructor or ColliderConstructorHierarchy

#

yeah

vestal minnow
visual sparrow
#

Wish I could patch to test

#

(please consider releasing at least a -alpha next time so I can patch binaries πŸ˜… )

vestal minnow
visual sparrow
vestal minnow
#

Mm I guess yeah, my test scenes are probably just too simple to repro that

#

I'll keep ColliderConstructor filtered out too

#

It's merging once CI is done, so we can test it with foxtrot then

#

(I need to go afk for ~30 min)

tough zealot
vestal minnow
#

for a world-space transformation the original rotation should be on the right

tough zealot
#

πŸ‘ I can open a PR

vestal minnow
#

thanks!

vestal minnow
#

Though there's this when pressing Quit to title

vestal minnow
#

another pretty big release, huh

#

Still missing content for the What's Next section, and I need to add images and videos and run some benchmarks... otherwise I have most of this written now

rocky seal
runic tinsel
vestal minnow
#

Nah these are the WIP release notes I'll post on my website (joonaa.dev) once everything is done and I've actually released 0.4

#

I'm considering changes to how we do releases moving forward but for this one I'll just do things like I've done in the past

#

(specifically, we could do slightly smaller and more frequent releases, and have migration guides in-repo, and maybe make release notes public as a draft somewhere even before the release)

#

(and also a dedicated avian.rs website would be nice, I do have the domain for that)

dry jolt
#

is there a new release of avian for bevy 0.17?

vestal minnow
#

Nope not yet, the upcoming 0.4 release will be for bevy 0.17. But the main branch has supported 0.17 for a while now, so you can hopefully use that

dry jolt
#

ohh ok thanks

dry jolt
#

its working. loving avian so far

little maple
#

is there any way to optimize SpatialQuery's cast_shape/cast_ray? Like, does setting max_distance to a low value help? Is a shapecast "cheaper" than a ray cast?

oak vigil
little maple
oak vigil
#

yah that's one way. you should be able to get the aabb from the collider

#

also you might be more interested in aabb being completely inside

#

doesn't seem like there is a function exposed to check if AABB is inside another, but it should be trivial by checking min/max

little maple
light vessel
# vestal minnow <@246330807541563405> <@1204708988298461234> <@227474830470021130> (any others?)...

Still seeing issues on main with entity cloning including the warning about no mass. Disabling the avian specific components shows that the starting position and rotation are correct:

#[derive(Component, Clone)]
#[require(
    Lifespan::new(1.0),
    //Sensor,
    //RigidBody,
    //Collider::rectangle(10.0, 10.0),
    //CollidingEntities,
    AnimationIndices::Cycle((0..=4).cycle()),
    AnimationTimer(Timer::from_seconds(0.2, TimerMode::Repeating)),
    Disabled
)]
pub struct Projectile {
    pub damage: Damage,
    pub speed: f32,
    pub forward_offset: f32,
    pub angle_offset: f32,
}
...
commands
  .entity(projectile_entity)
  .clone_and_spawn_with_opt_out(|builder| {
    builder.linked_cloning(true);
  })
  .remove::<(ProjectileOf, Disabled)>()
  .insert((
      Transform {
          translation: starting_position.extend(ZLayer::InAir.z()),
          rotation: Quat::from_rotation_z(rotated_direction.to_angle()),
          ..default()
      },
      LinearVelocity(rotated_direction * projectile.speed),
      CollisionLayers::new(
        GameCollisionLayer::PROJECTILE_MEMBERSHIPS,
        LayerMask::from(damage_source) | GameCollisionLayer::HighObstacle,
      ),
));
#

The translation issue is that its always moved to 0, 0 after the first frame. Removing sensor alone fixes this πŸ€” No idea whats up with the rotation.

vestal solstice
#

at what system set the spatial query updated?

#

i'm having an issue where an entity is despawned, but it still shows on the spatial query, and is breaking some of my logic

#

that is my assumption at least

little maple
#

This is done automatically once per physics frame in PhysicsStepSet::SpatialQuery

I have a few places where I'm calling update_pipeline manually though

little maple
#

when two colliders collide... is there an easy way to get roughly the point where they collide? I'm wondering if my raycast vehicles could be more efficient if they use sensors vs casting rays πŸ€”

snow urchin
#

expected update time?

little maple
late wind
#

So, just to be sure if I understood correct, since I'm just starting with avian2d, if I have a tilemap, which is just a grid of Vec2, the best way to create colliders for things like walls, is to use Collider::voxels, where voxel_size is 1x1 (since I'm using 32.0 as the lenth_unit, which is the pixel count of each tile, 32x32) and grid_coordinates are the "tiles" coordinates which will be a wall (collidible).

My only question is if grid_coordinates is a "local position" or needs to be in the "global" position.

sweet sundial
#

don't see how it wouldn't be local to the collider's origin

#

length unit doesn't mean that, though; it just scales things like the sleep threshold

little maple
#

is there something that would prevent a child collider sensor from detecting collisions?

like, I have a rigidbody moving and I have a sensor collider which is a child of it offset so it's always in front of the parent... but it doesn't seem to detect collisions at all πŸ€”

visual sparrow
little maple
#

Two colliders A and B can interact if and only if:

The memberships of A contain a layer that is also in the filters of B
The memberships of B contain a layer that is also in the filters of A

it's funny, I read that and think "yeah, that makes sense" and then I code something that isn't that.

#

yeah, that was it

echo parcel
#

Hi, what is the current state of a voxel colliders?

vestal minnow
#

The upcoming Avian 0.4 release (and the main branch) supports Collider::voxels and some other ways to create proper voxel colliders. I haven't tested them too much yet, they were just added to Parry and I exposed APIs for them

#

They should allow you to make very efficient voxel geometry without ghost collision problems (hitting the "internal edges" between voxels), as long as the sizes of voxels in a given collider are uniform

vestal minnow
#

But I have not tested the voxel colliders much yet

#

(they are from Parry, we just expose APIs for them)

vestal minnow
#

Does it work if you insert Position and Rotation instead of the Transform there? Or alternatively disable cloning for those two components, if there's some way to do that

#

(to be clear, cloning use cases like this should be supported better, but I'm interested to see if it works like that)

#

We should probably have some integration tests for entity cloning to make sure it works like expected

#

Mm supporting cloning feels extremely cursed though since it might also clone various identifier components that should be unique or connect entities to external data, like the BodyIslandNode component

#

I feel like there should be a way to mark components as "don't clone this please" without users having to do that manually

#

If this is a thing, let me know lol

echo parcel
glossy bloom
#

I've been just looking at the new joint API recently and it's soo much nicer than before. Especially the spherical joint axes configuration is much more intuitive than it was before the rework for ragdoll editing, and the docs are clearer. Thank you for your work! super_bevy

little maple
#

πŸ€” do the contact manifolds only get updated when colliders first collide? edit: ah, I was using local translations

little maple
#

so, I'm trying to use the contact manifolds to determine where these rectangular colliders intersect with the ground.. like, the surface point of where the block meets the ground?

I'm drawing a blue sphere on the contact points and a pink one at the "closest" point and I noticed they're like.. sunken in a bit? But then also, when I go over an edge (the red arrow), the contact points are at the edge

is it possible to get the point on the ground surface consistently?

light vessel
# vestal minnow Does it work if you insert `Position` and `Rotation` instead of the `Transform` ...

I had to insert Position and Rotation in addition to Transform like this

Position(starting_position),                   Rotation::radians(rotated_direction.to_angle()),
Transform {
  translation: starting_position.extend(ZLayer::InAir.z()),
  rotation: Quat::from_rotation_z(rotated_direction.to_angle()),
  ..default()
},

This fixed the projectiles but I still get the mass warning. Disabling the cloning of Position and Rotation stopped the projectiles from moving entirely (but also got rid of the mass warning lol)

It looks like there is a way to modify a components default clone behavior: https://docs.rs/bevy/latest/bevy/prelude/trait.Component.html#method.clone_behavior

#
#[component(clone_behavior = Ignore)]
vestal minnow
#

I believe you can get the point on the surface of either body by doing contact.point + manifold.normal * contact.penetration or contact.point - manifold.normal * contact.penetration depending on which surface you want

vestal minnow
vestal minnow
little maple
vestal minnow
#

It's unlikely, computing contact manifolds is generally costlier than just simple ray casts, plus it adds broad phase overhead and whatnot

#

I believe you could maybe also perform the ray casts in parallel since SpatialQuery doesn't require mutable access

little maple
little maple
vestal minnow
#

almost certainly slower, though not by much (and it depends on the shapes)

visual sparrow
vestal minnow
#

Between two spheres yes, between a sphere and some other shape it depends

#

It basically does point projection in the latter case

#

assuming we're purely talking about an intersection test that returns a bool

#

For a shape cast it'll need to do a "Minkowski ray cast" with GJK

#

Except for ball-ball and maybe some other trivial combination

late wind
#

Hello, another question: I've added a voxel collider, but I noticed when I add the PhysicsDebugPlugin there is a heavy hit on fps (debug build), which drops from ~120 FPS to like ~20 FPS.

There is no physics yet, only a Collider::voxel with a RigidBody::Static

Is this some known/expected thing?

sweet sundial
#

seems explicable to me
there's probably a "disable debug gizmos for this entity" component

oak vigil
#

Hey, hate to be that person, but is there an ETA on 0.4 release? πŸ˜„
I realize github is updated to Bevy 0.17, but the dependent libs are still backlogged
If there are any blockers that need an extra hand, I'd be happy to help

maiden charm
#

I think I hit some kind of bug in Avian whereby colliders don't get updated when transform scales change

#

oh, I think it's a slightly different problem: update_collider_scale only takes the Transform into account, whereby it should take the GlobalTransform into account. Also it should run whenever the GlobalTransform changes, not just the Transform.

#

wait, hmm, ColliderTransform is supposed to handle this. this is odd

maiden charm
vestal minnow
#

My estimate would be next Monday at the latest, but hopefully sooner

light vessel
#

What is the easiest way to disable the persistent simulation islands

vestal minnow
#

PhysicsPlugins::default().build().disable::<IslandPlugin>()

light vessel
#

Awesome thanks! Reason I ask is because I can't seem to get around this issue trying to despawn a disabled physics entity:

thread 'main' panicked at .cargo\registry\src\index.crates.io-1949cf8c6b5b557f\bevy_ecs-0.17.2\src\error\handler.rs:125:1:
Encountered an error in command <bevy_ecs::system::commands::entity_command::insert<avian2d::dynamics::solver::islands::BodyIslandNode>::{{closure}} as bevy_ecs::error::command_handling::CommandWithEntity<core::result::Result<(), bevy_ecs::world::error::EntityMutableFetchError>>>::with_entity::{{closure}}: The entity with ID 10227v0 was despawned by .cargo\registry\src\index.crates.io-1949cf8c6b5b557f\bevy_ecs-0.17.2\src\relationship\related_methods.rs:21:19
If you were attempting to apply a command to this entity, and want to handle this error gracefully, consider using EntityCommands::queue_handled or queue_silenced.

vestal minnow
#

Ah that's a good edge case, I hadn't considered that you can even do that haha

#

I'll see if I can fix that later

light vessel
#

Ty good sir. Sorry I'm kinda pushing the boundaries of cloning and use of disabled over here πŸ˜…

late wind
clear dew
#

hallo, am I missing something about CollidingEntities? e.g. is

(
 Collider::...,
 CollidingEntities::default(),
 CollisionEventsEnabled
)

The expected behavior is that CollidingEntities would be 1:1/track state for On<CollisionStart> and On<CollisionEnd>

#

I'm unsure what the actual behavior is

#

Ah, looking at the history of this channel, seems like other people have wondered about this. I see I'll just need to make an external colliding entities to track this

fossil pendant
#

this is with a really low tickrate for fixed update, but the issue is still there with a higher one, even if less noticeable

#

ok after trying to put every transform access into fixed update it went away, but having the camera movement in fixed update feels kind of bad

fossil pendant
#

I have absolutely no clue

clear dew
#

I might have the solution for your question

#

one sec, it's buried

clear dew
fossil pendant
clear dew
#

I believe Jan knows a lot about cameras and how do deal with the jitter effect. for third person, lemme see if I have some code..

clear dew
#

that would double interp here

#

but I think for me, that solves my issue πŸ˜† i also can't quite remember if there's a disabling component for transform interp

#

would prolly wanna add that

fossil pendant
#

ahhh global transform outdated

#

god I swear

vestal minnow
fossil pendant
#

taht's what I had before and it was jittering

#

but that was due to global transform being outdated

#

I assume I am using bevy wrong, but when working with hierarchies I need global transform updated a lot more often than once per frame

#

it's driving me insane

clear dew
fossil pendant
#

yeah but it's still annoying having to calculate it maybe multiple times if you are accessing it in different systems

clear dew
#

maybe the hack would be to run your code after TransformSystem::Propagate. kinda sucks in a postupdate system, but eh

fossil pendant
#

I suppose inserting the updated global transform again is a possibility? Feels like a hack though

clear dew
#

in the PostUpdate schedule

fossil pendant
clear dew
#

I feel that

fossil pendant
#

also I have quite a few instances of code needing global transform and then updating the transform of something else

fossil pendant
#

too offtopic though

#

I complained in #1425767150584594524

#

thanks for the suggestions though <3

visual sparrow
# fossil pendant thanks for the suggestions though <3
  • make the player a rigid body
  • enable interpolation for the player
  • do not make the camera a rigid body
  • do not make the camera a child of the player
  • in Update add a system to move the camera according to the Player's Transform (not GlobalTransform) + some offset
  • bonus: make the camera rotate before physics runs, see Bevy's physics in a fixed timestep example
fossil pendant
#

basically what I have right now, except that I have a camera target as a child of the player

#

really annoying that this doesn't just work

visual sparrow
fossil pendant
#

sigh

#

I have a lot of systems that need an up to date global transform

#

I feel like the current global transform implementation leads to a lot of footgun

burnt canyon
#

Hm, I'm trying to draw some debug shapes. And I got to something like this, but this doesn't work because SharedShape is not an enum.

use avian2d::parry::shape::SharedShape;
// ...

match collider.shape() {
    SharedShape::Circle(circle) => {
        // Simple circle - draw at entity position
        gizmos.circle_2d(position, circle.radius, color);
    }
    SharedShape::Capsule(capsule) => {

Any way I could do something like this?

EDIT: Sometimes asking the question leads one to the answer. It's not SharedShape, it's the TypedShape! That works perfectly.

use avian2d::parry::shape::TypedShape;
// ...

match collider.shape().as_typed_shape() {
    TypedShape::Ball(ball) => {
vestal minnow
burnt canyon
#

Are you kidding me. 🀣 Duh. I did a quick google, but couldn't find it. Thanks. πŸ˜„

late wind
#

Hello, 2 questions if you folks don't mind:

#
  1. for a 2D top-down RPG-like game, I don't need Gravity, so to disable it I just need to set Gravity(Vec2::ZERO) or is there another way?
#
  1. I'm using a KinematicBody to move my character, and I wanna a wall StaticBody to block to. By default, if I understood correct, the KinematicBody isn't blocked by StaticBody colliders, so I need to implement this "blocking" logic myself, like on the kinemaic_controller_collisions example, right?
oak vigil
#

are kinematic bodies even affected by gravity...?

vestal solstice
oak vigil
#

Yah, so would Gravity::ZERO even be needed?

spare bison
#

Played around with some custom gravity.

  • In the first screenshot the dynamic bodies are pulled by both planets.
  • In the second, only the closest planet is affecting gravity.

It's not so easy to get the bodies to sleep when there are constant forces going on.

vestal solstice
#

i just hit something weird, i have a rigid body and a collider as its child, the collider is static, but the parent is moving, and the ColliderTransform of the child is updating

sweet sundial
bleak wadi
vestal solstice
#

@vestal minnow have you see this happen? #1124043933886976171 message

vestal solstice
#

that wasn't it

vestal solstice
#

the default for ExternalForce being persistent: true makes the most sense?

spare bison
#

Otherwise you have to set the force each tick and that I believe makes them not fall asleep?

vestal solstice
#

hmm

visual sparrow
#

How evil is it to assume that a user's static rigid body will never ever change its transform (beyond being despawned and respawned)

#

and how misguided is it to assume that static rigid bodies will in general be spawned and despawned as part of the whole scene, with some rare exceptions (e.g. breaking an object at runtime)

#

I know Avian allows to move static bodies as much as you want, and I know you can spawn and despawn them at will

#

but I think in practice a general purpose library (in my case navmesh and steam audio) can assume the above conditions, right?

#

@vestal solstice how is it in your game?

vestal solstice
#

todays daily had a lot of discursion on that

#

players will be dynamic and npcs will be kinematic

visual sparrow
visual sparrow
vestal solstice
#

yes

visual sparrow
#

and I further assume that the level won't change its transform, right?

vestal solstice
#

correct

visual sparrow
mossy brook
#

Our game never modifies static rigid bodies' transform eithier. We are, however, spawning and despawning them a lot.

vestal solstice
#

spawn/despawn after the first instanciation?

visual sparrow
vestal solstice
#

all static bodies are defined on a glb using skein

visual sparrow
vestal solstice
#

not at the moment

visual sparrow
#

So that static rigid body would be spawned and despawned not as part of the scene, but as something dynamic

mossy brook
vestal solstice
#

my issue was on a Dynamic body

visual sparrow
#

But that would mean rebuilding the entire mesh when a static body changes

#

sounds like in your case, that would be expensive

vestal solstice
#

this is the avian channel, not landmass

visual sparrow
#

I guess I could have markers that say "Static for real for real"

visual sparrow
#

I want to know how people use Avian

#

This is also not for rerecast, but for steam audio πŸ˜„

#

but I can share the code with rerecast once I have it

vestal solstice
#

on the server it is instanciated on startup and on the client it is instanciated when moving to the room that has that scene

vestal solstice
#

anything with a marker component goes through a system that collects the entities in the SceneSpawner for that scene and creates a filter with those that have RigidBody::Static and generate the navmesh from them

mossy brook
visual sparrow
dreamy viper
#

Raycasts and other physics queries only work on RigidBodies, right? Would it make sense to enable them for arbitrary colliders that are not RigidBody?

sweet sundial
#

that first part seems unlikely

maiden charm
#

Avian is now out of the Tracy profile in my project with the 0.4 improvements. Amazing work @visual sparrow

visual sparrow
little maple
#

I know there's some overhead when generating colliders with like Collider::trimesh_from_mesh, but what about creating Collider::cuboid? Is that worth caching at all?

visual sparrow
#

Creating the cuboid is basically free

#

So you don't save on CPU time by caching it

#

However, the colliders use Arcs in the background, so if you have a large amount of cubes of the same dimensions, you could cache them and .clone() that cached collider to only represent it once in memory

#

that way you could potentially save RAM

#

for cuboids specifically though, you may want to instead use voxel colliders anyhow

#

And idk how those work haha

little maple
#

lol I haven't heard of voxel colliders, is that new?

little maple
#

this is a trace of spawning the player in my game and I noticed that on_collider_body_changed gets called 20 times during this process. I'm not sure if that's necessarily what's contributing to the overhead of spawning, but I suspect it's kinda wasted effort, right? Wouldn't I only really need it done once the entity is "ready" (I know that's arbitrary)?

#

I suppose the solution is like.. make adding the collider be the last step of creation?

maiden charm
#

Turns out the UI slowness culprit in my app was Avian. If you include the physics diagnostics UI at all you lose 1.5ms per frame on even a high end system, even if the UI isn't visible. Made a fix: https://github.com/Jondolf/avian/pull/856

GitHub

I noticed that UI layout and text measurement was taking around 1.5ms every frame in my application, even when no UI was visible. I added logging and traced it back to the Avian physics diagnostics...

vestal minnow
#

This read time plugin I have gives the release notes an estimated reading time of 40 min thonk though code examples and whatnot probably skew this higher

#

everything is done now except the cover image, "Other Changes" list, and migration guide

vestal minnow
#

It updates ColliderOf whenever ancestors change, or when a rigid body is added to the hierarchy

vestal minnow
vestal minnow
vestal minnow
#

Yup, the ray_caster example still works

#

That one doesn't have any RigidBody on the colliders

little maple
#

I don't understand the triangle part though

vestal minnow
#

what triangle part?

little maple
# vestal minnow what triangle part?

composite shapes with triangle meshes? I guess like.. is that saying if I have an entity with multiple colliders that aren't touching or something?

vestal minnow
#

I believe that is also the case with compound shapes like the ones produced by convex decomposition, they don't collide with voxel colliders yet

little maple
#

so, it wouldn't be a problem if everything uses voxel colliders? and you'd get a performance boost potentially? am I understanding that?

quartz heart
#

Is there a way to have child entities also ignored with a raycast, if the parent rigidbody is added to the excluded entities?

I often setup the colliders in child entities instead of the root object.

dreamy viper
vestal minnow
#

Voxels are mainly a better version of just throwing a bunch of cuboid colliders on a grid

#

And don't have the problem of ghost collisions between the cuboids, which is a common pain point for people doing tile maps collisions in 2D or voxel terrain in 3D

#

Hmm we should maybe look into whether we could provide some sort of built-in collider integration with Bevy's new tile map stuff at some point πŸ€”

vestal minnow
vestal minnow
#

Astro.js + some Svelte components

#

actual blog post content uses .mdx files

#

there are some custom remark plugins to preprocess the markdown, for example to automatically turn @SomeUser into GitHub user links

bleak wadi
#

@vestal minnow i just wanna remind you that i still have some bugs, the warnings involving re-enabling a collider, and the one with ldtk colliders (that could be ldtk itself or bevy not sure)

vestal minnow
#

Do you have some way I could reproduce the ldtk problem?

#

I haven't seen it in other contexts in my testing

#

I guess I could copy the platformer example in bevy_ecs_ldtk and adapt it to use avian instead of rapier

true hearth
#

If I'd like to simulate train physics in avian, I'm guessing I would probably write a custom constraint to keep the train wheels/bogies on the tracks, right?

#

I guess could also do it by applying appropriate forces, but I'm guessing that can cause problems easily due to the required stiffness there

lyric sorrel
#

@vestal minnow would you be happy to expose a few extra things from SpatialQueryPipeline as pub? I've been implementing some extra spatial queries in a downstream project (one of them is a multi-shapecast, which might be upstream-worthy if it works well, but the other is more niche), and I've ended up having to replicate the SpatialQuery and SpatialQueryPipeline types in my own crate to do it.

#

It'd be nice if I could just impl an extention trait on the upstream types, but it'd need: a way to obtain a reference to the &dyn QueryDispatcher, to get an entity from an index (i.e. a method returning self.proxies[idx].entity) and to access the parry TypedCompositeShape for the pipeline (public versions of as_composite_shape[_with_predicate], which could return impl TypedCompositeShape to avoid having to make the concrete return types public)

#

I've got a set of changes written that I'd be happy to PR if so, just wanted to temperature check first πŸ™‚

vestal minnow
#

But note that a lot of it may change soon-ish with the new BVH stuff using OBVHS (still WIP) and generic spatial queries (#810)

snow parrot
#

Speaking of SpatialQueryPipeline, what might be the cause of an out of bounds panic in rebuild_range_binned here?

index out of bounds: the len is 8 but the index is 8
(...)
   2: core::panicking::panic_bounds_check
             at /rustc/1159e78c4747b02ef996e55082b704c09b970588/library/core/src/panicking.rs:280:5
   3: parry2d::partitioning::bvh::bvh_binned_build::<impl parry2d::partitioning::bvh::bvh_tree::Bvh>::rebuild_range_binned
             at /home/x/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/parry2d-0.24.0/src/partitioning/bvh/bvh_binned_build.rs:58:28
(...)
Encountered a panic in system `avian2d::spatial_query::update_spatial_query_pipeline`!

I'm in the very early stages of implementing a character controller for PC and NPCs, and this happens if I get close to one of the NPCs on the side that has a raycaster. I'm very new at everything, so forgive me if this is a stupid question., or if I left out something useful from the backtrace.

vestal minnow
# snow parrot Speaking of `SpatialQueryPipeline`, what might be the cause of an out of bounds ...

Looks like a bug on the side of Parry (the collision detection lib used by Avian). That part is

// https://github.com/dimforge/parry/blob/master/src/partitioning/bvh/bvh_binned_build.rs

const NUM_BINS: usize = 8;
const BIN_EPSILON: Real = 1.0e-5;

let mut bins = [BvhBin::default(); NUM_BINS];

assert!(leaves.len() > 1);

let centroid_aabb = Aabb::from_points(leaves.iter().map(|node| node.center()));
let bins_axis = centroid_aabb.extents().imax();
let bins_range = [centroid_aabb.mins[bins_axis], centroid_aabb.maxs[bins_axis]];

// Compute bins characteristics.
let k1 = NUM_BINS as Real * (1.0 - BIN_EPSILON) / (bins_range[1] - bins_range[0]);
let k0 = bins_range[0];
for leaf in &*leaves {
    let bin_id = (k1 * (leaf.center()[bins_axis] - k0)) as usize;
    // THIS PANICS
    let bin = &mut bins[bin_id];
    bin.aabb.merge(&leaf.aabb());
    bin.leaf_count += 1;
}

In your case it somehow computes a bin_id of 8, which is just one too large

#

I'm guessing it might be some floating-point error when the leaf's center is close to equal with bins_range[1], which could produce a value like 8.000001 or something, when it should be just slightly below 8

#

the easiest fix would probably be to just do .min(NUM_BINS - 1) for the bin ID

dreamy viper
#

I see cases where my collider seems to have collisions disabled for some reason. It's not deterministic but I can reproduce it semi-consistently. Still trying to understand what could be the cause.
All components seem to be there, so i'm not sure what I should be looking at to debug this

dreamy viper
#

It could be that some additional resource needs to be rolled back, such as AabbIntervals. Maybe I have a resource that's stuck in an incorrect state because it wasn't rolled back? Or is AabbIntervals re-created from scratch every time? It doesn't seem to be the case.
Other candidates: ContactStatusBits ?

Then again this could also be a red herring

lyric sorrel
#

I could also look at writing a new example to demonstrate a custom query, if that would be valuable

#

And I'll keep an eye on the OBVHS work (and keep an eye out for peck too, I guess) for any future changes - thanks for the heads up

vestal minnow
#

looks like yes

vestal minnow
#

(I'm using niri, a scrolling/tiling window manager)

bleak wadi
#

nice, me too

vestal minnow
#

also hit this thonk probably a bevy thing and not lightyear though

vestal solstice
vestal minnow
#

Alrighty, I finally have the release notes and migration guide pretty much done, so I intend to release 0.4 tomorrow unless something goes horribly wrong

#

I have to zoom out to see the whole auto-generated list of PRs in 0.4 lol

visual sparrow
dreamy viper
bleak wadi
little maple
#

it's honestly not too bad depending on main. I got through almost all of 0.16 using main

vestal minnow
bleak wadi
#

yeah that's a good idea

#

it's a pretty niche usecase

vestal minnow
glossy holly
#

If I want to track collision events between two components, let's say "Ball" and "Goal", using the message reader, what would be the easiest way to query for the components? since the Ball could be either collider1 or collider2

#

rn something like this seems the most ergonomic, but might not be the most performant to check every frame

late wind
#

So, is it possible to do pixel perfect collisions with Avian2D?

vestal minnow
#

Pixel perfect in terms of accuracy, or the collider's shape? There's the bevy_collider_gen crate for generating colliders from images with transparency, which might work

vestal minnow
vestal minnow
#

Attach an observer for the ball, and collider1 and body1 in the event data will always correspond to the ball

glossy holly
vestal minnow
#

Yeah, if you have a lot of balls then the message reader approach might still be better

glossy holly
#

I'd like to keep the behavior attached to the ball component, so anywhere the ball component exists it will be handled properly

glossy holly
vestal minnow
#

For iter_many_mut you need to do the while loop thing like in the example docs I linked

glossy holly
#

oh i see

vestal minnow
visual sparrow
#

lol @knotty thicket I also thought the caching was released ages ago

tacit kayak
#

For my usecase I would like two objects to gently push away from each other (possibility more if there is a whole group of them in a corner). Does Avian have any support for this?

I read through the documentation but I figured I would ask here as a last ditch attempt.

#

Actually reading about it bit more I'm guessing I would want to use colliders for collision detection then build my own system on top of that

little maple
# knotty thicket For real though! Lol

ooo does this work well with skein? I was planning on tackling this specific thing in my game with colliders and skein this morning and got side tracked

cloud jasper
green adder
#

I don't know if I'm completely mistaken but is PreviousGlobalTransform gone with avian 4.0? Is there a replacement?

little maple
#

is there a straightforward way to move a collider (and any meta components that get added to it) to its parent? Edit: gonna just write an On<Add observer

vestal solstice
#

have the collider as a child

winged frost
#

Having it as a child messed with my logic, so this is what I did. I do not know if it's correct though
Collider::compound(vec![( Vec3::new(0., 2.5, 0.), Quat::IDENTITY, Collider::capsule(1., 3.), )])

sudden sparrow
#

Hi. I am quite confused. Since i updated to 4.0 none of the joints seem to work anymore. I use RevoluteJoint on the long boards and SphericalJoint on the chain. It seems no forces are applied by the joints. Basis and anchor values seem to not affect this at all. Any idea what is wrong?

willow elbow
#

Hello, I thought the warning Dynamic rigid body x has no mass or inertia. This can cause NaN values. Consider adding a MassPropertiesBundle or a Collider with mass was solved in 0.4 but I still get a lot of warnings. Do I need more than the following to make it go away?
RigidBody::Dynamic, ColliderConstructor::ConvexHullFromMesh, Mesh3d(meshes.add(Cuboid::new(x_length, y_length, z_length)))

visual sparrow
#

need to add docs and see if we can actually get away with not depending on bevy_render

#

and I need to verify that this still works the same as my rerecast version

#

but it's ready for a review πŸ™‚

visual sparrow
#

@vestal minnow alright, fully done now

#

Is this roughly the right shape?

vestal minnow
#

I'm not going to bikeshed this too much though since I expect this to be a relatively niche API, and we'll probably have something else later on with upstreamed mesh and collider types

visual sparrow
vestal minnow
#

How are the joints set up in your scene? You could also try some simpler joint configuration e.g. copying some example in the repo, to verify that at least that works

visual sparrow
vestal minnow
visual sparrow
vestal minnow
#

That one should (in theory) be fixed, though someone else was still getting some warnings when using ldtk I believe

visual sparrow
#

And remember to remove any patch.crates-io or git references you had in Cargo.toml

visual sparrow
vestal minnow
#

Oh you should rename the ball_subdivisions method too, you seem to have renamed just the property atm

#

Also update the doc comment and panic messages

#

(to use "sphere")

vestal minnow
#

Thanks! Looks good now, merging (assuming CI plays nice)

willow elbow
stiff cypress
#

Hi. Is there a way to fully clone entity with rigidbody component? Like with commands.(entity).clone_and_spawn or something. It only works if i change it while cloning from static to dynamic like so

commands
        .entity(root)
        .clone_and_spawn_with_opt_out(|builder| {
            builder.deny::<RigidBody>()
        })
        .insert((
            if is_anchored {
                RigidBody::Static
            } else {
                RigidBody::Dynamic
            },
        ))

or this way

commands 
        .entity(root)
        .remove::<RigidBody>()
        .insert(RigidBody::Dynamic);

but if i try to just clone it entities start floating around

#

mostly talking about preserving all velocities, moments etc while cloning

visual sparrow
visual sparrow
#

@vestal minnow do we have something like a weak handle to colliders?

#

I guess I could clone the underlying shape weakly

knotty thicket
visual sparrow
#

They're Arcs

#

So I guess I do a weak clone of them and put it in a hashmap for lookups hmm

knotty thicket
#

rubs glasses

#

I guess not handles anyway but lol at "not handles, they're arcs!"

visual sparrow
#

Wish I had an AssetId for them and AssetEvents

#

Since I don't know how I would ever clear up a HashMap<SharedShape, T>

#

Oh wait

#
map.retain(|shape, _| Arc::strong_count(&shape) > 0);
#

this works!

#

Hold up, a HashMap<SharedShape, T> or HashMap<Collider, T> is useless ;-;

#

No Eq, no Hash

#

Any of you got a better idea than to... store the Debug string as a key? bavy_spin

vestal minnow
#

pressed the button

visual sparrow
knotty thicket
#

so, uh, unwrap it? lol

#

HashMap<Arc<dyn Shape>, T>

visual sparrow
#

no dice

knotty thicket
#

wanders off to find the error from that

visual sparrow
#

Or, in minimal:

knotty thicket
visual sparrow
#

I'm not very experienced in these things

#

Do you have a suggestion how to go about it?

#

I guess the most manual way would be to downcast the shape to every possible typed shape and hash those?

sweet sundial
#

Shape: DowncastSync seems helpful

visual sparrow
#

the typed shapes also don't implement Hash

visual sparrow
#

It just seems like a lot of boilerplate hmm

sweet sundial
#

and a direct downcast lol

#

picked HeightField from the shapes at random and it doesn't impl Hash

visual sparrow
#

hmm and even hashing the individual fields of the methods is tricky because they're f32

#

time for ordered float

knotty thicket
sweet sundial
#

and the end goal is just to deduplicate things like Collider::cuboid(1.0,1.0,1.0)?

visual sparrow
#

it's for steam audio

#

I need to have a map from colliders to meshes

#

where steam audio would appreciate it if two identical colliders reuse the same mesh

sweet sundial
#

try hashing by address then

visual sparrow
#

otherwise I could also fill in this beautiful thing bavy

knotty thicket
#

RoundTriangle

sweet sundial
#

c.shape().0.as_ptr().hash(..)

visual sparrow
visual sparrow
visual sparrow
#

ah heck, this fails

sweet sundial
#

well yeah it's address hashing

visual sparrow
#

A and B are not the same

#

I was hoping it would hash the address of the thing behind the Arc

sweet sundial
#

if it's two clones of the same arc-

visual sparrow
#

As in, two Arcs pointing the same way

sweet sundial
#

this should do that

visual sparrow
sweet sundial
#

try using the same HashBuilder on all three?

#

might be the random whatever

visual sparrow
#

or wait

sweet sundial
#

hashbuilder not hasher

visual sparrow
#

That was it

#

thank you so much πŸ˜„

#

So do I need to store the hash builder in my collection?

#

In order to not rebuild it

sweet sundial
#

that's what a hashmap does

#

tbh i'd just do a hashmap with a newtype as the key

visual sparrow
visual sparrow
# sweet sundial tbh i'd just do a hashmap with a newtype as the key
struct ColliderKey(Collider);
impl Eq for ColliderKey {}
impl PartialEq for ColliderKey {
    fn eq(&self, other: &Self) -> bool {
        Arc::ptr_eq(&self.0.shape().0, &other.0.shape().0)
    }
}
impl Hash for ColliderKey {
    fn hash<H: Hasher>(&self, state: &mut H) {
        Arc::as_ptr(&self.0.shape().0).hash(state);
    }
}

like that?

sweet sundial
#

actually i'd probably put it onba Weak, for that thing you were doing earlier