#Avian Physics

1 messages · Page 45 of 1

heady oasis
#

Do i have to add plugins separately?

#

like .add defaultplugins

#

and then .add physicsplugins

vestal minnow
#

Do the entities have CollisionEventsEnabled?

vestal minnow
#

or two separate add_plugins calls, should have the same effect

heady oasis
#

is there a way to add a plane collider

#

or should i just have a cuboid with 0.0 height

vestal minnow
#

There's Collider::half_space which can be used for something like an infinite ground plane. But it's not an actual thin plane, everything below the plane is solid

#

Otherwise I'd probably use a cuboid

sweet sundial
#

can also use a really big triangle

vestal minnow
#

IIRC really big triangles can have some stability issues in Parry, though I don't remember if that was specifically trimeshes or convex hulls (or both)

heady oasis
#

how do I query a rigidbody?

#

it says rigidbodyqueryitem is not implemented for avian3d::prelude::rigidbody

sweet sundial
#

add an &

#

any &component impls querydata

fiery mortar
#

hey! Is there a way I can allow 2 static colliders overlapping each other without making it glitches out?

#

in 3D

knotty thicket
fiery mortar
#

man I've been reading the docs for 3 hours without a solution

sweet sundial
#

static colliders shouldn't really be interacting with each other

ancient quarry
#

might be able to help more if you could describe "glitches out" further

viral goblet
#

I got these two from playtesters, what could be the cause?
(Sending here because it's in parry2d)

#

The giant number is just -1 in u64

heady oasis
# sweet sundial add an &

the trait bevy::prelude::Component is not implemented for avian3d::prelude::RigidBodyQueryItem<'_, '_>
= note: consider annotating avian3d::prelude::RigidBodyQueryItem<'_, '_> with #[derive(Component)]

#

mut car_rb  : Single<&mut RigidBodyQueryItem , With<Car>>
vestal minnow
#

unless it's in some internal BVH for a trimesh shape or compound shape, but that I don't have any control over since it's internal for Parry

vestal minnow
#

however I generally don't recommend using RigidBodyQuery, it's not reeaally meant for users and will likely be removed in the future

#

QueryData types like this are considered somewhat non-idiomatic for library APIs, and RigidBodyQuery in particular is very inefficient

heady oasis
vestal minnow
#

just query for the components you need, like you normally would

heady oasis
#

So just query for force or position?

heady oasis
viral goblet
old crane
#

Is there any tool to draw a mesh to use as a collider on top of an asset (which I'm using as a sprite) for 2d physics?? It seems like there should be an easier way than manually typing out all of the components to get a right approximation ?

sweet sundial
#

could use the voxels shape, could try a convex decomposition of the outline

viral goblet
#

I noticed that CollisionLayers are now immutable, so I assume I should just try_insert() new ones

viral goblet
snow urchin
#

Can I spawn a ray as a component alongside another?

#

If so, how?

lucid cloud
peak timber
snow urchin
peak timber
#

And each ray can have its own transform

snow urchin
snow urchin
#

Like for a spring arm, it would be easier if you could just grab the distance if it hit

wet niche
#

Are you aware of https://docs.rs/avian3d/latest/avian3d/spatial_query/struct.RayCaster.html ?

Or instead, if your spring arm and any relevant world objects have Colliders (which they should!), you could use event-driven detection, i.e. a callback when the arm hits something, rather than always casting rays each frame (not cheap!). See the CollisionStart and CollisionEnd events (and remember to add CollisionEventsEnabled component to collider entities!) and use ordinary Bevy Observers or MessageReaders to process the events. They'll tell you the entities with the colliders that touched -- but you have to identify both entities somehow (they're collider1 and collider2 with an arbitrary order).

If you prefer polling instead of handling events -- be warned it's a bit harder -- be sure to use the RayCaster system parameter. proves similar information, more efficiently for large numbers of Collider entities., Look up ContactGraph and ContactPairs diving down to find ContactPoint::penetration.

snow urchin
#

Thanks for the info btw

snow urchin
snow urchin
#

Or rather, it seems like you're implying that I should use RayCaster alongside the methods you reccomended.

snow urchin
sweet sundial
#

manifolds[].points[]

snow urchin
# sweet sundial manifolds[].points[]

This doesn't seem to work.

fn spring_arm(
    contact_graph: Res<ContactGraph>,
    spring_arm: Single<Entity, With<PlayerSpringArm>>,
    mut camera: Single<&mut Transform, With<PlayerCamera>>,
    player: Single<Entity, With<Player>>,
) {
    if let Some(contact_pair) = contact_graph.contact_pairs_with(*spring_arm).filter(|contact_pair|contact_pair.body2.unwrap() != *player).nth(0) {
        camera.translation.z = contact_pair.manifolds[0].points[0].penetration;
    }
}
#

I know what i'm doing wrong but I don't know the solution.

sweet sundial
#

singles skip (annoyingly), or maybe your contact filter's not hitting, but idk which

snow urchin
#

I'll go with the former. What should I do?

sweet sundial
#

use Queries directly

sweet sundial
snow urchin
sweet sundial
#

the system made from fn qwe(_:Single<&Asd>){} will not run if there isn't an entity with an Asd component

snow urchin
#

But I have to add an asd component to the thing i'm queuing for queuing to work?

#

I'm confused, that seems counterintuitive

sweet sundial
#

it's vaguely similar to fn qwe(q:Query<&Asd>){let Ok(_)=q.single_inner() else {return}}

snow urchin
#

The behavior is expected

#

No it's not skipping

snow urchin
sweet sundial
#

.filter()

#

you should check both bodies

snow urchin
#

The first body is always the closest right?

#

Along with the first manifold and manifold point?

sweet sundial
#

collisions_with doesn't make body1 the given entity

snow urchin
#

Sorry I meant first contact pair

sweet sundial
#

not that either

#

there's a deepest_contact thing iirc

snow urchin
#

in which is the farthest right?

snow urchin
#

Which isn't helpful for a spring arm

#

Might just take the event approach, if this is more efficient then the devs would probably implement it soon

snow urchin
#

Oh wait I just realized what sorbitol was saying

#

Though How do I apply a RayCaster query into ContactGraph?

wet niche
#

@snow urchin Sorry for the confusion. Raycasting and events/contacts are two different approaches to collision checking. The RayCaster-like approach seems to be what you started with. It's a fully manual way of finding entities with Colliders in the world from an arbitrary point and direction. AFAICT, all you need is Colliders on the entities you want to detect. You'd use the world position of the camera or spring arm to start the ray,camera.rotation * Vec3::NEG_Z for the ray direction (I.e. "stuff in front of the camera"), and iterate the RayHits after casting to see if you found something. (I haven't used this approach and am just going by the docs and examples.)

On the other hand, the event-driven approaches will let Avian do all the work for you -- more useful in scenes with more Collider entities. It's a similar scene setup (adding Colliders to things you want to detect) but also: (1) add Collider to your spring arm or camera, (2) add CollisionEventsEnabled to the camera/arm and things you want to hit (I'm unsure if you need to tag both, but I usually do), and then (3) process any generated events. Use either (a) On<CollisionStart>/On<CollisionEnd> events which are detected using observers in e.g. commands.spawn(...., Collider.... ).observe(event: On<CollisionStart>, ...) or (b) systems in the FixedUpdate schedule that iterate all events using MessageReader<CollisionStart>/etc.

The contact graph approach might be overkill here since it has all the potential and actual collisions for everything in the world (more useful in scenarios with a lot of colliders, for efficiency, but not likely useful here). I only mentioned it since it provided one method of detecting the amount of penetration between two colliders. There may be other ways of computing this in the raycaster or event driven methods.

tl;dr: check the docs.rs/avian3d pages, since they include a lot of more informed explanations and examples than I am doing here 🙂

winter pebble
#

Hello, is there a way to have multiple "physics scenes" (or something like that) to have separate physics simulations that don't interact with each-other?

#

as if the objects from those scenes were infinitely far away or something

#

can't use collision layers, each "scene" requires 20+ of them already

snow urchin
snow urchin
#

It removes the performance cost of observers in theory.

ancient quarry
#

This part of the RayCaster docs is confusing:

Note that when there are more hits than max_hits, some hits will be missed. To guarantee that the closest hit is included, you should set max_hits to one or a value that is enough to contain all hits.

This implies that max_hits = 2 doesn't guarantee the closest is included when there's more than 2, but max_hits = 1 does (even when there's more than 1)

It's not clear why that would be

Does max_hits = 1 have special-cased different behavior from all other values? If so, that should probably be documented, like "If set to 1, the resulting hit will always be the closest one (if there are any hits)"

somber portal
#

Can you define gravity direction on a per entity basis?

sweet sundial
#

only with the constant force components et c

heady oasis
#

how would I rotate with forces api

sweet sundial
#

Quat::to_scaled_axis?
how do you want it to act

ancient quarry
# heady oasis how would I rotate with forces api

you can either directly add rotational inertia (around CoM):
apply_{torque/angular_impulse/angular_acceleration}
apply_local_{torque/angular_impulse/angular_acceleration}
or cause it with a non-centered force:
apply_{force/linear_impulse/linear_acceleration}_at_point
or non-physically modify it:
angular_velocity_mut

snow urchin
#

Is there a terminal velocity component?

sweet sundial
#

there's a max velocity (iirc) and a drag

snow urchin
sweet sundial
#

LockedAxes

#

you could probably find this stuff in the docs

snow urchin
#

Any reason dynamic rigidbodies don't stop against static ones?

sweet sundial
#

they should

snow urchin
outer raven
#

Can spatial queries be made in parallel (on 6.0.0-rc.1)? Take a function like this:

fn apply_tension(
    spatial_query: SpatialQuery,
    spatial_input_query: Query<(&Transform, &Tension)>,
    mut query: Query<(&Transform, Forces), With<Tension>>,
) {
    query.par_iter_mut().for_each(|(transform, mut forces)| {
        let collision_entities = spatial_query.shape_intersections(
        ...
sweet sundial
#

does that not work?

sturdy heart
#

@vestal minnow gm, why does jumping on the cube with a kinematic body (kinematic_character_3d example) makes the cube go through the plane ? how to prevent this

outer raven
sweet sundial
#

no, the spatial query methods just use regular reading
only atomic in there is the Arc<dyn QueryDispatcher> afaict

molten mason
#

I have a question, I want to make stuff grabbable which is already constrained by a joint.
In this concrete case, I have a string from a lamp to pull which is already constrained by a PrismaticJoint.
Then, when interacting with it, I thought I'd spawn a DistantJoint with the anchor at the interaction point with a "3d cursor" and then move it accordingly. The problem is tho that even tho the 3d cursor (kinematic rigidbody)'s dominance is way lower, it completely ignores the prismatic joint. What can I do to say "respect the PrismaticJoint more but when it's respected, still do the DistantJoint" or can I somehow apply a force to the string "to pull in the direction of the cursor" instead of a joint?
Thanks 😄

sweet sundial
#

turn up the compliance?

foggy storm
#

Why doesn't CollisionHooks::modify_contacts get called when I have the collider as a child? Collision detection/resolution still works with the child collider but the hooks don't.

vestal minnow
#

not the rigid body

foggy storm
#
#[derive(Component)]
#[require(ActiveCollisionHooks::MODIFY_CONTACTS)]
pub struct RockCollider;
...
children![Collider::cylinder(0.28, 0.15), RockCollider]
#

Oh wait...

vestal minnow
#

that's two different entities

#

needs a tuple

foggy storm
#

Forgot the tuple :/

vestal minnow
#

yeah it's really footgunny, I debugged a similar problem for hours during the jam haha

foggy storm
#

Thanks for the help @vestal minnow ! I should have my eyes checked lol

foggy storm
vestal minnow
#

mm yeah using required components isn't really Avian's concern to document, but it could still be worth demonstrating with a small code example in the docs since it might be a pretty common pattern for these hooks

vestal minnow
# sturdy heart <@545959292281552928> gm, why does jumping on the cube with a kinematic body (ki...

That's what happens when an unstoppable force meets an immovable object :)

The collision algorithm for the KCC in that example is pretty hacky and not what you should typically use for actual games. It lets the physics solver handle the actual movement and collisions, and because kinematic bodies effectively have infinite mass, it just dominates any dynamic objects and can exert massive forces on them. KCCs shouldn't really use the normal physics solver for movement.

The KCC should really be using the new MoveAndSlide functionality, the example just hasn't been updated to use it yet. With move-and-slide, the KCC won't actually exert any forces during movement since it essentially stops right at the surface and slides along it. To apply forces to dynamic bodies, KCCs typically have some custom logic, see for example what bevy_ahoy does (though this isn't perfect as it only applies a force one way).

If you want a more complete KCC for 3D, then I'd probably recommend just using bevy_ahoy directly, or vendoring and modifying it to match your game-specific needs

#

We will eventually (hopefully soon) have examples of different kinds of KCCs using move-and-slide in Avian's repo too, no one has just made examples for it yet

sweet sundial
rough lintel
#

How come this exists if rapier works fine

coral kite
#

That's like asking why Unity exists when Unreal Engine works just fine.

Avian is built to work natively with Bevy, that's just one difference between the crates. Rapier is a good physics engine as well.

rough lintel
#

Unity and unreal are very different

#

But this is kinda reinventing the wheel

coral kite
#

How so?

rough lintel
#

Cuz it's basically the same thing

#

If u wanted ECS so bad, why not just add it on top of rapier?

outer raven
#

Hey folks, I have a third person camera pointing at a moving entity - upon camera rotation around the vertical axis, I want to apply centrifugal force to a particular set of entities in the world, as if the camera is stable and the geometry is rotating. What is the best approach to this in avian? Is it to detect collisions for these entities and apply an impulse force? Surely it isn't to actually just rotate everything in the world, right?

vestal minnow
# rough lintel How come this exists if rapier works fine
  1. Some different APIs and features
  2. Different architecture and design choices
  3. Different priorities (Rapier seems to focus more on commercial users and industry than general users and indie game devs)
  4. Avian is more Bevy-focused, integrates with it better, and follows Bevy's conventions more
  5. Having more options in the ecosystem gives people more freedom, and drives improvements for everyone involved, e.g. if Rapier implements something cool, we may try to adopt it too, and vice versa
  6. I like making it, it's not like I'm getting paid to do this as my full-time job (though I do have some lovely sponsors <3)
#

You could also expand the question to other physics engines: why does C/C++ have PhysX, Havok, Jolt, Rubikon, and soon Box3D? Why does Unity DOTS have its own physics? Why does Roblox have its own physics? Why does anyone make anything if there's already an "okay" alternative?

#

Every engine has different design choices and tradeoffs, and has different ways to solve problems, what works best for a given project depends on what they need or want

rough lintel
#

How come you didn't fork rapier instead tho

heady oasis
#

so I have this force I want to apply, that is locked to +45 or -45 degrees of the main body

#

how would I apply the force so angular velocity also is applied

#

I.E. the main body turns towards the force direction

#

(but not snaps towards the force)

#

Have my current setup here
(relevant code is on line 86)

vestal minnow
# heady oasis how would I apply the force so angular velocity also is applied

Hmm, I think you might want some kind of PD controller setup like this:

let forward = global_transform.forward();
let force_dir = force.normalize_or_zero();

// PD controller parameters, feel free to tune
let stiffness = 10.0; // higher -> turns faster
let damping = 2.0; // higher -> less oscillation/wobble

let torque = forward.cross(force_dir) * stiffness - ang_vel.0 * damping;

forces.apply_torque(torque);

(the names aren't from your code of course, so you'll have to change those)

#

I haven't tested the above, so no promise it works first try :P

heady oasis
#

but i should apply this along with the force, or will the torque also provide forward propulsion?

vestal minnow
#

Yeah, apply both the force and the torque, separately

heady oasis
#

cool

vestal minnow
#

force = linear
torque = angular

#

(also I know Swedish but having a FART constant is still funny to me haha)

molten mason
# molten mason I have a question, I want to make stuff grabbable which is already constrained b...

Regarding this, I now have experimented with some compliances between "doesn't move at all" and "now it just randomly goes everywhere again" and seem to have found a sweet spot, but when I don't fully push it down it does this spring like thing. And I think it does that because of the compliance (?) but I need that because with a compliance of 0 it lets me just drag the thing everywhere on screen I want to. How can I make it respect the PrismaticJoint but still be as strict to the DistantJoint as possible? thanks

heady oasis
outer raven
vestal minnow
heady oasis
#

weird, I'm not getting any rotation

vestal minnow
# vestal minnow Ah, it is yeah

I was thinking that you'd query for AngularVelocity, but since you have Forces too, the query would conflict. So yeah you need to access it through the .angular_velocity() helper

vestal minnow
#

if the angular inertia is large compared to the torque then it might look like it has no effect

heady oasis
#

hmm wait is force supposed to be the resulting force?

vestal minnow
#

force is the force (in Newtons) that you're applying to move in some direction

#

if you want acceleration in m/s², use apply_linear_acceleration instead

#

(and apply_angular_acceleration for turning)

#

or alternatively just don't use the Forces API, and manually modify LinearVelocity and AngularVelocity

heady oasis
#
let z : i32 = input.any_pressed([KeyCode::KeyW , KeyCode::KeyJ , KeyCode::ArrowUp]) as i32 - input.any_pressed([KeyCode::KeyS , KeyCode::KeyK , KeyCode::ArrowDown]) as i32;


for  mut kraft  in &mut force_query {
        let forward = hjulen.local_z();
        let force = *forward * z as f32 * FART;
        let ang_vel = kraft.angular_velocity();

        let styv = 100.0;
        let damp = 0.5;

        let tork = forward.cross(force.normalize_or_zero()) * styv - ang_vel * dämp;
        kraft.apply_angular_acceleration( tork );
        kraft.apply_linear_acceleration( force ) ;
// got these values from println!(tork);
// Vec3(6.2881384e-8, -3.8403947e-8, -8.940707e-8)
// Vec3(-5.4124694e-8, -6.233105e-8, -1.4677661e-7) 
}
#

tried this and apply_force / torque and can't seem to get any rotation

#

seem to be getting a super tiny piece of torque

vestal minnow
#

forward is meant to be the forward direction of the car

#

and force should be in the direction you're trying to move

#

right now I think they point in the same direction, so the angle difference is zero and the torque ends up being near-zero

#

oh something is wonky with the coordinates too

#

so the camera is looking from -x towards +x, and it looks like that is assumed to be the forward direction for the car too, but the wheels have their forward direction along the z axis

#

the wheels and car basically seem to be at a 90 degree angle

vestal minnow
#

set styv way lower to 1.0 or something

#

however I would strongly recommend fixing up the coordinates lol, the car and wheels should have the same forward direction (ideally towards -z)

#

or not the same forward direction, but that when the wheels are in the neutral position, they should line up with the car

molten mason
#

I wonder if I should change from a ConstantForce to a force only when the player doesn’t hold it after reading this here, but I still worry that the stiffness then will just make it slide down

visual sparrow
#

excellent mischief, I approve broovy

heady oasis
#

it only turns towards the right despite wheel direction

heady oasis
#

are there any good crates for car physics in avian?

sweet sundial
outer raven
# sweet sundial depends on how they're differentiated

Do you mean how the objects are different from the rest of the scene? Or (I promise I am not taking the piss, I have a math degree and this is a physics engine channel) do you mean the change in their position over time? I assume the first, so they are some number of spheres that are attracted to each other via some forces applied by a system. My thought process with the “detect collision and apply impulse force” was that since they are spheres applying it to the center of mass when contacting the scene is fairly easy? I think this might be unphysical though?

sweet sundial
#

i meant something like, are they experiencing the centrifugal force according to an arbitrary flag or because they're touching something

#

or third option, everything's doing it but you don't want to deal with a rotating scene

outer raven
sweet sundial
#

free floating objects in a rotating reference frame experience virtual forces

outer raven
#

What I want is effectively to emulate rotating the world and camera at the same rate around a vertical axis, without having to do the work of actually rotating every body - I think that means these forces aren’t applied to free floating bodies?

sweet sundial
#

if there wasn't gravity, you'd expect a still object to look like it's moving in a circle to a spinning camera, yeah? means in the rotating frame, there're virtual forces keeping it going around

heady oasis
#
// very unexpected behavior but IG multiplication with quaternions is directional
let foo : Quat;
let bar : Vec3;

foo * bar // no error
bar * foo // no implementation for `bevy::prelude::Vec3 * bevy::prelude::Quat`

visual sparrow
#

That also means that Quat A * Quat B is different from Quat B * Quat A

golden python
#

Hello, I would like to use the move and slide from the release candidate but i'm getting build errors around glam types. Anyone know why ?

vestal minnow
#

Cargo doesn't like that OBVHS uses a different version of Glam and gets confused without the update

golden python
#

Thanks

cinder summit
#

I didn't need to edig the Cargo.lock????

vestal minnow
#

yup

heady oasis
#

are there any fixes for ghost collisions?

#

using bevy trenchbroom & ig I could just merge all the meshes into one

visual sparrow
heady oasis
#

could make it

visual sparrow
heady oasis
#

oh

#

only found ppl talking about it

#
ColliderConstructor::TrimeshFromMeshWithConfig(TrimeshFlags::FIX_INTERNAL_EDGES)
visual sparrow
visual sparrow
#

(If what you’re experiencing are really ghost collisions; it’s hard to tell from the video)

heady oasis
#

so speculativemargin on the player or the map

visual sparrow
#

Would you mind taking a video with the physics debug view on?

heady oasis
#

how do I enable that?

visual sparrow
#

Add the plugin, I think it’s called PhysicsDebugPlugins

#

Or similar

heady oasis
#

yeah that works

#

there are still edgecases though

#

but that's specifically when hitting a 3 way corner

flat root
#

Hi everyone, hope you are doing great 🙂 I was wondering what would be "cheaper" to do to get some measurement from a Collider. Let's say I have a Collider::circle(25.0). Should I do something like collider.shape().as_circle().radius or take it from collider.aabb(...)? Sorry if this is a super obvious question...

minor moat
#

Hello, I'm making a custom constraint on 0.6.0-rc1, but I can't seem to get the angular correction working. I want to use MotorModel to drive the rotation and angular velocity of a body to some target values, but it has some instability and slow convergence that I can't figure out. I'm also doing a similar thing for positonal corrections, and that seems to work just fine, so I reckon it must be something with my angular correction code.

minor moat
white garnet
#

was there a logical change to PhysicsDebugPlugin ? I just upgraded bevy 16 -> 18 including all plugins and things work fine (e.g. physics themselves) but it no longer renders the debug info.

#

ah nvm found it, had to add bevy_ui_render feature

maiden epoch
# heady oasis

It's better to use shapecast and mass-spring-damper model for car suspension, you will need only the distance to the ground
No contact normals - no ghost collisions at all

visual sparrow
heady oasis
flat root
visual sparrow
#

but since the player is always a simple primitive like a capsule or cylinder, it's dirt cheap 🙂

smoky sand
#

How do I make the player not slide around like this? I tried many different things apart from directly modifying velocity, including setting linear velocity, accel, various forces/accels, etc. Increasing friction just makes it slide around a little slower, and makes acceleration annoying. This is my latest attempt.

pub fn process_player_inputs_fixedupdate(
    mut player: Query<
        (
            &Transform,
            &DesiredMovements,
            &GroundEntityMoveStats,
            &mut ConstantForce,
            &mut AdvMobility,
        ),
        (With<Player>, Without<Camera3d>),
    >,
) {
    let (transform, desired_dirs, stats, mut speedcontrol, mut a_mobility) = player
        .single_mut()
        .expect("Multiplayer is not supported yet");

    let wants_jump = desired_dirs
        .modifiers
        .contains(DesiredMobilityModifiers::JUMP);

    if wants_jump {
        // TODO: Double jumps in the air with a powerup
        a_mobility.jump_ticks += 1;
    } else {
        if a_mobility.is_grounded {
            a_mobility.jump_ticks = 0;
        }
    }

    if desired_dirs
        .modifiers
        .contains(DesiredMobilityModifiers::CROUCH)
    {
        a_mobility.crouch_ticks += 1;
        // TODO: Handle crouching
    } else {
        a_mobility.crouch_ticks = 0;
    }

    const TROUBLESHOOTING_VECTOR_MULTIPLICAND: Vec3A = Vec3A::new(4., 1., 4.);
    let move_vector = stats.get_vector_for_desired_movements(
        desired_dirs.horizontal,
        desired_dirs.modifiers.determine_state(),
        transform.forward().to_vec3a(),
        transform.right().to_vec3a(),
        transform.up().to_vec3a(),
        a_mobility.jump_ticks as f32,
        wants_jump,
    ) * TROUBLESHOOTING_VECTOR_MULTIPLICAND;

    let move_vector = move_vector.to_vec3(); // saves 3 __m128 unpacks
    speedcontrol.x = move_vector.x;
    speedcontrol.y = move_vector.y;
    speedcontrol.z = move_vector.z;
}
#

(Also I have no idea how to stop the random rotation, and I would use a capsule collider if it could stand upright, but those aren't as pressing)

wet niche
# smoky sand How do I make the player not slide around like this? I tried many different thin...

My take on this:

  • ConstantForce might be incorrect here. I think it's causing the sliding since that component is meant for e.g. wind, gravity, etc. where you want Avian to smoothly move and accelerate stuff over time. It's the wrong dimension for player movement, which is applying instantaneous nudges to velocity, which increases to some maximum then decays after inputs cease. I'd recommend using LinearVelocity instead, with a similar increase/decay over time corresponding to activity on inputs for each axis.
  • Jumping can be a single application of a large (mass-based) change to LinearVelocity.y. Use a flag like jump_just_pressed: bool to avoid (or limit) multiple jumps. (See avian3d::prelude::Forces::apply_linear_impulse for an example.)
  • For friction, I use Friction::ZERO.with_dynamic_coefficient(0.0).with_static_coefficient(0.5), on the player. That makes the player stop smoothly when no more movement is desired but apply no friction when it's moving.
  • To make your player capsule stand up, add LockedAxes::new().lock_rotation() . Then you're in control of all the rotation.
smoky sand
#

I just tried only setting Y velocity when the player wants jump, now friction doesn't work at all, it just stops abruptly

wet niche
smoky sand
#

I had problems adding it to linearvelocity as well a bit ago, the player would shoot off into the aether

#

It feels like to solve the problem, I would need to be able to modify a separate velocity layer entirely that only applies/scales with the player's linear velocity, sort of like "desired" vs actual

#

if I just added it in steps, the player would most likely have herky-jerky motion

minor moat
smoky sand
#

Should I have a separate bitflags struct that tracks the previous movement state so I can determine whether the key was just released, so as to manually maintain a layer on top of whatever force I use?

wet niche
smoky sand
#

Or should I simulate actual bipedal walking? Would be difficult to implement with my limited understanding of inverse kinematics

wet niche
minor moat
#

The way I did this was by interpreting the movement vector as a target velocity, then instead of applying that as a force directly, the force you apply is target_velocity - current_velocity, which will accelerate the body to whatever the target velocity is, including if the target is zero velocity.

wet niche
smoky sand
# wet niche Yes, but I recommend using something like `leafwing-input-manager` or `bevy_enha...

This is my current input code, it uses a custom subcrate I made called directionlib and inside the filter_event function it just determines what to do based on which keybind I have bound. This is the player logic.

pub fn keyboard_input_event(
    mut player: Query<&mut DesiredMovements, With<Player>>,
    controls: Res<Controls>,
    mut keyboard_input_events: MessageReader<KeyboardInput>,
    mut exit: MessageWriter<AppExit>,
) {
    let mut desired_movements = player.single_mut().expect("No multiplayer yet sorry :(");
    for ev in keyboard_input_events
        .read()
        .filter_map(|e| controls.filter_event(e.key_code, e.state))
    {
        match ev {
            ControlResult::Exit => {
                exit.write(AppExit::Success);
            }
            ControlResult::MoveOn(m) => {
                desired_movements.horizontal = desired_movements.horizontal.union_direction(m);
            }
            ControlResult::MoveOff(m) => {
                desired_movements.horizontal = desired_movements.horizontal.difference_direction(m);
            }
            ControlResult::CrouchOn => {
                desired_movements.modifiers = desired_movements
                    .modifiers
                    .union(DesiredMobilityModifiers::CROUCH);
            }
            ControlResult::CrouchOff => {
                desired_movements.modifiers = desired_movements
                    .modifiers
                    .difference(DesiredMobilityModifiers::CROUCH);
            }
            ControlResult::JumpOn => {
                desired_movements.modifiers = desired_movements
                    .modifiers
                    .union(DesiredMobilityModifiers::JUMP);
            }
            ControlResult::JumpOff => {
                desired_movements.modifiers = desired_movements
                    .modifiers
                    .difference(DesiredMobilityModifiers::JUMP);
            }
        }
    }
}
#

This is my player now.

impl PlayerBundle {
    pub fn new(pos: Vec3, mesh: Handle<Mesh>, material: Handle<StandardMaterial>) -> Self {
        let transform = Transform::from_translation(pos);
        Self {
            transform,
            locked_axes: LockedAxes::new()
                .lock_rotation_x()
                .lock_rotation_y()
                .lock_rotation_z(),
            mesh: Mesh3d(mesh),
            material: MeshMaterial3d(material),
            rigid_body: RigidBody::Dynamic,
            collider: Collider::round_cuboid(1., 1., 1., 0.25),
            friction: Friction::ZERO
                .with_dynamic_coefficient(0.0)
                .with_static_coefficient(0.5),
            restitution: Restitution::ZERO.with_combine_rule(CoefficientCombine::Min),
            center_of_mass: CenterOfMass::new(0., -1., 0.),
            gravity: GravityScale(1.),
            move_stats: GroundEntityMoveStats {
                jump_impulses: GroundEntityMoveStateArray::new(4.2, 6.5, 6.2, 5.6),
                step_velocity_multipliers: GroundEntityMoveStateArray::new(2.5, 7., 9.3, 12.),
                transition_ticks: GroundEntityMoveStateArray::default(),
                max_jump_ticks: GroundEntityMoveStateArray::new(40., 40., 40., 40.),
            },
            ..Default::default()
        }
    }
}
#

(Had to truncate the output bc Discord yelled at me), that's what the ..Default::default() thing in there is for. I actually initialize everything in code

wet niche
# smoky sand This is my current input code, it uses a custom subcrate I made called `directio...

OK, I think you can add a step in your movement processing where if desired_movements.horizontal is empty, clear out accumulated velocity. I have this kind of logic, along similar lines, for planar movement (the jumping code adds a lot of complexity):

PlayerInput::Move(_, input) => {
                instant_thrust.x = Into::<f32>::into(input.right_left) * input_settings.move_scale.x;
                instant_thrust.y = Into::<f32>::into(input.up_down) * input_settings.move_scale.y;
                instant_thrust.z = Into::<f32>::into(input.forward_back) * input_settings.move_scale.z;

                instant_thrust = instant_thrust.clamp_length_max(1.0);
                
                if instant_thrust == Vec3::ZERO {
                    movement.velocity_ramp = 0.0;
                }

                movement.velocity_ramp = (movement.velocity_ramp
                    + input_settings.velocity_ramp_scale)
                    .clamp(0.0, 1.0);

                let dir_velocity = transform.rotation * instant_thrust * movement.velocity_ramp;
#

(sorry, left out the important part)

wet niche
# smoky sand accumulated velocity?

That's like I mentioned (and like you inferred was necessary) -- a side data structure that tracks how fast the player should be going, based on continuously-pressed movements.

smoky sand
#

To be honest I would try to mess with accel first because that is the derivative of velocity, so it would make the code less manual if it worked out

#

it feels weird because we are sidestepping the physics engine

#

I want to work with the tool, not against it

wet niche
#

You're not, though. Applying changes to linear velocity is the key to the issue for responsive FPS-like behavior. That's the kind of control you need for a player controller. Adjusting force would work if you account for mass and the time delta, but it gets finicky real fast.

sleek thicket
smoky sand
wet niche
#

(I guess I'm using acceleration to a degree, on the side -- don't take my word for any of this. I have spaghetti code which works but likely isn't the best way to do anything 🙂

sleek thicket
#

you basically only have your XY velocity and desired XY velocity, so there's not much you have to work with but you can make a curve to adjust the feel, you can even combine it with acceleration/speed/velocity, which is what i'm assuming @wet niche is doing there

smoky sand
sleek thicket
#

i'm talking about manual, built-in one is just bad for this purpose because you'll just make it feel like you're walking through water

smoky sand
#

hmm that's an idea...

wet niche
#

I recommend looking at BigWingBeat's source reference above if you want to work based on forces (and use the handy Forces parameter instead of handling a long list of components).

sleek thicket
#

oh, i didn't even notice it was applied to constant force, yeah you need to add to LV unless it's kinematic

#

constant force is for things like rockets/bullets

smoky sand
#

Idea: I use LV. Store the unmodified velocity as well as the modified velocity from the last tick. Compute differences to determine how much velocity is there that I didn't cause. Add that to my desired velocities, then directly set LV to the result.

#

This has the benefit of just doing some SSE2 float manips instead of pulling several unrelated strings

wet niche
smoky sand
#

And also I might want to set accel instead if I am doing that

smoky sand
wet niche
#

Also, I think any player controller will need a vel = vel.clamp_length_max(max_speed) somewhere. The player will have a key pressed for a long time but that doesn't mean they go faster and faster -- just faster up to the maximum speed you want.

smoky sand
wet niche
smoky sand
#

Maybe I'll add a scalar for that but just define it in const

#

Plus time delta is variable because even if our process has realtime sched priority, the actual electronic components are inherently analog so it would not be as good as if we just assume a constant time and go from there. Clocks have jitter. Some instructions are hardwired to take variable amounts of time. Don't get me started on the ludicrous timing discrepancies I've had to deal with in embedded dev

smoky sand
wet niche
smoky sand
#

Monotonic clocks are specifically designed to not change if the CPU frequency changes. That's specifically why I would never want to rely on it for something that moves in lockstep with the schedulers, which are all running on the CPU

wet niche
#

Good news, these are not CPU-based clocks.

smoky sand
#

I am told fixedupdate is fixed. It cannot be truly fixed because of the fundamental nature of electronics, so in this case, we have to implicitly trust the engine's promise, since any number of systems are interacting behind the scenes.

#

So that's why I don't want to use delta secs. I have no idea if it counts its own internal schedulers too

sleek thicket
#

and fixed updates are usually used as turns, so multiplying by delta would just break that

smoky sand
#

tried it just now

sleek thicket
#

did you add damping?

smoky sand
#

yes, my linear damping is 0.8\

sleek thicket
#

manual.

smoky sand
#

oh not yet

sleek thicket
#

linear damping = walking in water
manual damping = applying a counterforce to slow down

#

games like titanfall 2 go a step further to retain momentum using essentially the same thing

smoky sand
#

Maybe if the player is grounded and no movement keys are pressed, a pulse of accel in the opposite direction of the previous velocity vector slows it to a stop. If the player is grounded and presses a movement key, I either manually add some accel to the vector I would be adding to the velocity or try to use avian3d for that

sleek thicket
#

that's exactly what i was talking about for 1 hour now 🫠

#

whether you want it only when grounded or in air too is up to you

#

and previous velocity is just linear velocity

sweet sundial
#

say fixed dt is .1
starts with 0 elapsed time and 0 fixed elapsed time
there's an update, +0.05, so now Time<Virtual> has 0.05 elapsed
another update, +0.05, total 0.1, so it runs a fixed timestep, bringing elapsed Time<Fixed> to 0.1
+0.08, v=0.18, f=0.1
+0.10, v=0.28, +fixed, f=0.2
+0.12, v=0.4, +2fixed, f=0.4
etc

#

the way i set up my player movement was to add the control direction to the velocity, then also nudge the velocity so its direction is much closer to the control direction (also decelerating for zero control)

smoky sand
# sleek thicket that's exactly what i was talking about for 1 hour now 🫠

Update: I got much more satisfying movement results with the following logic

    // in process_player_inputs_fixedupdate
    speedcontrol.x = flt_signed_abs_maxof(speedcontrol.x, move_vector.x);
    speedcontrol.y = flt_signed_abs_maxof(speedcontrol.y, move_vector.y);
    speedcontrol.z = flt_signed_abs_maxof(speedcontrol.z, move_vector.z);
}
fn flt_signed_abs_maxof(control: f32, test: f32) -> f32 {
    let isneg = control.is_sign_negative();
    if isneg == test.is_sign_negative() {
        if isneg {
            control.min(test)
        } else {
            control.max(test)
        }
    } else {
        control + test
    }
}
#

I haven't really found any damping values I like yet, but I am still searching

sleek thicket
#

you're really overcomplicating it

smoky sand
#

I might also simplify my input system so it adds the move vectors directly to a swap buffer vector. Shouldn't make a noticeable difference in perf because it is a sse add, but it would simplify my other code a lot.

#

well wait it would recalculate view directions

#

I might just keep what I have, because it is well-separated from the rest of the implementation, and I wouldn't have to care about yet another place that modifies the player rigidbody state

#

making a git commit before I break everything all over again lmao

sleek thicket
#

are you vibe coding this

smoky sand
#

plus this is the kind of logic that requires actual playtesting, which is what I am doing

smoky sand
#

I honestly have no idea what I am going to do when it comes time to turn this into a ragdoll.

sleek thicket
#

you'll probably end up cutting it in half after working on it for the next year

smoky sand
#

well if I can cut it in half today, it will make it a lot nicer to work with, and it would also improve performance in multiplayer if I ever go that route (because packets)

smoky sand
#

no, it is still dynamic

sleek thicket
#

then it should be simple enough, just remove your component and let physics take over

smoky sand
smoky sand
smoky sand
# sleek thicket then it should be simple enough, just remove your component and let physics take...

Update: I finally got around to implementing airjumps, the jump code is longer but now it's a lot better than syncing 2 booleans. I am going to do the key state thing (it is a couple bit manipulations don't worry) and manually damp horizontal velocity. I tried doing this with accel but it was just too weird, so I'm giving up that idea. I still need to test with other rigid bodies as well as with jetpack force applied with ConstantForce

sleek thicket
visual sparrow
#

Except if this is jetpack movement

#

Then disregard what I said

fathom cedar
fathom cedar
#

like this

sleek thicket
smoky sand
heady oasis
#

got that exact same bug when following along

#

its because avian is a bit more "stuff" to walk around

#

assuming your code looks something like this:

for wheels in wheel_query:
  let raycast = spacial_query.cast_ray(at the wheel, pointing downwards) {

  let new_height = SPRING_REST - raycast.distance;
  let damping = SPRING_DAMPING * forces.get_velocity_at_point(where the wheel is);
  let spring_force =  new_height * SPRING_STRENGTH - damping;

  forces.apply_force_at_point(spring_force * 5.0 , where the wheels are);
  // calculate the steering force
  // calculate the gas/break force
}
#

this code would make vibrations resonate with themselves

#

as you are multiplying the force (which includes the current speed)

#

then again this is why my code didnt work as expected

heady oasis
visual sparrow
visual sparrow
#

damn @spare lily that gif looks cool

#

thanks for the PR, I'm super excited to review it later 😄

fathom cedar
#

Yes sorry @sleek thicket I was a bit light on details. @heady oasis I too had a double strength force. But mainly my mass + gravity scale was to high, I compensated with high spring stiffness which caused the tap dancer. The springs are a bit soft at the moment but I think I can tweak this to right place.
@smoky sand I use shape casts with spheres for my distance check. I shrunk the chassis collider to allow the body to flow over terrain easier.

molten mason
heady oasis
#

you could try the ```rust
offset * strength - ( speed * damping )

molten mason
heady oasis
#

yeah

#

then just put in offset as the wanted length - the current length

#

and clamp it to the max and min lengths of the rope

molten mason
#

so you mean I shouldn't use avian for this at all but directly move it? I'm sorry I can't quite follow

heady oasis
#

no do force.add_force ( that value)

molten mason
#

ohh so no constant force

heady oasis
#

constant force?

molten mason
#

My rope has a constant upward force via the ConstantForce component currently

#

as it automatically goes up

heady oasis
#

oh

#

yeah no constant force then

molten mason
#

when I do the offset, I'd use abs(cursor.y - rope.y), right? Do I even need the DistantJoint then?

heady oasis
#

that should give you a wrong wanted position

#

or the wanted "length"

#

you'll rather want the distance from the cursor and the lamp joint

#

so where the rope starts

#

then take that -whatever length the rope currently has

molten mason
#

ohh i see

heady oasis
#

though that will only take care of y direction

#

the rope will then not swing left nor right..

molten mason
#

and that isn't possible?

heady oasis
#

no you could simulate that separately

#

just that this formula doesnt include x or z

#

so it wont move in either x or z from this script (as of now)

#

essencially you should have something like this

let rope_length = joint.y - rope.y;
(cursor.y - joint.y - rope_length) * rope_strength - ( forces.get_velocity_at_point(rope) * rope_damping
#

as joint.y cancels out itself here your earlier code snipped actually works here too

molten mason
#

okay let me try that 😄

heady oasis
#

so this would be the simplified expression ```rust
let force = (cursor.y - rope.y) * rope_strength - ( forces.velocity_at_point(rope) * rope_damping;
forces.apply_force(force); // either this if that works out, forces api takes care of delta time so dont worry about it too much
forces.apply_local_force(force); // this is the code I think would work best, as the above doesnt take where the rope is into account
forces.apply_force_at_point(force , rope) // this might work best but unsure if local cordinates work here aswell, as the force value you calculate above isn't in global space

molten mason
#

I'll just try all of them then 😄

#

what would a good rope_strength be here? 0.1?

heady oasis
#

for a first test something like 10 for the strength and 2 for the damping seems to work fine

#

a higher value would mean the spring is stronger

#

or damping is more powerfull

molten mason
#

ohh okay since the stiffness I hesitate before putting anything over 1.0 in anything in avian 😄

heady oasis
#

you'll need to query the forces api

molten mason
#

nvm it's named without the get

heady oasis
#

yeah

#

sry abt that

#

what results do you get ?

molten mason
#

still hacking it in, give me a moment

#

Update or FixedUpdate?

heady oasis
#

I usually just do update but I dont think it matters with force api

molten mason
#

I forgot to remove the ConstantForce, I'm stupid

heady oasis
#

no worries

molten mason
#

this is with apply_local_force and apply_force

heady oasis
#

maybe try 100 on the spring strength

molten mason
#

heh that's even funnier

heady oasis
#

oh?

molten mason
heady oasis
#

hmm

molten mason
#

huh

#

there's something else what's weird

#

I'm getting avian3d::dynamics::rigid_body::mass_properties: Dynamic rigid body 166v0 has no mass or inertia. This can cause NaN values. Consider adding a MassPropertiesBundle or a Collider with mass.

heady oasis
#

oh

molten mason
#

but I add all 3

#

and they are all there

heady oasis
#

you could also add

Mass(1.0)
molten mason
#

this doesn't make sense

#

I now add a ColliderConstructor::Sphere(0.1)

#

same error message

heady oasis
#

did you add a mass?

molten mason
#

doesn't ColliderConstructor do that itself?
I've removed all 3 manual ones for the Collider

heady oasis
#

it should

#

wait no

molten mason
#

even with a Mass it's the same error

heady oasis
#

just do Collider::sphere( 0.1 ),

molten mason
#

with or without explicit mass?

heady oasis
#

try either

molten mason
#

same result

#

I use skein btw

#

but it doesn't matter if I first add the rigidbody or first all the other components

heady oasis
#

are you adding this in blender or in code?

molten mason
#

the mass and rigid body are added in blender

heady oasis
#

add them inside code maybe?

#

so

commands.spawn((
  Rigidbody::dynamic,
  Collider::Sphere(0.1), // or just Mass(1.0) if you don't need a collider for this entity
  //other components
));
#

also here is the code I used in my car game```rust
let speed : Vec3 = forces.velocity_at_point(current_pos);
let offset : f32 = wanted - current;
let new_pos: Vec3 = current_pos + Vec3::new( 0.0 , offset , 0.0);
let local_up : Vec3 = *Dir3::Y;
let power : f32 = strength * offset;
let relative_speed : f32 = local_up.dot(speed);
let dampening : f32 = DÄMP * relative_speed;
let resulting_force : Vec3 = ( power - dampening ) * local_up;
forces.apply_force_at_point( resulting_force , new_pos );

#

to get a stable spring force (upwards)

molten mason
#

._.

#

I feel silly

#

ooookay

heady oasis
#

you got it working?

molten mason
heady oasis
#

how are you setting the y for the rope?

molten mason
heady oasis
#

oh

molten mason
#
let force = (cursor.y - rope.y) * 100.0 - (rope_force.velocity_at_point(rope) * 2.0);
rope_force.apply_local_force(force);
heady oasis
#

no like somewhere the height is clamped

molten mason
#
fn ready(
    _: On<SceneInstanceReady>,
    mut commands: Commands,
    a: Single<Entity, With<desk_lamp::Rope>>,
    b: Single<Entity, With<desk_lamp::TheBase>>,
) {
    println!("Spawning PrismaticJoint!");
    commands.spawn(
        PrismaticJoint::new(*a, *b)
            .with_slider_axis(Vec3::Y)
            .with_limits(0.0, 0.1),
    );
}
heady oasis
#

oh

heady oasis
#

try saying

let force : f32 = ...
#

you might want to get the speed in the y direction

#

so velocity_at_point(rope).y

molten mason
#

wait yeah, how would it even go up by default

heady oasis
#

because the speed points downwards

molten mason
#

like when I don't press then there's no cursor so no force will be applied

heady oasis
#

you are getting a f32 - vec3

#

which is a vec3

molten mason
#

yeah

#

wait I'll change that

#

even then, as long as I don't click, the system won't run as theres no cursor.y

heady oasis
#

oh?

#

then you just set the wanted height to 0

#

so it should still run but wobble to 0 instead

molten mason
#

so 0 - rope.y or just 0 directly?

heady oasis
#

cursor.y here represents the wanted length

#

and rope.y represents the current

#

so eventually, as you set the wanted length to 0 you'll get the height 0

molten mason
#

so 0 - rope.y

heady oasis
#

becomes 0 over time

#

you also need to change

forces.apply_force(force * *Dir3::Y) // as apply force takes a vector
molten mason
#

do I then apply Vec3::new(0.0, force, 0.0)?

heady oasis
#

btw

molten mason
#

ah perfect timing 😄

heady oasis
#

yeah that should work too

#

same thing

molten mason
heady oasis
#

you need to increase the damping and you might want to look over the "offset" part of the code

#
let cursor_length = joint.y - cursor.y; 
let rope_length = joint.y - rope.y;
let offset = cursor_length.clamp( 0.0 , rope_max) - rope_length   // cursor_length - rope_length or wanted - current
molten mason
#

well I do let cursor = if let Some(cursor) = cursor { cursor.translation() } else { Vec3::ZERO }; currently

heady oasis
#

that should work

#

hmm

#

yeah no the offset code is wrong

#

the joint.y doesnt cancel out

molten mason
#

wait that makes no sense

molten mason
#

because when my cursor is at the most top position it's still not 0

#

also I want to not move it directly to the cursor but with the offset of where the joint is

#

yeah

#

whats rope_min and rope_max tho

heady oasis
#

how long the rope max and min can be

#

but you kinda already sorted that out

molten mason
#

and joint is the base of the lamp, not the joint between cursor and rope, right?

heady oasis
#

yup

#

the topmost point of the rope you might say

molten mason
#

okay so it's back up

#

but I think the spring is too strong

heady oasis
molten mason
heady oasis
#

yeah maybe try a strength of 10 or 20

molten mason
#

hm

#

so with a strength of 1.0 it was constantly down

#

with 5.0 it jaggs when not being touched but still goes down completely

heady oasis
molten mason
#

it would go up if I drag it

#

but gravity was stronger

heady oasis
#

how does your code look rn?

molten mason
#

wait I'll try once more with a lower mass

#

okay

#

with 0.05 Mass it looks okay

#

tho it feels too smooth idk

#

also, maybe a silly question, but why did "just adding PrismaticJoint for the locking and DistantJoint for the cursor" not work?

heady oasis
#

sry but kinda know nothing about prismaticjoint tbh

molten mason
#

I don't have much (any) experience with physics engines but from a quick docs read it looks like that would be the normal solution, this feels more like manually setting a position

molten mason
heady oasis
#

but this code is just the formula for springs

#

offset * strength - ( speed * damping )

molten mason
#

hmm

#

what if I always make it retract to the offset but let the DistantJoint handle the dragging?

#

I fear that this will make it go up and down again tho

heady oasis
#

if you want it less smooth just bumping up the spring strength should work

molten mason
#

what still bugs me is that this isn't like a normal spring

#

it's a spring where the retraction point is dynamic via my cursor

heady oasis
#

yup

#

so the "constant" spring length is your cursor

molten mason
#

but I have modified the code again so that cursor is always 0 and now it jaggs again when I drag it down 😭

heady oasis
#

what code do you have?

molten mason
#
    let wanted_length = joint.y;
    let rope_length = joint.y - rope.y;
    let offset = wanted_length - rope_length; // cursor_length - rope_length or wanted - current

    println!("{offset}");
    let force = offset * 1.0 - (rope_force.velocity_at_point(rope).y * 2.0);
    rope_force.apply_local_force(force * Dir3::Y);
#

and then a DistantJoint which connects the rope and the cursor

#

to "drag it down"

heady oasis
#

wanted_length should be joint.y - cursor.y

molten mason
#

yeah it was before

#

but I don't understand why the spring's wanted center should move here

#

like don't I want the spring to still be forced to go up, just that my distantjoint makes that impossible as I grab it?

#

like when I grab a spring in real life it still gives force upwards, it just cant move as I'm stronger (most of the time)

heady oasis
#

sure but that code wont react to the cursor

molten mason
#

yeah that's what the DistantJoint is for, like the "I grab you now, you cant move"

heady oasis
#

oh

#

but that wont change the speed of the spring?

molten mason
#

and the cursor is a kinematic rigidbody so the spring has to move

heady oasis
#

it'll just snap to the new position, right?

molten mason
#

well, no

#

it does this

heady oasis
#

oh

#

then do that

molten mason
heady oasis
#

as long as the cursor applies velocity it will affect the spring script

molten mason
#

the cursor doesn't apply velocity I think

#

I just have a kinematic rigidbody (my cursor) and a joint between it and the rope at the point where I clicked

heady oasis
#

then you kinda have to " delta length over time" and get the speed from there

molten mason
#

huh why

heady oasis
#

to add a velocity

#

with the cursor

molten mason
#

doesnt the joint already do that?

heady oasis
#

if it does then it applies velocity

#

..

#

otherwise you need to add it yourself

molten mason
#

like I thought a joint would mean that infinite force is used to minimaly comply to it

#

but here, as it jaggs, the joint isn't really treated corretly

heady oasis
#

try reading the speed

#

if it changes then the joint thing applies speed

#

otherwise you need to add it manually

#

(in that case you are "teleporting" the spring around - so it jaggs)

molten mason
#

am I misunderstanding joints?

#

how do I even read the speed

#

Velocity component?

#

this looks somewhat better

#

like essentially I want to first respect the prismaticjoint and as long as that is fulfilled I want to respect the distantjoint with the cursor, but it seems like that's not now physics engines work?

heady oasis
molten mason
#

okay so I have thought a bit about it and am replacing the cursor joint with a system that just tries to "drag"/apply velocity at the point clicked towards the cursor.

#

now my question: how do I make it apply a force towards one point?

#

do I even use force or linear acceleartion?

heady oasis
#

otherwise you just apply a force in that direction

#

that has a chance to overshoot but if you smooth it a bit it might not do much

heady oasis
#

just different ways of accessing them

#

angular acceleration is torque

#

linear is force

#

:P

#

the vector from A to B is the same as B - A

#

so

let force_direction = point - position;
molten mason
#

yeah I tried that before but that made it directly go down

#

or maybe I just made something stupid because I did apply_force_at_point

heady oasis
#

hmmm

#
let force_direction : Vec3 = Vec3::normalize(cursor - rope);
let force : f32 = power / rope.distance(cursor);
forces.apply_force( force * force_direction)
molten mason
#

don't I need to normalize the direction?

heady oasis
#

yes

molten mason
#

mehh

#

it would be so cool to have a "apply_force_towards_point" function

#

now either I have a smaller strength and the spring is strong enough to pull it up

#

or I give it a stronger strength and then it goes over the goal and back

muted goblet
#

Hi, when I add a voxel to a compound, the voxel stops colliding. Is this a regression? Collider::compound(vec![( // calculates to Vec3::splat(8.0) Vec3::splat(-((HEKAT_SIZE+1) as f32 / 2.0)), Quat::IDENTITY, Collider::voxels(Vec3::ONE, &collider ))]) however, this works Collider::voxels(Vec3::ONE, &collider ))])

vestal minnow
#

(they have since added shape casting support, but no non-convex collisions for voxels still)

dusty pagoda
#

im getting very poor performance when i set transforms for 15 kinematic rigidbodies every tick. i make a set of hitboxes for my character and i just sync them to skeletal bone positions in FixedUpdate. this causes fps to drop to 12-15, for only 1 character. it is definitely coming from setting the transform. if i comment out the line setting the transform, performance goes back up to 60fps. They have kinematic rb, Sensor, CollisionEventsEnabled and SleepingDisabled.

slender lotus
#

why does the CollisionEnd event not trigger when i remove a collider from an entity that was colliding before?

#

is there another event that i can hook in that notifies me of this?

ancient quarry
dusty pagoda
ancient quarry
#

I agree that it shouldn't have such a big impact
I'd suggest either trying to isolate a minimal reproduction (e.g. can you observe the same without collision events, with simpler? collider shapes, driving transforms by something more specific/simpler than skeletal animation, with fewer other things in the world), or using Bevy's Tracy support to see what systems are taking more frame time—whether it's truly in the physics update or if this indirectly is slowing something else down

#

Avian also has a debug profiling UI (behind a feature?) that you could use to see how long different steps are taking

sweet sundial
#

try making them static bodies, could determine if intercollisions are the problem

sleek thicket
terse shard
#

Hello all, I was wondering if I could get some input on a little avian issue I'm having.
I'm making a little vehicle sim, and doing the standard "ray cast for suspension" thing, however I recently refactored to instead use a ShapeCaster, with some issues.

When I was using the RayCaster approach, the simulation was very steady. The vehicle would happily settle and "sit still" if no input was provided.
After converting to use a ShapeCaster, I'm getting some strange "jitter" when the vehicle is sitting still.
Checking the physics gizmos, I've noticed the hit point for the ShapeCast will sit nicely under the "wheel" for some time, until suddenly the hit starts happening some point further up the shape.

I'm trying this with spheres currently, but the same is present using a cylinder.
It's difficult to describe so I've attached a really rough drawing of what I mean.
It will bounce rapidly between these two states, causing the suspension to act unpredictably and the vehicle will then "jitter" and "walk" around.

Any help would be super appreciated!

dusty pagoda
sleek thicket
sleek thicket
heady oasis
#

oh I got it working in the end, just had faulty code on my part

#

honestly was thinking of making a proper tutorial on the subject but there are just soo many quirks that just dont make sence at first

slender lotus
#

hey, do you know how i can model this?

#

in gameplay thsi should end up in the player draging on the mass-object. smaler objects should just be yeetet towards the target while heavy objects should not budge to the pull of the player cursor instead requiring the palyer to move the player cahracter.

#

basicaly this rope and spring setup should be a way to model interpolating between these 2 effects

sleek thicket
slender lotus
#

im fairly new to using avian

#

or modeling more complex behaviour than colision

#

ill google it

noble spade
#

Hello there, quick question. I want to build a 2d platformer but using a Camera3d, mainly for light and parallax. Will avian2d work the same or should I expect some issue ?

sweet sundial
#

it doesn't know anything about the camera
only problem might be preserving z position on bodies, but i think it does already

noble spade
#

Okay, nice ! Thank you !

terse shard
slender lotus
#

but i still cant peace it together

#

btu its also prety late where i live so probably tomorow ill find a way

sleek thicket
ancient quarry
sleek thicket
heady oasis
#

everything just operates awkwardly

#

trying to read forward velocity for the car but when applying torque that velocity shoots away into negatives

#

rlly cant use that data for consistent "throttle" using a curve

#

like it's "working"

#

but nowhere near a best-practice and intuative tutorial level

terse shard
heady oasis
#

sure

steep sequoia
#

I shifted the physics to run in PostUpdate (and all my FixedUpdate schedules to Update), but that causes a panic caused by NaN values:
Error: The vector given to `Dir3::new_unchecked` is not normalized. The length is NaN. Encountered a panic in system `car_suspension::apply_acceleration`!
Has anybody come across this?

#

It feels like it shouldn't behave any differently whether I'm using PostFixedUpdate + FixedUpdate or PostUpdate + Update

sweet sundial
#

log the delta time every frame
nonfixed timestep'll make your physics harder to keep solid

slender lotus
slender lotus
#

im a bit bafled

slender lotus
#

all i can come up with seems crazy complicated. rn my idea is to solve in 2 steps. first comput the position of R then use that to compute the forces between P M and T. does that make sense? or is thera a way easier solution?

sleek thicket
slender lotus
#

i meant for initial exploration. afterwards chat gpt is great

#

at elast to point u to the docs

#

i just noticed this would be a cool featur but its totaly not gameplay relevant rn

#

i get way to sidetracked XD

sleek thicket
# slender lotus i get way to sidetracked XD

you might burn out if you don't let yourself sidetrack though (especially if you have ADHD), just keep irrelevant things in plugins/mods so that you can disable them when you drop them half-finished

slender lotus
#

yee

#

but overall making cuts of too important tangents is prety important

#

else i get burned out on a tangent and dont even continue the main path XD

#

wich is the worst of both worlds XD

slender lotus
#

while in my game i rn dont even have a plan for large masses. and even if i could just make it 2 seperate actions that arent interpolated (E connect to mass and bull with body. LMB+ drag move mass to cursor)

knotty thicket
sleek thicket
knotty thicket
slender lotus
#

i dont think there was any ill intent

#

i also think both sides of the ai argument are valid but its starting to become something religeous in the extrems (vibe codesr vs people that ignore ai exists)

knotty thicket
#

think about it like this. if someone was constantly responding "Google is your friend" to questions, that is not a great way to interact with people asking for help.

slender lotus
#

as we all use google extensively this is rude

#

ur right

#

but io know a lot of people that havent learned to use chat gpt properly yet and maybe still sometime google in cases where chat gpt is more efective

sleek thicket
slender lotus
#

so i see it more of a friendly hint that there is a good tool to learn that might help in this cases

#
  • in this case @sleek thicket also pointed me straigt to the docs wich is more than a LMGTFU
#

i think this is no topic we must fight about lots XD

knotty thicket
slender lotus
#

@knotty thicket would you make a video about all things joints though? that could be very eductaional and looks quite intresting too so it makes great content?

knotty thicket
slender lotus
#

but thats cool

peak timber
#

I think it's wrong to assume LLMs are going to be helpful learning how Avian works, since any training data it has on it is very sparse and likely outdated compared to more general topics. So it will just make stuff up to fill in the gaps. Asking questions in the channel where the literal author of the library can see them makes sense

slender lotus
#

partialy. newer models are prety good at reading the docs though. so that is less of an issue for situations where u know what concepts need to be applied but dont know how. if u dont knwo the concept it can be a bit more beneficial readin the docs and talking to knowledgeable people first. overall i think its a tool worth learning.

#

but i think thats enough yapping about ai. we prob should make a chanel / thread for this if we want to discus this more

sleek thicket
visual sparrow
#

friends, #machine-learning is that way 😉

terse shard
#

I'm encountering some strange behaviour with ShapeCasters for my little vehicle sim, which is causing some bizarre behaviour.

For context, I initally built this sim using RayCasters for the suspension, which is pretty standard (as far as I understand), but wanted to move over to using ShapeCasters as this allows for a wheel to react to uneven surfaces (where a RayCaster has to pass over the "step" entirely before reacting to it).

I've tried with several different Collider shapes as well but get similar results regardless.
It appears as though the contact point for the ShapeCaster changes every tick, resulting in inconsistent distance values, which then gives unpredictable spring forces.

Has anyone used ShapeCasters in anger and had a similar experience?

To test, I built a stripped down version containing a single mass with a similarly configured ShapeCaster setup, however the behaviour here is very predictable, so it seems odd to me that in the main sim things are so... wobbly.

#

For a little additional info, the ground is a Plane3d with a trimesh_from_mesh collider.
I noticed the severe jitter as the hit point crosses the triangle boundary and thought it might be something to do with that, but then the test setup uses the same ground, just smaller.

wet niche
vestal minnow
#

Parry's shape casts and ray casts in general are kinda flaky though, and can sometimes even fully miss obvious hits or return highly inaccurate points or normals (see #298, #180, #70, #193, #317, #378, #166...)

#

the accuracy and robustness of my WIP collision detection library Peck seems to be a lot better, so hopefully it'll improve things once it's ready for real-world usage

last mountain
#

Is it possible to emulate something like ColliderOf{body: None}? I have two collider children on my parent, but one only serves as a proximity sensor (and has a Sensor component). For this reason I'd like to exclude it from RigidBodyColliders so that ahoy doesn't see it as a collider. Is this possible?

I was hoping something like this would work:

player_commands.with_child((
        Transform::from_xyz(0.0, 0.0, 0.4),
        Collider::cuboid(0.8, 1.2, 1.0),
        CollisionEventsEnabled,
        PlayerInteractionSensor { offset: -0.5 },
        Sensor,
        ColliderOf {
            body: Entity::PLACEHOLDER,
        },
    ))

but sadly it doesn't

sweet sundial
#

shouldn't Sensor work already?

#

could use a custom relationship to sync transforms without ChildOf

vestal minnow
visual sparrow
#

you're also right, I should change it to ignore sensors for that

#

at least allowing exactly one read collider and an arbitrary amount of sensors should be easy

visual sparrow
#

I don't see any indication of that hmm

vestal minnow
#

so that ahoy doesn't see it as a collider

visual sparrow
#

oh I cannot read

#

lololol

visual sparrow
#

watch out for the release super_bevy

vestal minnow
#

ofc a sensor might be more convenient since it'd automatically follow the character and can also trigger collision events

fallow pike
#

Why static bodies cam collide with other static bodies?

#

My game crashes if yhey collide (if they placed very near more like to z fighting)

#

But if i set collision layers directly for collision only with player

#

Then all works

acoustic spoke
#

does avian plan to add support for cloth/spring physics?

#

or can i already do that with joints?

last mountain
# visual sparrow I can fix this in like an hour

Amazing, thanks. Btw I'm also the person who made the issue about gravity direction. I'm still interested in working on it but life happened and I will probably be busy for a week but afterwards I hope to take a look

vestal minnow
#

It's not planned for the near future, but once I'm happy with where were at in terms of the core rigid body dynamics engine (collisions, joints, APIs, performance), I'd love to explore cloth and soft bodies and maybe fluid sim

#

Note that there is already bevy_silk for CPU cloth, though they seem to be at Bevy 0.17 still

acoustic spoke
#

i could probably just fork bevy_silk and port to 0.18 and hope there aren't too many breaking changes that i don't know how to fix

vestal minnow
acoustic spoke
#

unfortunately the author seems...inactive for the time being

vestal minnow
#

yeahh

fallow pike
# fallow pike My game crashes if yhey collide (if they placed very near more like to z fightin...
thread 'main' (105300) panicked at /home/noviui/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/avian3d-0.5.0/src/dynamics/solver/constraint_graph.rs:173:9:
assertion failed: !is_static1 || !is_static2
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `<Enable the debug feature to see the name>`!
Encountered a panic in system `<Enable the debug feature to see the name>`!
Encountered a panic in system `<Enable the debug feature to see the name>`!
Encountered a panic in system `<Enable the debug feature to see the name>`!
Encountered a panic in system `<Enable the debug feature to see the name>`!
sweet sundial
#

are you changing what type of body they are at a weird time

fallow pike
#

I can fast add and remove static body and collider

finite blaze
visual sparrow
#

since you need all that physics stuff on the CPU in the end, and GPU readback slow enough that it would in the end probably end up slower than our CPU implementation

#

And for something like cutscenes you can pre-bake the physics as animations anyways

finite blaze
#

Thanks for sharing that info, appreciated 🙂

vestal minnow
#

GPU physics can be great iff you need to optimize for maximal throughput, don't have game code tied too tightly to physics, and are not GPU bound on rendering. In general, game code needs to be quite close to physics code though (ex: read back simulation data, use collision hooks, etc.), and with Bevy having a GPU-driven tenderer the GPU may not even have much bandwidth available for large and detailed scenes

#
#

That being said, Rapier is working on some cool stuff for GPU physics, it definitely has its uses too

random rain
#

I have tried to use avian "v0.6.0-rc.1" but I have compilation error:
error[E0277]: cannot subtract glam::Vec3A from bevy_math::Vec3A
--> /home/pc/.cargo/git/checkouts/avian-4150e49b684ad442/8012ac0/crates/avian3d/../../src/collider_tree/obvhs_ext.rs:481:34
|
481 | let point_min = self.min - point;
| ^ no implementation for bevy_math::Vec3A - glam::Vec3A

bevy 0.18.1

Any idea what is going on?

latent vigil
#

if you have just switched try a cargo clean, cargo update and build again

random rain
#

That worked, Thanks!

random rain
#

v0.6.0-rc.1 solved for me a problem where avian was slow when on scene was 20k static objects 🙂

paper jasper
#

Out of curiousity is there any way to “simulate” an entity manually for a few ticks for example a projectiles flight path projection with avian?

surreal junco
#

I'm trying to get a character controller with rudimentary ground detection to work on 0.6.0-rc.1; here's what the scene looks like right now:

#

(the ball is the ground detector sensor, the capsule is the player, and the trapezoid is a static ground rigid body)

#

For some reason, the ground detector is currently reporting no collisions (CollidingEntities is an empty set, and Collisions::collisions_with(detector) is an empty iterator)

#

Is there any way I could debug that?

#

(besides the debug render I'm actively using, which seems to show the sensor overlapping the ground platform)

sweet sundial
#

what are its collision layers?

surreal junco
#

I didn't set collision layers for anything

#

The other detail is that it sometimes detects the platform

#

(also, the sensor is a child of the entity that has the capsule rigid body)

#

Including, when I start up the scene and let the capsule fall for the first time, it doesn't detect the ground, but when I move left or right, it starts detecting the ground plane again

#

And just about any time it stops detecting the ground, I can get it to detect again by moving left or right and waiting a bit

sweet sundial
#

what's the ground detector? a Sensor collider?

#

you could check all the collisions on the graph and print the relevant entities' ids

surreal junco
#

The ground detector is a Sensor, yeah

#

The complete list of collisions when the sensor sees nothing is empty, and the list when the sensor sees something appears to only contain that one collision

coral kite
#

Is avian rerecast still recommended to be used with Avian?

faint kite
#

@vestal minnow
Hello! Why does ShapeHitData's distance occasionally (quite often actually, like 10% of the time) shows wrong (much smaller) values, while the difference between point1 and point2 shows correct results?

Also, the docs for point2 (and for normal2 iirc) say they are in world space, but they are in fact in local space. I have to add a position to it to get actually world space coordinates.

And one more question, why does the distance in Avian's KCC gets truncated on walkable slopes, while even in the aforementioned algorithm (video about KCC for Unity) it preserves the distance?

Thanks!

bleak wadi
#

i havent bevy'd in a while, but wolud avian be suitable for just handling collision while my movement code is basically custom?

faint kite
sleek thicket
bleak wadi
#

haha rusty

sleek thicket
bleak wadi
#

ah i probably want dynamic then

#

i'm already using dynamic

#

maybe it's tnua that's the problem

sleek thicket
#

last time i looked at it, it seemed overcomplicated so i just made my own 🫠

faint kite
#

Every major game engine uses KCC. Think about it. 🧠

sleek thicket
faint kite
bleak wadi
bleak wadi
faint kite
#

Btw, Avian is getting its own KCC. Or already have got.

bleak wadi
#

kinematic character controller?

faint kite
bleak wadi
#

yeah that's what i want

#

how do i prevent clipping?

#

and just handle collision at all

faint kite
bleak wadi
#

im using tnua and it feels really bad

#

it also didnt feel good when i wrote the dynamic controller

#

i reckon ill write the kcc

#

idk if the game will ever be finished lol so may as well have some fun with it

faint kite
sleek thicket
bleak wadi
#

floating has gross bouncing for me

#

and it clips through the floor with/without floating

#

with dynamic

sleek thicket
#

clipping sounds weird, bouncing can be configured

bleak wadi
#

the floating still felt really weird

#

i didnt feel like i could make it feel snappy at all

#

which i want for a metroidvania

#

btw doubling physics ticks fixed the clipping but hurt performance

sleek thicket
#

i have no idea how you configured it, but that doesn't sound right

bleak wadi
#

alright ill look into it again

faint kite
bleak wadi
#

does it work well with pixel art?

bleak wadi
faint kite
bleak wadi
#

ah

bleak wadi
faint kite
#

But generally you just cast the shape of your character controller, and if it hits smth, you bend your vector along the surface. And then there go different cases, like if the slope is too steep, or if it's stairs...

bleak wadi
#

is that with a kcc?

faint kite
#

Yeah.

bleak wadi
#

cool

faint kite
#

It's generally just tons of geometry and algebra.

bleak wadi
#

sounds fun

bleak wadi
faint kite
#

I think it should be much easier in 2D than in 3D. And there are probably tons of algorithm on the internet, since there are tons of 2D platformers out there.

faint kite
bleak wadi
#

do you check with like corner coordinates?

sleek thicket
faint kite
#

In 3D we need clearance between character and the ground, because otherwise it will instantly hit the ground. I think it might be the case in 2D as well.

bleak wadi
#

im remembering now i think. polygons get weird but circles especially and also rectangles should be easy

faint kite
#

Is it blocky like Terraria?

#

Or does it have slopes?

bleak wadi
#

im imagining more like hollow kinght

#

which i dont think has slopes

#

but isn't exactly blocky

#

the physical design is all straight lines iirc, though the decoration ofc isnt

#

im using ldtk, so it'll have to be blocky i think. unless i used something else

#

an annoying thing with dynamic controllers is that the character would lose all horizontal speed on a vertical collision, and vice versa

sleek thicket
#

from friction? you can just disable it

bleak wadi
#

ah cool

#

as you can tell i didnt get far before giving up lol

#

a bunch of stuff broke when i chnaged to pixel art, and i lost motivation. also school started up again

sleek thicket
#

hidden defaults are a reasonable issue though 🤔

bleak wadi
#

ill see if i can get stuff working, ill ask people here to help if not, and otherwise ill rewrite as a kcc. do you recommend tnua or writing my own dynamic one?

sleek thicket
#

i don't know enough about tnua, but i recommend learning how it works if you decide to use it

bleak wadi
#

iirc i dont think you could customise the pivot speed

#

ill have to check again though

#

writing a kcc sounds like a fun project as well...

faint kite
#

Either way, if you hit smth, you get the surface normal from hit data, and then compare the angle to Y axis. If you have slopes, then you also should come up with some max_slope_angle and compare to it, e.g. if it's more than 50°, then it works as a wall. 90° means a vertical wall, 0° means ground. You get user's input, cast your shape in that direction, deal with what you hit, if anything. Use a loop within a function, so if you hit smth and want to bend your vector, you make a new shape cast in the next iteration, all during the same frame. But limit the number of iterations, or you can get into a endless loop.

sleek thicket
#

you can just use dot to check if it's wall/floor/ceiling

faint kite
faint kite
sleek thicket
sleek thicket
regal gulch
#

Is there a way to implement CollisionEvents between Scenes (as in Gltf's) nowadays? I could find few messages about it (e.g. the one this message responds to) but @vestal minnow suggestion back then still doesn't work and it seems that it still doesn't work out of the box.

wet niche
# regal gulch Is there a way to implement CollisionEvents between Scenes (as in Gltf's) nowada...

Hmm, this should work today (and in the past).
(1) glTF loads asynchronously, so when you spawn a SceneRoot(your_gltf_handle), you need to watch for On<SceneInstanceReady> to know when the model is fully loaded and spawned.
(2) In the event handler for SceneInstanceReady, traverse the hierarchy of the scene (use e.g. child_q: Query<&Children> and child_q.iter_descendants(...) starting at SceneInstanceReady::entity) and insert any Collider or ColliderConstructor components to the appropriate entities -- usually those with Mesh -- or if your model is simple and has homogenous colliders, add ColliderConstructorHierarchy component to that scene root.
(3) You need to have CollisionEventsEnabled on any entity with a Collider. Either add these in step (2) if adding Collider/ColliderConstructor. If you use the Hierarchy version, you'll need to add a system that watches for a query like Query<Entity, Added<Collider>>, which should fire some time after (2) and then use that entity to add this component.

If you're using Blender to make the glTFs, the easier way to get all this set up is to use Bevy Skein and just directly add these components at the appropriate locations (e.g. the Mesh portions of your model).

regal gulch
wet niche
wet niche
regal gulch
#

Okay that explains! I however still can't get it working o_O I can't however produce collisions even with Collisions SystemParam so there must be something other that I'm doing very very wrong. Have to continue on this later, now's the time to close laptop for today 🙂

EDIT: For context; I’m building a strategy game and until now I’ve determined the validity of new buildings placements by representing the map as a grid (for pathfinding and placements) and checking whether n-adjacent cells are not occupied. I decided to make buildings rotatable and figured I could simplify the validity determination with colliders.

wet niche
regal gulch
regal gulch
#

Okay even as I'm total beginner in this physics stuff.... I still feel embarassed... The problem was that I attached RigidBody::Static to all scenes/meshes. I ended up reading Avian source until I realised that "oh, two static rigid bodies can't collide" 😄

Still I can't get Observers working with the Collision events as I'm observing the root entity, but the collider is nested deep within the scene. Is there any workaround for propagating the events?

regal gulch
#

This is what I came up

fn prepare_colliding_scene(
    mut commands: Commands,
    q: Query<Entity, (Added<Collider>, With<GltfMeshName>)>,
    child_of_q: Query<&ChildOf>,
) {
    for entity in &q {
        let mut current = entity;
        while let Ok(ChildOf(parent)) = child_of_q.get(current) {
            current = *parent;
        }
        commands
            .entity(entity)
            .insert(CollisionEventsEnabled)
            .observe(move |trigger: On<CollisionStart>, mut commands: Commands| {
                commands.trigger(CollisionStart {
                    collider1: current,
                    ..*trigger
                });
            })
            .observe(move |trigger: On<CollisionEnd>, mut commands: Commands| {
                commands.trigger(CollisionEnd {
                    collider1: current,
                    ..*trigger
                });
            });
    }
}
vestal minnow
#

We could consider propagating collision events from child colliders to the parent rigid body by default

regal gulch
#

Well this seems to get the job done! Is there any particular reason for it not to be supported out of the box or did I just find such a niche use case? 😄

vestal minnow
#

Mostly it just hasn't been implemented, I think it's probably a good idea to propagate to the root body in principle

#

More generally there are some other cases too where usability could be improved for hierarchies

#

Oftentimes you only want to configure the body and have it affect all child colliders too, unless overridden for those entities

#

Some components already work like that, some don't, so it's maybe a bit inconsistent

vestal minnow
#

I would probably just manually estimate the trajectory by manually stepping through the movement, taking into account initial velocity and gravity, and if you need to consider collisions, using shape casts or something to detect hits, and reflecting velocity accordingly

#

We should probably make this a bit easier with some helpers and maybe have an example to demonstrate this sort of thing

regal gulch
#

Thanks for the response and assistance @vestal minnow and @wet niche !

vestal minnow
#

Np :)

vestal minnow
# faint kite <@545959292281552928> Hello! Why does `ShapeHitData`'s `distance` occasionally ...

Why does ShapeHitData's distance occasionally (quite often actually, like 10% of the time) shows wrong (much smaller) values, while the difference between point1 and point2 shows correct results?

Not sure, that data comes from Parry (the underlying collision detection lib) so I don't have too much control over it. I haven't personally noticed this or issues caused by it, but it's possible something is off there

Also, the docs for point2 (and for normal2 iirc) say they are in world space, but they are in fact in local space. I have to add a position to it to get actually world space coordinates.

What version is this on? In 0.6.0-rc they seem to all be in world space based on quickly rendering some shape cast results with gizmos. I think we might've fixed an issue here recently

why does the distance in Avian's KCC gets truncated on walkable slopes, while even in the aforementioned algorithm (video about KCC for Unity) it preserves the distance?

This depends on the behavior you want. In Godot for example, this is controlled by floor_constant_speed, which is false by default (i.e. going up slopes is slower, going down slopes is faster). Avian has no official KCC yet, it just has kinematic_character_2d and kinematic_character_3d examples (which were updated recently) to demonstrate how you could use the MoveAndSlide functionality to implement some basic KCC movement and collisions. A more complete KCC may want this sort of behavior to be configurable.

#

It will get more KCC functionality in future releases, right now there's just MoveAndSlide and some related utilities

wet niche
# regal gulch Thanks for the response and assistance <@545959292281552928> and <@641436315346...

yw! I wonder, though, if a review of the code shows a few misunderstandings instead.
(1) ~~Double-check that collider1 is the same entity -- I don't think the order of collider1 or collider2 is reliable in relation to the observe'd entity. ~~ (clarified below)
(2) Are you sure entity != current? before registering the observers?
(3) Do you know about MessageReader<CollisionStart/End>. They see the "global" set of events. I usually go this route for large-scale filtering of events.
I Imagine what you want is a cascading event system for collisions, perhaps where you collect all this data in a big observer at the root?
See if MessageReader better fits your needs? It'll avoid a lot of overhead.

vestal minnow
# coral kite Is avian rerecast still recommended to be used with Avian?

That's for @visual sparrow, but rerecast is the core crate for generating nav meshes, and it can be used without Bevy or Avian. bevy_rerecast is the Bevy integation. avian_rerecast just adds a backend to automatically generate navmeshes for static rigid bodies in Avian. So yeah if you want navmeshes for Avian, you should use bevy_rerecast together with avian_rerecast

#

and if you want to use rerecast with something other than Avian (ex: Rapier), you'll just have to write your own backend for it

vestal minnow
# wet niche yw! I wonder, though, if a review of the code shows a few misunderstandings inst...

(1) Double-check that collider1 is the same entity -- I don't think the order of collider1 or collider2 is reliable in relation to the observe'd entity.
In the context of observers, collider1 and collider2 do actually have a specified order, this is briefly mentioned in a code example in the docs (link)

fn on_player_stepped_on_plate(event: On<CollisionStart>, player_query: Query<&Player>) {
    // `colider1` and `body1` refer to the event target and its body.
    // `collider2` and `body2` refer to the other collider and its body.
    let pressure_plate = event.collider1;
    let other_entity = event.collider2;

    if player_query.contains(other_entity) {
        println!("Player {other_entity} stepped on pressure plate {pressure_plate}");
    }
}
#

However for messages there is no event target, so there the order is unspecified

wet niche
#

Absolutely right, thanks for the correction. Given that, a downside to MessageReader is that unorderedness. (I tend to (over-)use that pattern so am used to its need to validate order.)

regal gulch
# wet niche yw! I wonder, though, if a review of the code shows a few misunderstandings inst...

I’d want to emphasize that the snippet I posted will definitely need a more thorough thought! I already encountered a stack overflow without the GltfMeshName QueryFilter and colliding something against a regular Mesh3d 😂 That QueryFilter could use some thought I think. But about the points in your message;
2) you’re right that should be double checked. I also don’t (yet) have enough knowledge of these concepts to determine what entity the body1 field should point to. With those last nights brief tests it seemed to always be the same entity as collider1 but I suspect there are cases where it’s not that simple.
3) yes I’m aware of global Messages! Imo observers just make a lot more sense in this feature that I’m currently developing. You could of course achieve the same behavior with global Messages but determining the root ancestor would still be nescessary at one point.

faint kite
# vestal minnow > Why does ShapeHitData's distance occasionally (quite often actually, like 10% ...

What version is this on?
Yeah, I haven't updated it for a month or more. It's not even a “number” version, but it was always like this. (Although I've started to use Rust and Bevy not too long ago in general.)
I haven't personally noticed this or issues caused by it, but it's possible something is off there
When my custom character controller floats over a perfectly flat surface and casts its shape every frame, the difference between points is always consistent, but the distance sometimes shows like a 5 times smaller numbers.

surreal junco
#

I think I found a possible bug related to the character controller

#

I don't feel like I have enough info to file a full issue about it

surreal junco
#

The sensor ball and the platform are definitely colliding, but no collision is detected

#

I went down to broad phase to figure out if the problem was there, and sure enough, the ball never enters MovedProxies until after I move left or right

#

I'm wondering if this has something to do with it being the child of a CustomPositionIntegration entity?

#

That feels odd though

#

If someone more knowledgeable has more tips for tracking this down, I'd very much appreciate it; I don't know what I'm doing in physics engines

vestal minnow
surreal junco
#

I really don't have anything remotely minimal; I have a 200-line blurb I can throw in a gist

vestal minnow
#

That would be fine

surreal junco
vestal minnow
#

Thanks!

surreal junco
#

Let me know if there's anything else I can do to help on my end (partially because I want to be less useless at diagnosing these things when they do happen)

vestal minnow
#

unfortunately I have to go afk for ~40 min but I'll try to figure out what's happening after

surreal junco
#

Sounds good 😄

surreal junco
#

Any update? (I'm available for a little while)

vestal minnow
#

Basically the broad phase creates contact pairs for colliders whose enlarged AABBs overlap, and the narrow phase removes contact pairs when the AABBs stop overlapping, but the narrow phase was actually using the tight-fitting AABB instead of the enlarged AABB, so it would sometimes create and then immediately remove the contact pair

#

There's also some other inconsistencies in the tolerances used for AABB updates

#

should be able to get things fixed and PRd tonight

surreal junco
#

Ahhhh

#

Nice! a_cat_pats_hyper

vestal minnow
#

I'll merge it tomorrow

#

I was also playing around with making ColliderAabb actually tight-fitting (right now it's expanded based on velocity to account for speculative contacts), but that'll require a larger rework of our CCD logic, so I left it for now

#

I'll come back to that eventually, I'd really like to try Box2D's approach to CCD, it should be super fast but still quite reliable

surreal junco
#

Nice!!!

#

I'm excited to try it!

vestal minnow
candid canyon
#

yipee

candid canyon
#

uhhh

#

the f64 feature isnt really working

sweet sundial
#

easier to debug with #[cfg()] let v = a(); #[cfg()] let v = b(); v

#

but it looks like you have both features enabled and avian's resolving to 32

candid canyon
viral goblet
#

Would you consider adding modifier functions to CollisionLayers now that it's immutable?
(Sending here the extensions I made so far so others may use them)

viral goblet
#

Getting a panic:

no element at index 33 in StableVec::index_mut

Encountered a panic in system `avian2d::collider_tree::update::update_moved_collider_aabbs<avian2d::collision::collider::parry::Collider>`!
Encountered a panic in system `avian2d::schedule::run_physics_schedule`!
Encountered a panic in system `bevy_app::main_schedule::FixedMain::run_fixed_main`!
Encountered a panic in system `bevy_time::fixed::run_fixed_main_schedule`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
nimble fiber
#

Aren't you supposed to overwrite immutable components by just calling insert on a new copy of them?

viral goblet
viral goblet
candid canyon
#

how does big space work with avian?

surreal junco
#

PhysicsPicking is going haywire

#

The graphics are from the PhysicsDebugPlugin, as per usual

#

Look at the entity in the picking debug; it keeps alternating between entities 104 and 105 when the player entity jumps and moves around, even when the mouse is nowhere near the entities

surreal junco
#

If anyone has any ideas on how to debug this further, I'm all ears; I know I have a bit of an odd system for drawing the scene, so that could feasibly be part of the problem, but I don't know

dull dew
#

I'm having some issues where the fixedupdate seems to be ireggular (at least that's what i think is happening)
The car in the video is either accelerating at a fixed rate, or moving at a fixed speed. Yet i get these jumps.
It's much less noticable in release mode, but you can still see it if you look for it.
All gizmos are drawn in FixedUpdate along with my physics calculations and forces.

I'm on the newest 0.6 version

spring moss
#

Is there a way to make a collider that's the boolean intersection of some other colliders? I'm trying to compile Source maps, and I think that some of the collision is represented as the intersection of a bunch of half-spaces (i.e. infinite-extent planes). I'd like to try that out, I tried to figure out a meshing algorithm but haven't been able to make it work.

spring moss
#

Ok never mind, my meshing algorithm was actually fine

#

I just wasn't using it in the right places

royal helm
#

Is there a way to disable the physics debug gizmos on specific cameras?

#

or opt in only

#

I guess this is more of a bevy gizmos issue

sweet sundial
#

gizmos have visibility layers

surreal junco
#

What's the most idiomatic/efficient way to modify a collider that's actively being used on a character?

Specifically, I have a character whose collider stretches and shrinks to fit the model during its animations. I could use the Transform on it to translate/scale/rotate it, which was my first instinct, or I could directly modify the collider itself; what do you think would be the best option?

#

(also still wondering about how to effectively debug PhysicsPicking)

nimble fiber
# surreal junco What's the most idiomatic/efficient way to modify a collider that's actively bei...

I'm no Avian expert so take this with a grain of salt and some extra research:

My understanding is that any modification to a collider will cause a recalculation of things like the AABB; different physics engines cache more or less information about colliders. Avian's BVH implementation is brand spanking new so I don't know if it's rebuilt every iteration or if it is retained, I assume it's retained, so I imagine any collider change is also a BVH recalculation.

Most physics engines absolutely freak out if your scale is anything but identity on the transform, but my understanding is Avian handles scaled colliders and bodies correctly. I recall using scale to work with colliders in Skein before and it was fine. Maybe check if your masses are what you expect them to be, idk if Avian calculates mass from densities in world space or local space.

To give the lame answer, I don't think it matters unless character collider changes are a performance bottleneck for you. If that's the case, my guess would actually be that maintaining separate colliders that you enable/disable is most efficient. But that is 100% a guess.

An even lamer answer: Games like Silksong never change the character colliders for any characters. Hornet is just an ultra skinny stick whose collider doesn't even remotely match up with her sprites in most animation states. So you might be being too pedantic, unless your game is one where the characters grow and shrink a lot and that is a core mechanic.

I personally would avoid scaling just because I am allergic to altering scales on my transforms unless I have an extremely good reason to, from prior experiences in other engines.

#

As for physics picking- Does your character have sensors attached? Raycasts hit sensors. I had a weird issue where my units wouldn't be selected if I clicked on them dead center and it's because they had sensors in the middle for detecting other bodies on a different layer.

You may need to set the layer mask for the raycast to just the layer your character is on.

surreal junco
surreal junco
nimble fiber
#

Hmm- Is your collider a child of your rigidbody?

#

Would explain why the entity ids are neighbors

surreal junco
#

I can also guarantee that the characters that are being selected include the capsule and... something else? not sure what... but they're being selected no matter where my cursor is

#

The ground detector is a child of the rigid body, yeah

nimble fiber
#

I wonder if the picker is ping ponging between both for some reason

#

are you using a query to filter the result or just printing the raw entity ids

surreal junco
#

Considering I was having issues with the BVH right before release and they were also patched just before release, I wonder if that has something to do with it

surreal junco
nimble fiber
#

There was a sweep and mark broad phase but that's distinct from BVH

surreal junco
#

I was using the master branch

nimble fiber
#

Oh okay yeah nvm

surreal junco
#

(main? i forget which Avian uses)

#

I was using it to have access to the move-and-slide before release

#

I found a bug with colliders being excluded; it was an incompatibility between broad phase and narrow phase which presumably cropped up during the switch to BVH

nimble fiber
#

might be a dumb question but you're using Avian's PhysicsPickingPlugin and not Bevy's built-in mesh picking backend?

#

If so you can try adding Pickable::IGNORE to your child collider or the rigidbody

#

See if that changes the behavior

#

I suspect PickingDebugPlugin is logging all picking events, both for the collider and rigidbody

surreal junco
#

I'm using the PhysicsPickingPlugin, yeah (I had no meshes at the time of that video)

#

I may add Pickable::IGNORE to the child collider, but I'm still concerned that the plugin doesn't even seem to be remotely indicating what's actually under my cursor

nimble fiber
#

Yeah that I'm not sure on :/

If it was point query based my guess would be not checking for the inside bool but rays shouldn't have that issue.

#

Another random idea would be some issue with the camera setup? But I've gotta imagine bevy_picking is designed to smooth over stuff like camera transforms

surreal junco
#

yeah

#

One slightly odd thing is that it's 2D physics in a 3D world with a 3D camera

#

... But the gizmos are rendering fine

nimble fiber
surreal junco
#

yeah

#

That's kinda what I figured could be the issue

#

I'll take a closer look soonish; I'm currently trying to get bounding boxes (or, as the case may be, diamonds) set up so I start using the correct shapes in my tests

#

I should also get bevy_inspector_egui set up; the VS Code inspector has been flaky

nimble fiber
surreal junco
#

That feels like it'd be the same problem though

#

Like, if viewport_to_world works, that's probably what PhysicsPicking uses under the hood, or something like it

nimble fiber
#

yeah but you could lead with drawing a gizmo at the position of viewport_to_world

#

would at least give you an idea if the 2d physics/3d camera are clashing

surreal junco
#

True

#

... wait, but viewport_to_world is probably what Bevy normally uses

#

hmmmmmmm

#

Or maybe not

#

Maybe I'm thinking of the wrong function

#

No, yeah, it's Bevy's function; there's no way that's wrong

#

I'm a few minutes away from being able to test with the new bounding boxes, one sec

surreal junco
nimble fiber
#

Ahh true. Unless you have tens of thousands of them I don't think it will matter at all. I also think you can't really avoid it.

#

AABB/BVH rebuilds aren't that expensive. And, again, not an Avian SME so it's possible it's zero cost in this particular physics engine.

surreal junco
#

A potential solution would be to follow the ray to z=0, where the 2D objects are effectively being rendered, and then do the point check. I can imagine this could matter for other games, such as if a platformer has a 2D layer with the player and enemies but has 3D-placed scenery

#

I don't think performance is an issue in this case, since this bit of the picking code is only run once for every cursor on the screen (usually one). I'll make a PR

#

Thank you for coming along with me on this journey! a_cat_pats

surreal junco
#

Journey isn't over

surreal junco
#

So, as far as I can tell, the right point in world space is being found. That's completely okay now

#

... And yet, the actual picking is still completely broken

#

I made an example to test it, and even though I can prove that the ray is being converted to 2D world space correctly, the objects are still not getting highlighted how I'd expect

#

I shouldn't say completely broken; when I'm hovering over a ball, one of the nearby balls will highlight, it just might not be the one I'm actually hovering over