#Avian Physics
1 messages ยท Page 26 of 1
How to create new SharedShape from old SharedShape ? My system receive event include &SharedShape to create Collider, but I could not clone Arc object from it.
I guess this is right Collider::from(shape.clone())๐ฅฒ
Is there any difference between setting physics speed and setting physics time step?
Like id assume they do the same thing right?
Physics time step controls how frequently physics runs. Like the refresh rate on your monitor. Simulation speed controls how fast the actual simulation looks, allowing slow-mo or fast forward (fast-mo?)
Running physics more frequently is more expensive but can improve simulation quality
Oh right i thought step made the simulation go faster lol
Fair
Instead of using hollow shapes or an approximation I just used joints which did a good enough job, other solution would have have taken too long to load
in avian 2d, do both of these conditions have to be met or just one?
https://docs.rs/avian2d/latest/avian2d/collision/struct.CollisionLayers.html
Defines the collision layers of a collider using memberships and filters.
@vestal minnow do you plan on yoinking the avian picking backend for 0.15? bevy_mod_picking is on track for deprecation.
Both
Docs should probably be clarified though
Yup, I intend to yoink it and put it behind a bevy_picking feature flag (probably enabled by default)
I have some general design questions on how to implement a kinematic character controller in avian3d. My plan is to update the linear velocity of my character using shape-casting before the phsics step. Is this the right approach? Won't this mean my character could end up colliding with other moving kinematic rigidbodies at the end of the physics step?
Or maybe I'm confused on how avian works. The kinematic character controller example here https://github.com/Jondolf/avian/blob/main/crates/avian3d/examples/kinematic_character_3d/plugin.rs#L295 says "speculative collision". What does this mean, exactly?
Is there a bundle for removing all physics stuff, I spawn an object with a bundle containing
pub rigid_body: RigidBody,
pub collider: Collider,
pub collider_density: ColliderDensity,
pub dominance: Dominance
Is there a bundle of all physics components that may be generated so I can remove them all as I only do physics on gamestart and rather not run it after its done
As far as I'm aware, Avian will always allow all bodies to "collide" kinematics just lack built in response behavior, so its up to you to handle the response. There shouldn't be any issue with two entities running collide and slide hitting eachother as long as they're both working with linearvelocity
the list of removables
physics_stuff.remove::<(
ColliderParent,
ColliderMassProperties,
Mass,
InverseMass,
Inertia,
InverseInertia,
CenterOfMass,
ColliderTransform,
LinearVelocity,
AngularVelocity,
ExternalForce,
ExternalTorque,
ExternalImpulse,
ExternalAngularImpulse,
Restitution,
)>();
rest I cannot remove
is there a cleaner way to get the normal of the contact manifold depending on whether the queried entity is entity 1 or 2?
let normal = if entity == event.0.entity1 {
event
.0
.manifolds
.iter()
.next()
.and_then(|m| Some(m.normal1))
} else if entity == event.0.entity2 {
event
.0
.manifolds
.iter()
.next()
.and_then(|m| Some(m.normal2))
} else {
None
};
it seems that entity is consistently equal to entity1, but I'm not sure if I can depend on this, there seems to be no distinction between 1 and 2 in any documentation, so I have to write code like the above
would be good to be able to convert the Collision event into one that is relative to a given entity, so 1 and 2 become "this" and "other" for example. Something like event.relative_to(entity), returning Option<RelativeCollision>, where None is returned if it doesn't match entity1 or entity2
I don't understand the example. If I set the velocity in the collision response behavior, is that velocity used in the current step?
If I understand the example correctly, then velocity set in the collision response will be applied in the next physics update, right? At the end of the physics step, my kinematic rigidbodies will still be colliding, right?
Curious why PhysicsLayer requires implementing Default - shouldn't the default just be the empty mask?
Btw @vestal minnow, I noticed that the PhysicsDebugPlugin emits a ton of validation errors each frame on main:
Validation Error: [ SYNC-HAZARD-READ-AFTER-WRITE ] Object 0: handle = 0x555559a1ba80, type = VK_OBJECT_TYPE_QUEUE; | MessageID = 0xe4d96472 | vkQueueSubmit(): Hazard READ_AFTER_WRITE for entry 3, VkCommandBuffer 0x7ffee80ccfa0[main_transparent_pass_2d], Submitted access info (submitted_usage: SYNC_VERTEX_ATTRIBUTE_INPUT_VERTEX_ATTRIBUTE_READ, command: vkCmdDraw, seq_no: 3, reset_no: 37, debug_region: main_transparent_pass_2d). Access info (prior_usage: SYNC_COPY_TRANSFER_WRITE, write_barriers: SYNC_FRAGMENT_SHADER_COLOR_ATTACHMENT_READ|SYNC_FRAGMENT_SHADER_DEPTH_STENCIL_ATTACHMENT_READ|SYNC_FRAGMENT_SHADER_INPUT_ATTACHMENT_READ|SYNC_EARLY_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_READ|SYNC_EARLY_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE|SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_READ|SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE|SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_READ|SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE|SYNC_SUBPASS_SHADER_HUAWEI_INPUT_ATTACHMENT_READ, queue: VkQueue 0x555559a1ba80[], submit: 7, batch: 0, batch_tag: 192, command: vkCmdCopyBuffer, command_buffer: VkCommandBuffer 0x555559c53550[(wgpu internal) PendingWrites], seq_no: 8, reset_no: 1).
2024-10-29T20:59:18.770377Z ERROR wgpu_hal::vulkan::instance: objects: (type: QUEUE, hndl: 0x555559a1ba80, name: ?)
TLDR: PhysicsLayer is a trait you can derive for enums to make each of their variants represent a collision layer. On the main branch, the first bit is reserved for the default layer. We added the Default restriction to make this default layer explicit and prevent footguns.
Long explanation, starting with some background: Collision layers in Avian are specified for colliders with the CollisionLayers component (similar to bevy_rapier's CollisionGroups). Previously, the default was that every collider belongs on every layer, and can interact with every layer, meaning that all bits in the bitmasks are set to 1. I originally just copied this from Rapier.
However, we realized that this is very impractical and doesn't make sense in practice. It means that you can't e.g. perform ray casts targeting a specific layer without overriding everything, since all colliders belong to all layers by default. So, we changed the defaults on the main branch in #476 such that colliders only have one membership and all filters by default. The first bit in the bitmask is reserved for this default layer. This is the same as what the Box2D physics engine does.
To clarify what PhysicsLayer is for: it's a trait you can derive for an enum to use it for CollisionLayers. It's not something you're intended to manually implement for anything. Using it on the main branch looks like this:
#[derive(PhysicsLayer, Default)]
enum GameLayer {
#[default]
Default, // Layer 0 - the default layer that objects are assigned to
Player, // Layer 1
Enemy, // Layer 2
Ground, // Layer 3
}
// ...
// Player collides with enemies and the ground, but not with other players.
let layers = CollisionLayers::new(
GameLayer::Player,
[GameLayer::Default, GameLayer::Enemy, GameLayer::Ground],
);
If you have an enum value that is a PhysicsLayer, it must obviously represent some layer. You can't have an enum value that doesn't represent any of its variants. You can have empty CollisionLayers though, but it wouldn't make sense as a default, since then nothing would collide by default.
Now, finally the reason PhysicsLayer requires Default. Since the first bit is now reserved for the default layer, it means that one of the enum variants (typically the first one) is also the default layer. This is implicit and could be very confusing if you are not aware of this. So, we added the Default restriction in #494 to force users to explicitly specify "this variant represents the default layer", i.e. the first bit.
(wow, that became long ๐ )
got it thanks ๐
Is there an easy way to see your colliders, like a debug mode in aviann?
Or make like a semi visible capsule
Yup, you can add the PhysicsDebugPlugin
A plugin that renders physics objects and properties for debugging purposes. It is not enabled by default and must be added manually.
oh wee
what does LinearVelocity mean when running the physics simulation in FixedUpdate? is LinearVelocity not units per step?
It is
or no, I mean units per second
misread
So, for example LinearVelocity(Vec3::new(5.0, 0.0, 0,0)) would move towards positive X at 5 units/s
thanks. Followup question, is there a way to configure the plugin so that it represents velocity per step? Otherwise, what's the most reliable way to convert from velocity per step to velocity per second?
I'm not exactly sure what you mean by velocity per step, but if you mean converting "units per fixed delta time" to "units per second", then I think it's velocity_per_step / time.delta_seconds(), where time in your case is Time<Fixed>
So I was trying to setup my server to be able to handle avian physics. I got this error related to the debug plugin I think.
impl Plugin for SharedPhysicsPlugin {
fn build(&self, app: &mut App) {
// Leafwing input plugin handles the whole leafwing shenanigans
app.add_plugins(LeafwingInputPlugin::<CharacterAction>::default());
// SETUP FOR MAKING OUR PHYSICS WORK
app.add_plugins(
PhysicsPlugins::new(FixedUpdate)
.build()
.disable::<SyncPlugin>(),
);
app.add_plugins(PhysicsDebugPlugin::default());
// We change SyncPlugin to PostUpdate, because we want the visually
// interpreted values synced to transform every time, not just when
// Fixed schedule runs.
app.add_plugins(SyncPlugin::new(PostUpdate));
// Position and Rotation are the primary source of truth so no need to
// sync changes from Transform to Position.
app.insert_resource(SyncConfig {
transform_to_position: false,
position_to_transform: true,
});
// Setting timestep to same rate as fixed timestep hz
app.insert_resource(Time::new_with(Physics::fixed_once_hz(FIXED_TIMESTEP_HZ)));
// Setting up gravity
app.insert_resource(Gravity(Vec3::ZERO));
// Make sure that any physics simulation happens after the input
// SystemSet (i.e. where we apply user's actions).
app.configure_sets(
FixedUpdate,
(
(
PhysicsSet::Prepare,
PhysicsSet::StepSimulation,
PhysicsSet::Sync,
)
.in_set(InputPhysicsSet::Physics),
(InputPhysicsSet::Input, InputPhysicsSet::Physics).chain(),
),
);
}
}
I encountered this panic
Resource requested by bevy_gizmos::update_gizmo_meshesavian3d::debug_render::configuration::PhysicsGizmos does not exist: bevy_asset::assets::Assets<bevy_gizmos::LineGizmo>
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace
Encountered a panic in system bevy_gizmos::update_gizmo_meshes<avian3d::debug_render::configuration::PhysicsGizmos>!
Encountered a panic in system bevy_app::main_schedule::Main::run_main!
Any ideas on what type of adjustment i need to do to my physics debug plugin gizmos to avoid this?
FIgured it out
app.configure_sets( FixedUpdate, ( ( PhysicsSet::Prepare, PhysicsSet::StepSimulation, PhysicsSet::Sync, ) .in_set(InputPhysicsSet::Physics), (InputPhysicsSet::Input, InputPhysicsSet::Physics).chain(), ), ); this is nono
there's an avian backend in bevy_mod_picking @vestal minnow
are you interested in taking ownership/splitting that out at some point?
Yes #1124043933886976171 message
Great. Heads up, I'm going to try to do an end-of-life update to the existing avian backend, moving it to 0.15 but still using the legacy bevy_mod_picking version. We'll leave it to you to publish a version for the upstreamed picking version.
FYI Avian isn't using the 0.15 RC yet, but I intend to finish the migration today/tomorrow. I also can't do a release yet since I'm blocked on some other dependencies
no worries, we are also blocked on a release
@vestal minnow Is the correct way to "pause" physics to set the timestep to zero in Time<Physics>?
Time<Physics> should have a pause method (through an extension trait)
Great thanks, found it
I think Physics::fixed_hz doesn't exist anymore?
Oh, maybe I'm to use with_relative_speed now to force the resource to be created
Er no, that can't be right
oh, I can use default
Since physics on the main branch runs in FixedPostUpdate by default, you can just use Bevy's own Time::<Fixed>::from_hz now (the generic is optional there)
if you don't set the resource, what happens?
Basically that resource must exist to do pause / unpause
It's initialized by the physics plugins
Or you can just .init_resource::<Time<Physics>>() if for some reason you need it before that
(or insert_resource)
Does it use the value of the current fixed timestep by default? (btw, it works, I had an unrelated bug)
in other words, I'm doing this:
app.insert_resource(Time::<Fixed>::from_seconds(FIXED_TIMESTEP));
curious if it'll use that under the hood, or if i need to explicitly set it
Yes, it just uses Time::delta_seconds, and Time depends on the clock of the schedule that physics is running in
In fixed schedules, Time<Fixed>
Awesome thanks ๐
Np ๐
Hi! I am using spatial_query.cast_shape(...) and I need the point where the other collider is hit by the shape in local coordinates of said collider. I kind of thought that point1 of ShapeHitData is in local space of the collider but it seems to be in global space. At least that's what I think because when I subtract the Position/Transform of the collider from point1 I get the correct value.
That seems to be counter intuitive because ContactData works different where point1 and point2 are in their respective local coordinates. Is that intended or am I misunderstanding something? ๐
Yep I believe it's actually in world space. The docs in Parry (the collision detection lib Avian is currently using) say that it's in local space, but it doesn't seem like it when I've tested. I agree it's a bit inconsistent though
Avian's docs are also wrong here atm but I have a PR open that fixes them
I might also rename point1 and point2 for contact data to local_point1 and local_point2 to be more explicit
I finally made the initial 0.15 migration PR for y'all who are early adopters
https://github.com/Jondolf/avian/pull/540
I'll probably merge this tomorrow so people can use the main branch for the RC
I'll migrate internals to required components and add that picking backend in follow-ups
I have to wonder why this is like this
This is Parry Capsule right? Not Bevy's Capsule
yeah
Parry represents capsules with two endpoints and a radius rather than just a half-height and radius
So the half_height getter is just a helper to compute the distance between those points
*half of the distance
yeah ok it is just a getter cool ty
So I'm now porting things to required components, and I feel like it'd be a good time to rework some of our defaults as well. Any opposition to making these components optional?
For RigidBody:
FrictionRestitutionExternalForceExternalTorqueExternalImpulseExternalAngularImpulse
For Collider:
CollidingEntities
I think the force-related components definitely shouldn't be required. They're not used by anything internally, and you rarely need them on too many entities. CollidingEntities also makes sense as something you need to add manually, although people might then have the issue of forgetting to add it, at least at the start. Either way, I don't think any of these should be "required". If people want to insert them automatically anyway, it'll be easy in 0.15 with runtime required components.
Friction and Restitution I'm least sure about, but I think instead of inserting them for every rigid body automatically, we should treat them as extra configuration, and default to globally defined default material properties (see #119). This would let each app specify its own defaults.
Later on I'd also like to split the RigidBody enum in some way to only require velocity and mass components for dynamic bodies
@vestal minnow Hi, hope you are doing great!
I am making rts game on bevy using Avian 3d. And at the moment I am facing one issue:
I cannot pinpoint a time when I need to run observer or system so that it run after certain collider has been initialised.
I need to run series of raycasts on level collider to determine buildable and not buildable positions, if ray hits level then its buildable, if it doesn't then its not buildable position.
Since its quite compute heavy task I need to run it only once - when the level collider has been fully initialized and ready to be detected by raycasts.
I have difficulty getting system/observer run in this point in time. So far I have tried both observer Trigger<OnAdd, ColliderMarker> and system Query<Entity, Added<ColliderMarker>> , with system I have tried to run it on different schedules like Last, PostProcessCollisions and others.
If you have time I will be very grateful if you could give me advise on how to approach this problem.
Thank you!
You could try running it in the PhysicsSchedule, using .in_set(PhysicsStepSet::Last), with an Added<Collider> or Added<ColliderMarker> filter
Running anywhere after physics should also work, but it might be some issue where physics doesn't happen to run during the frame you added the collider and some values aren't initialized properly
It works with PhysicsSchedule .in_set(PhysicsStepSet::Last), thank you so much!!!! โค๏ธ
So if I'm following this right, if you make CollidingEntities optional without making it a required component using the new 0.15 feature, it'll never be added even by ContactReportingPlugin ?
Yes, it'd mean you need to add it manually to query for it
That's how it is in bevy_rapier too
Adding it to every collider is mainly just unnecessary memory usage for entities you don't need it for, which usually is most of your entities
Right, I get the motivation now!
Then it wouldn't make sense to make it a required component?
Yeah. Like, you probably don't need CollidingEntities on all random objects in the environment, but just on specific entities
Yep that makes sense
#1302253308010037309 message
This is such a strange thing, maybe someone can advise something?
in short, the joints behave strangely when the parent is turned
hey i was wondering what your thoughts are on this
https://github.com/Jondolf/avian/pull/527
@vestal minnow
Is the idea behind the context being able to query for other components or resources, or is there something else to it?
I don't love that you'd now need to pass a context (typically unused) to a bunch of user-facing methods. Conceptually it also doesn't make much sense that computing an AABB or mass properties for colliders requires access to outside information
yea pretty much
yea I get that, i agree. however, my usecase does seem to require it
IIRC the motivation was that this makes it easier to implement a custom voxel collider, right? Let's you access voxel data
If I think of context as Res<Assets<Sdf>> that makes sense to me tbh ๐ค
however, as i'm typing this out I think that I can just use observers
to update data inside collider components
or smth
yea
There's also that thing where avian probably needs to start using Assets at some point rather than having a big enum with weird Arc types from parry
So you have a shared structure that stores voxel data, and need to access that in the collider methods
yea
yeah, makes sense... I think it might require something context-like then
I don't think that PR can handle per-component vs world resource data correctly tho can it? ๐ค
Also wonder if there's some rust magic that can be done to remove that context arg entirely when the generics are ()
Probably not, but we could technically have separate _with_context variants of the methods
Maybe make impl only for types with empty context that add the non-context version, then make it non-optional
Because empty context would probably always be wrong on colliders that need it
Right, that'd probably be fine
yea
this was more of a proof of concept
to get it working for my use case
i'd be happy to clean it up further if it'd be useful
If it works for your use case, and you can't think of nice alternatives that'd work, I think I'd be fine adding something like this
I'd preferably like to keep the non-context versions for colliders that have an empty context, and also have the non-optional context versions, like Nise suggested
I wonder if something like the Fetchable collider idea from a while back could also work here somehow #1124043933886976171 message
probably?
Set gravity scale to 0 and add an external force to entities in a query with filter ?
Yeah i could do that
I was just thinking how the gravity resource works
but it seens he directly affect velocity
Not entities with impulse as I expected
Restitution::new(0.).with_combine_rule(CoefficientCombine::Min) Doesn't seem to be having any effect ๐ค
I'm dropping a rotation locked dynamic cube on a static cube, both with 0 restitution
This is caused by friction
Setting friction to 0 prevents any bouncing
I get this ๐ค
Okay yeah with a high friction of about 0.75 it gets a bit wack
but not with default friction in this basic test
Interesting, I've left the friction at the default. It does get worse if I raise the friction further
Ahhh sorry I missed "rotation locked", yeah it's worse with that
Let me test without locking the rotation
I'm aware of the 3D friction implementation being a bit wrong (see #489) so I wouldn't be surprised if this is related
With this setup I get some bounce
Yeah I get a small corner bounce with that too
I have two questions:
- what is the order of AngularVelocity?
- why is AngularVelocity euler angles instead of quaternions?
It's just a vector pointing along the rotation axis, and the length of the vector is the rotation speed in radians per second
2D would be equivalent to Vec3::Z * rotation_speed
i.e. you're only rotating about the Z axis, the other axes project to zero
using a scaled axis makes computations much simpler / more efficient than having to deal with quats everywhere
I'm not aware of any engine using quats for angular velocity
Glam's Quat is also intended to be normalized
So it doesn't make sense to use for angular velocity. It's primarily for representing orientation
Okay, that makes sense. I thought they were eulers cause I missed the comments on the AngularVelocity. ๐โโ๏ธ
The contact tangent directions for friction seem to be very wrong for the initial contact in a spinning case at least ๐ค lemme investigate
okay there's actually no way
this fixes it
- let tangent_velocity =
- relative_velocity + force_direction * force_direction.dot(relative_velocity);
+ let tangent_velocity =
+ relative_velocity - force_direction * force_direction.dot(relative_velocity);
god I love programming
I've tried debugging this friction bug on like five separate occasions and of course it ends up being a sign issue
FYI @pulsar bone ^ fixed it
I'll make a PR
Nice!
I'll run some more examples to test things though, this changes behavior quite a bit
since friction is now actually... like friction
Yes, that would affect things ๐
(the diff is misleading there because of snapshots, really it's a +2/-2 change)
I should really change our determinism tests to just produce a single hash that is compared between platforms instead of using these large snapshots
I noticed something about how the cubes bounce when it lands flat on a side. Its biased to rotate towards the positive axes after it bounces
I.E. Dropping a cube flat with the default gravity makes the top of the cube turn diagonally, towards positive Z and X(Towards the camera and to the right)
Same for dropping it in the other gravity directions I've tested(X, -X, and -Z ), it always turns toward the positive axes
Probably some bias in the order that Parry returns contact points for contact manifolds
For a cube landing flat, there can be 4 contact points, and they are solved sequentially
The order matters there, though more iterations can help make it less apparent
That makes a lot of sense ๐
It's possible to make a block solver that solves multiple contact point at once without bias, but I've only seen it for two contact points, for more than that it quickly gets very complicated and expensive afaik
Hello,
I am trying to switch away from rapier and made a test implementation
for top down car physics. I removed gravity, calculate the all
acting forces according to current energy. And then set the fixed
external force & torque each frame. No impulses. This works butter smooth
in rapier, but in avian I have these 'impuls' stutters. Besides the gravity, both
plugins run in default config. (1/60 step). Any idea, what could be the cause?
Looks like it could be a scheduling issue in camera following logic. Does this system ordering help?
https://docs.rs/avian2d/latest/avian2d/#why-does-my-camera-following-jitter
Its not a camera follow issue. The logic is the same in both test. Your suggested changes did improve the overall follow by a tiny bit. But the stutter still remains.
@vestal minnow Could it be a lack of transform interpolation + the fixed timestep being one frame ahead/behind sometimes? IIRC avian actually does properly run in fixed timestep unlike rapier
If the FPS isn't exactly 60, or it only happens sometimes then it would be because of the fixed timestep yes
You are right, that is the cause of the problem. On 60fps the stutter is gone. Demo runs on 164fps (vsync). I have to
look into avians schedule system. Thx alot, I was about to go nuts. ๐
Yeah Rapier defaults to a weird variable timestep with a capped delta iirc, so it's less of an issue there
I'm adding built-in interpolation for Avian 0.2 though
Thoughts on making collision started/ended events be observable ๐ฅบ
I'd like to do this yeah, it just ideally should be opt in instead of triggering for both entities for every single collision
A performant way to check whether there is an observer present would be nice
I'm wondering whether you could observe an observer being created for the collision events and then add a marker component automagically 
The tricky thing is that each observer is its own entity, and they don't live on the target entity. But IIRC there is a way to get observers targeting an entity, and I think I managed to get something scuffed like that working a while ago
Lemme see if I can find it
Hmm, Observer is type erased now :u
Mm I found old code related to this but it's not doing the thing I was thinking about
Right, Bevy has this ObservedBy component but it's private ๐
It sure would be nice
Oh and there's still the issue that you need to figure out if there's an observer with the correct event
I feel like this would be ideal here, but it's type-erased now like you said...
lemme ask in #ecs-dev
Should the next release include something like
if rb1.is_added() || rb2.is_added() {
+ if !contacts
+ .manifolds
+ .iter()
+ .any(|m| m.contacts.iter().any(|c| c.penetration >= 0.01))
+ {
+ continue;
+ }
```or just finally  the overlap warnings? ๐ค
I'd probably be in favor of just removing the warning, but this could be fine too
might need to scale by PhysicsLengthUnit?
Made a PR for each option, you previously mentioned 0.05 * PhysicsLengthUnit, so that's what the check version does
Ah I see you made a bunch of PRs, thanks
I think I'll merge the
version, I don't really see a need for the warning anymore and it's easy enough to add on the user's side too if someone really wants it
the threshold is also kinda arbitrary
Yea, was planning to make just these two options, but then I realized I had some some fixes for {:?} locally too, and I ran into failing doctests and by the time I fixed them I realize they were unrelated to my change ๐
At least in 0.15 the {:?} for Entity is a bit less awful, but it still looks a lot worse than {}
Weird how CI is fine with the doc tests
Maybe it doesn't run them? ๐ค
If you pass something like --lib to cargo test it won't run doc tests for example
It does look like it's running them
Oh ... Yea, that's very strange then ๐ค
Does it pull avian from crates and use that? ๐
I don't think so, it should be using the workspace's crates
The command it's using is currently
cargo test --no-default-features --features enhanced-determinism,collider-from-mesh,serialize,debug-plugin,avian2d/2d,avian3d/3d,avian2d/f64,avian3d/f64,default-collider,parry-f64,bevy_scene
I've also run it locally and tests pass fine
In my case I just ran cargo test -p avian3d -j 2 -- --test-threads=2
The -j and --test-threads is so doc tests and examples don't crash everything 
Might be a rust version thing tho, but I don't thinkg Type::default() should've ever been valid as a reference ๐ค
Is there a commonly accpeted workaround to not having motor joints at the moment? Even a way to just set a joint angle manually by moving around entities?
Alternatively what's in the way of motor joints currently? I've love to contribute so if it's more a matter of getting it done I'd be happy to take a crack at it. But if it's requires changing the entire engine or knowing the deep magic I'd leave it to the main devs.
Hi everyone, I need some help ๐
Long story short, I made a custom schedule to run Avian on it because I need it to keep looping while the visual frames are rendering, because I need to communicate with an external controller in real time. I run that custom schedule in a loop in a world exclusive system until it gets a signal that rendering is done.
The problem with this approach is that the physics simulation suddenly became insanely fast. I assume this is because every time I run the schedule, Avian will advance the physics clock it uses internally by the delta of the real clock, which would be equivalent to the delta time of the full app loop instead of my internal real time loop.
How should one get around this issue? Should I try to replace the real clock with my own and then restore the original at the end of my system?
A hacky way that might somewhat work is to dynamically change the min and max angle limits to force the joint to adjust the angle. Or you could maybe manually apply some torques to try to emulate a joint motor. I'm not sure how well these approaches would work though, I don't think I've tried them or seen other people have nice workarounds
So, Avian's joints currently still use Extended Position-Based Dynamics (XPBD). There's an XPBD rigid body simulation paper that describes the "proper" way to handle joint motors with it. For revolute joints (i.e. hinges, see section 3.4.1), you essentially just have a target angle that you update at every substep based on a target velocity, and the joint applies a correction that attempts to match this target angle. I have a very old branch that largely implements this.
The main blocker though is that I'm in the process of overhauling joints to use a completely different impulse-based approach instead of XPBD. I'd be a bit hesitant to spend time or effort adding proper XPBD-based joint motors right now, when it'll likely need to be entirely rewritten for the joint rework. The rework is still pretty WIP, but I hope to have it ready for Avian 0.3 (not the upcoming release coming with Bevy 0.15, but the one after that)
For impulse-based joints, motors should be relatively straightforward to implement, but the joints themselves are quite complicated and a lot of work
And the idea is that the release with impulse based joints will include motors or they'll be coming some time after that? If that's the case what the current timeline on that rewrite (days, weeks, months, or years). If it's more than a year away I might just try anyways since it could be nice to have an established interface when doing the rewrite so it wouldn't be completely wasted work.
I intend to include joint motors in that release, yeah, along with some other improvements to joints. Accurate estimates are always hard, but I would hope to have the rework ready in anywhere from 1-3 months. I have revolute joints in 2D and 3D mostly working locally already, and once they're fully done I expect the rest of the joints to be a bit easier
(I'm assuming you're using 0.1 and not the main branch)
You should probably set the physics timestep to Time::new_with(Physics::fixed_once_hz(my_internal_timestep_hz))
On the main branch you'd probably do what you're describing and replace the clock for the duration of physics, since physics uses the current schedule's active Time clock
Basically this just says "every time the physics schedule is run, advance physics time by 1.0 / my_internal_timestep_hz"
Which is a bit confusing, but... It's simpler on the main branch
You could also make your own scheduling by pausing the Time<Physics> clock (or rewriting PhysicsSchedulePlgin), and creating a system that manually advances time and runs the PhysicsSchedule
Ah that's interesting, so basically I could just replace the Time<Physics> resource every time I run my custom schedule with the true delta?
Yes I'm on 0.1.2
What I did now was replacing Time<Real> with a fake version and advance it on each interal cycle with the delta calculated in the system. I guess this has the added benefit that it works for other plugins as well, not just Avian, however it is a lot more complicated then basically setting the physics delta.
I noticed that my dynamic bodies randomly jump around, could that happen if the delta is very close to 0 perhaps?
I'm working on a robot simulator and I'm trying to use Avian but I'm having some difficult behavior. I'm constructing the robot from a URDF and I know I'm assembling it correctly but the moment I try to actually simulate anything it gets hairy fast. There's lots of stuttering and shaking and jumping around and it eventually just folds up. This might be a larger challenge of robotics simulation in general. I really should look into hoe Gazebo handles intersection and joints.
If anyone has the time my code is here: https://github.com/RunnersNum40/bevy_robotics
Things I have tried to fix this:
- Ignore collisions between links using
collisions.retain
- This doesn't seem to do much
- Turning the dampening on the joints up really high
- Going from nothing to a lot makes a difference but it doesn't solve it
- Setting restitution to zero
- Might make a difference but it's hard to say
- Increasing the substep count
- This helped a bit but didn't solve it
- Removing gravity
- No change
- Slightly scaling down the meshes
- Bad idea for obvious reasons and it didn't work
- Increasing the resolution of the VHACD convex decomposition
- Not much effect
- Locking all the joints be setting the angle limits to a small range or a single value
- I don't think it did anything
- Many combinations of the above
If anyone has some advice I'd greatly appreciate it.
Okay update. When I remove the colliders entirely and keep the joints everything works fine (except collision detection of course). This is confusing to me because I assumed that 1. Ignoring collisions between links using collisions.retain would have made them a non-factor. Is it possible I'm misinterpreting what the function does?
This is the system that's supposed to prevent small intersections from mattering:
fn ignore_collision(mut collisions: ResMut<Collisions>, query: Query<&URDFCollider>) {
collisions.retain(|contacts| {
let entity1_is_urdf = query.get(contacts.entity1).is_ok();
let entity2_is_urdf = query.get(contacts.entity2).is_ok();
if entity1_is_urdf && entity2_is_urdf {
collision_below_threshold(contacts, 0.01)
} else {
true
}
});
}
fn collision_below_threshold(contacts: &mut Contacts, ignore_threshold: f32) -> bool {
contacts.manifolds.iter().all(|manifold| {
manifold
.contacts
.iter()
.all(|contact| contact.penetration >= ignore_threshold)
})
}
Okay so one things that I wasn't doing that's made a big difference was having the ignore_collision system on the PostProcessCollisions schedule. I had it on Update so it basically didn't do anything.
That's solved a lot of my problem but I'm still a bit confused about how contact penetration works. I'm having a difficult time selecting a value that makes ignoring small intersections work correctly. They seem to vary in the 0.01 +- 0.005 range no matter what's happening. Does anyone have any insight into what the values mean? Should I consider a completely different metric?
@rich gazelle I have no answer to your questions, just wanted to say it looks really cool. I'm a robotics engineer and I'm trying to make a drone simulator. I think in case of Gazebo it doesn't actually simulate joints and joint motors, I'm pretty sure it just applies position or velocity updates to the "joints". Basically they can be treated as static bodies. Of course if you want "real" simulation which would allow collisions of the arm with itself or even ragdolling the arm that would be cool but yeah I'm not sure how to avoid this janky behaviour.
So it doesn't actually deal with link intersection it just is based on the joint limits?
Well I wouldn't swear on it but that's my understanding. There are joint limits in the URDF but you can still easily get the robot into a self collision. Honestly I used gazebo mostly for drones and robwork for industrial arms so I'm not fully sure. You could do manual collision checking in a test configuration to determine if that pose is valid for example.
if I were you I would try to make the collision mesh smaller around the joints so they are clearly not touching. Two links will not move closer to each other anyway since they are rigit bodies rotating around each other over just one axis.
But it depends on what your end goal is with this project.
Damn that makes me reconsider some choices here. I really like the idea of doing a proper simulation to get more accurate dynamics but I think it gets farther from real once things start exploding like this
My end goal is to be able to not use ROS but still have Gazebo
it's be nice to improve on it on the way
There are collaborative robots out there which go into a handmanouverable safety mode when they collide with something. That would be hard to do without modelling the dynamics
sorry that's confusing, I thought you're basically making a Gazebo replacement? Otherwise I think you can use Gazebo without ROS you just need to do some messaging
I tried making the meshes smaller but the naive approach leads to more intersections since you start pulling some of them into each other if they aren't perfectly convex
I am making a Gazebo replacement, sorry for any confusing language
mostly for personal use but I just want to try doing an entire robotics project in plain Rust
Yeah that's funny we're doing very similar things. Alright I feel a bit bad about hijacking this thread ๐
nah that's okay I stole yours
is there something similar to collision groups in avian?
Does avisn intend to make softbodies?
Jondolf has posted a soft body showcase in the past usin bevy_xpbd, haven't seen any soft bodies since however ... I think in theory it might be possible to add them manually on top too ๐ค
There's a third party bevy_silk crate for cloth, but actual deformable solids are not on the near-future roadmap for first party features. Hopefully some day once everything on the rigid body simulation side is good enough
It's not too hard to make very basic soft bodies with just a mass-spring-damper model using joints though
I remember there was some talk about adding a AnyCollider::Context associated type so that you can pass arbitrary world context down to colliders from the world. Previously this was implemented by @alpine oak (#1124043933886976171 message) where the context was a single extra component that may be included in the collider query. I've built on this and turned Context into a full ReadOnlySystemParam which you can access, and also give the AnyCollider access to its own entity ID, so it can read its own components from queries within that param.
Implementation here: https://github.com/oxkitsune/avian/pull/1
@vestal minnow Do you think this approach is suitable to be upstreamed into avian?
there's 1 safety comment which I think is actually safe, but I need to confirm with ecs folks
I think this resolves your concerns with having non-context versions though, since in that case colliders will just take () as context, which means nothing extra is queried
@vestal minnow Imagine the following, I have gravity setted up manually in my game, because it is networked. If my player is on ground, should I keep applying gravity in your opinion or nah? If the whole limitations of messages and such.
If you stop applying gravity when on the ground it's trivially easy to stop being on the ground, but not necessarily impossible when an object is stationary
well fudge
What might caused the following error/panic?
thread 'main' panicked at ...\.cargo\registry\src\index.crates.io-6f17d22bba15001f\avian3d-0.1.2\src\collision\collider\mod.rs:327:9:
assertion failed: b.min.cmple(b.max).all()
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `avian3d::collision::collider::backend::update_aabb<avian3d::collision::collider::parry::Collider>`!
Encountered a panic in system `avian3d::schedule::run_physics_schedule`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
I can re-prduce the above panic consistently. Since the setup has many objects/colliders running the same time, I wonder if there is anyway for me to debug which entity is causing the panic?
NaN
NaN in turn is usually caused by things rotating at very high speeds, denormalizing the rotation and making things quickly spiral out of control
After some debugging, I noticed the object I spawned into the game has the following initial transformation (without angular rotation)
--------- pos Vec3(5.0, 0.0, 0.0) rot Quat(0.0, -0.0, 0.22975293, 0.97324896) s Vec3(0.6, 0.6, 0.6)
in the avian3d system avian3d-0.1.2/src/collision/collider/backend.rs#L495 update_aabb both Position and Rotation for the collider is NaN
Position(Vec3(NaN, NaN, NaN)) rot Rotation(Quat(NaN, NaN, NaN, NaN))
Then I removed the debug_assert! from the grow method and notice the game seems to be running fine, with the object colliding with other objects correctly. I wonder if this NaN only exist for the object after the initial setup, but then gets auto corrected into valid numbers?
Ok. Here is my question:
Where is the logic that added the initial Position component for the newly initialized Collider. I can dig into that deeper to understand why it is NaN
I think I found the fix. I have a auto aim system that update the object orientation towards a moving target. The system was executed under Update schedule. When I change that system to use FixedUpdate schedule, now I no longer see the NaN in avian's update_aabb system.
Anyone knows why changing the schedule to FixedUpdate solves the issue?
Does avian run in FixedPostUpdate in your setup or in PostUpdate?
I don't know. What is the difference and how to configure it? Any best practice here?
It's configured based on the schedule passed to PhysicsPlugin, on 0.1.2 it's still PostUpdate, but if you'r on a newer git version it's FixedPostUpdate
The best practice is generally to use FixedUpdate so things aren't tied to FPS, but there are still some issues (which the default in 0.1.2 also has because it runs its own loop in PostUpdate, rather than just once per frame at a variable delta) like getting jittery movement when your frames and updates don't align perfectly. Which could be fixed with some interpolation, and there is a plugin for interpolation with avian, it's just not something you have by default iirc
I noticed the objects move slightly slower on my macbook (120FPS) versus my windows (60FPS). The configuration on the objects are the same, with LinearVelocity applied. I'm using FixedPostUpdate schedule to run physics. Suppose Fixed schedule would make the movement the same on different frame rate right?
BTW, I'm using avian 0.12. When I switch to PostUpdate for the Physics schedule, everything seems to work fine now. The movement looks exactly the same between 60 and 120 FPS.
The only issue I had with PostUpdate physics update is that when FPS drops lower (like 30FPS) things start moving slower again.
I think on 0.1.2 you also need to set Time<Physics> to match with how it runs. It should work as expected out-of-the-box in FixedPostUpdate in the next release
By default it currently is set up to run its own loop in PostUpdate, so the physics theirselves should run the same, but your own code might not run in-sync with physics, which can cause the results to be off
Here is what I did, and it seems everything is working well now, for 30/60/120 FPS consistently.
app.insert_resource(Time::new_with(Physics::fixed_once_hz(60.0)))
.add_plugins(PhysicsPlugins::new(FixedPostUpdate),...
...
.add_systems(FixedUpdate, keyboard_handle)
I learned bevy's FixedUpdate schedule is running at 64HZ instead of 60. I wonder if the above setup of 60.0 hz for physics would cause any issues? Does it need to match 64HZ?
Ideally it would match yes, you can either set FixedUpdate to 60Hz too, or set both to 64Hz
Yeah in this case, if it doesn't match, I think the simulation would be slower/faster than real time
like if fixed_once_hz was configured to 10 Hz and Bevy's fixed update uses 64 Hz, it'd run physics whenever the fixed update runs, but advance physics time by the equivalent of 10 Hz every time
(which is 1 / 10 Hz = 0.1 s)
but yeah on the main branch it's different and simpler, stuff like fixed_once_hz doesn't exist, you'd just configure Time<Fixed>
I'm doing my best to approximate joint motors with external forces and torques. Can anyone suggest the best schedule to run updates on? I've been using FixedUpdate but it would be nice if it could match the substeps so I can increase the accuracy if needed. I tried using avian3d::schedule::SubstepSchedule and avian3d::schedule::PhysicsSchedule but both cause a panic.
If anyone wants to take a look at a working implementation of motor joints I've made this plugin which allows velocity control of revolute joints
Hey, sorry, got a stupid question
I'm doing an rts selection system. Basic click on a unit and highlight it. I'm drawing boxes around units ala Starcraft.
Problem I have is I can't figure out the correct way to do it
The way I'm doing it atm is this
I decided to cache the mouse pointer info in a resource for reuse in multiple systems later on. I know events are probably a smarter way to do it but I just want something simple whilst I learn and mess around with things
I then get a point intersection using avian, with a collidable box
The problem I'm having after that is that I don't really know what to do with the entities themselves
Entities are set up like this. The idea is, click the entity, flag it as selected or unselected in some buffer somewhere, flip the visibility state of the child
Under normal circumstances in a game engine you'd just grab the entity and go to town finding its child. All I can think of is tagging the entity with a tag component of some sort and flipping it next frame
Any advice on how to deal with this and other similar problems coming out of SpatialQuery?
If I understood your setup correctly, you should just get the Children of the selected entities, query for the ones that are selection boxes, and toggle their visibility. I think it's something like this
fn flip_selection_box_visibility(
mouse_info: Res<MouseInfo>,
mouse_buttons: Res<ButtonInput<MouseButton>>,
mut q_selection_box: Query<&mut Visibility, With<SelectionBoxTag>>,
children: Query<&Children>,
mut commands: Commands,
) {
if mouse_buttons.just_pressed(MouseButton::Left) {
for &entity in mouse_info.selectable_entities.iter() {
// Get child entities.
let Ok(children) = children.get(entity) else {
continue;
};
// Iterate over children that are selection boxes.
// We can't use a for loop for `iter_many_mut` (I forget why)
let mut iter = q_selection_box.iter_many_mut(children);
while let Some(mut visibility) = iter.next() {
visibility.toggle_inherited_hidden();
}
}
}
}
So I was looking at defaults for friction and restitution coefficients and combine rules across physics engines
- Jolt: 0 restitution (max), 0.2 friction (geometric mean)
- Box2D: 0 restitution (max), 0.6 friction (geometric mean)
- PhysX: 0 restitution (average), 0 friction (average)
- Rapier: 0 restitution (average), 0.5 friction (average)
- Godot: 0 restitution (?), 1.0 friction ("rough" boolean)
- Unity 2D: 0 restitution (max), 0.4 friction (geometric mean)
- Unity 3D: 0 restitution (average), 0.6 friction (average)
- Avian: 0.3 restitution (average), 0.3 friction (average)
(gotta love how Unity is inconsistent between 2D and 3D)
I think we should at least change the default restitution to zero, making bounciness opt-in
I think it might be good to increase the default friction too, maybe to 0.6 or 0.5
probably good for default stability too, I imagine?
In almost everything I do I add in the Restitution::ZERO
Yeah, might help a bit
so I'd like that default
agreed
Then for combine rules, I'm not sure; the geometric mean sqrt(a * b) for friction is kinda nice since it means that the mixed friction is zero if either coefficient is zero, so e.g. everything can slide on "ice"
but it's still somewhat averaged otherwise
you can get that by just using CoefficientCombine::Min on the ice though... so I'm not sure if it's worth it
the current arithmetic average (a + b) / 2.0 is easier to reason about and think about in your head, so it might make sense to keep it as the default
especially for consistency with restitution, if we keep that the same
So I think the only thing left to figure out is what the default coefficient for friction should be, that's a bit more arbitrary
The current default of 0.3 feels way too slidey, and 0.6 feels like it's slightly too much
0.5 like in Rapier might be the sweet spot...
Wait are these used when the component is missing too?
Yes
Yea restitution probably should be 0 then, because having things bounce by default is kind of odd ๐ค
Yeah I think I'll change default restitution to 0 and default friction to 0.5, but keep the combine rules the same for now
and Restitution will be optional (currently it's added automatically)
Now I'm not sure if I should make Friction required or not. Conceptually yes, but I'd like to have DefaultRestitution and DefaultFriction resources that let you configure the global defaults
Similar to Unity's default physics material
(side note, I love how in Unity it's "Physic material" in 3D but "Physics material 2D" in 2D)
Technically we could do physics materials as assets, which would let us require a physics material component with the default handle for every rigid body, and you'd be able to modify the default material's asset... But I've felt like it'd be more annoying to work with (without an editor) since you'd need to define assets just to specify friction and restitution for things
The other benefit would be that you can just change one material and have that change affect every entity using that material, but you could also just define constants for friction and restitution values atm, so changing it in code is pretty straightforward
Physics material as assets does sound nice but yes it does also sound kind of painful ๐
What is the best way to alter a colliders size at run time? Is it just updating the collider shape or is there a better way I'm not aware of?
You could change the Transform scale
If you have other things like a mesh on the entity and you don't want to scale those, you can put the collider on a child entity and only scale that
Otherwise, yeah updating the collider shape would be the way
I'll give that a go, thanks!
what kind of physics body should i use for players?
There's no single correct answer, but at the very least static is probably the wrong choice ๐
Kinematic bodies are used for kinematic character controllers, while dynamic bodies are used for physics-based character controllers like the common floating capsule character controllers
thanks!
no pls, i used to try to use static physics bodies in physics engines for players thinking "well i dont want anything to act upon it, why is it making things bug out when i update the position?? why isnt the velocity being calculated??" ๐ญ
What is the correct schedule to run systems that modify the physics on? Things that modify the torques, velocities, or positions.
On the main branch, physics runs in FixedPostUpdate by default, and the intended place to run most logic like that would be before that, in FixedUpdate. Same as running things in _physics_process in Godot or FixedUpdate in Unity
In 0.1 physics is in PostUpdate by default, so it's a bit more annoying to run things at the same fixed timestep
There you'd run in PhysicsSchedule, with .before(PhysicsStepSet::Prepare) IIRC
Or, move physics scheduling to FixedPostUpdate kinda like the main branch
You can also run things inside the physics schedules or even the substepping loop if you really need to, but avoiding scheduling conflicts there is more annoying, and scheduling internals are prone to changes
values greater than 1.0 should be allowed, though not recommended
Finally we can model perpetual motion machines in avian that generate energy!
Thanks I'll have to consider that
If anyone's interested I've implemented really really basic motors for revolute joints https://github.com/RunnersNum40/avian_motors. The interface and naming is a bit rough because I've been prototyping a lot and changing things. I might work on cleaning it all up but if actual motors are coming soon I don't want to spend too much time on it.
It has PID based position and velocity control for revolute joint angles
I'd super appreciate if anyone has any suggestions for improvements
I'm also pretty new to rust so I've no clue how to setup the Cargo.toml so it's a usable library.
Question how can I acess the physics debug plugins gizmos, I need to insert a little bit of visual interpolation into them in my networked game
Doesn't modifying them to not match up with what physics actually did make them kind of useless?
hmm true, I wonder how I can make them less figety tho
Once there are corrections and rollbaccks
With my rollback it's pretty easy, I just clear all the gizmos before new simulations so I get exactly just one set of gizmos matching the newest tick
Mind if I see how you do it, I dont even know how to acess the gizmmo itself
Ah it looks like I slightly changed what I do.
I run this system after any resimulation so only events from the real simulations get picked up
fn clear_collision_events(
mut col_events: ResMut<Events<Collision>>,
mut start_events: ResMut<Events<CollisionStarted>>,
mut end_events: ResMut<Events<CollisionEnded>>,
) {
col_events.clear();
start_events.clear();
end_events.clear();
}
I'd assume you otherwise access them trough the Gizmos<PhysicsGizmos> system param
What is the/is there a recommended way of changing a collider's size at runtime? I'm trying to use it for collision detection on a basic 2d rts-style unit selection (rectangle that gets bigger with a mouse drag).
I tried using the ColliderConstructor, but it seems disappear upon the collider creation and adding a new one doesn't overwrite the previous collider.
is it ok to use CollisionLayers along with Sensors? i cant seem to get my player to collide with event triggers, but tile collisions ive set up with CollisionLayers in the same way work just fine
for reference, this (save for irrelevant bits) is how im spawning the triggers
commands.spawn((
RigidBody::Static,
Collider::rectangle(rect.width(), rect.height()),
CollisionLayers::new([Layer::Portal], [Layer::Player]),
Sensor,
/* trigger components */
));
and the player:
commands
.spawn((
RigidBody::Dynamic,
LockedAxes::ROTATION_LOCKED,
Collider::capsule(4.0, 8.0),
ShapeCaster::new(caster_shape, Vector::ZERO, 0.0, Dir2::NEG_Y)
.with_max_time_of_impact(1.0),
Friction::ZERO.with_combine_rule(CoefficientCombine::Min),
Restitution::ZERO.with_combine_rule(CoefficientCombine::Min),
ColliderDensity(2.0),
GravityScale(2.5),
CollisionLayers::new([Layer::Player], [Layer::Wall, Layer::Portal]),
))
I can detect every other collision with EventReader<CollisionStarted> just fine
it should work. i just double-checked, and i didn't even need rigidbody. not sure if it's added automatically though.
if you have a minute that'd be appreciated! i went through the sensors example and i'm still at a loss
the main things that are different for me: TransformBundle and const CollisionLayers... and using Collider::Sphere
@sharp dew how are you checking that it's getting hit? maybe you just forgot to use the system D;
hideous but here it is
fn portal_detection(
mut reader: EventReader<CollisionStarted>,
player_query: Query<Entity, With<Player>>,
portal_query: Query<Entity, With<Portal>>,
) {
for CollisionStarted(e1, e2) in reader.read() {
for portal in portal_query.iter() {
if let Ok(player) = player_query.get_single() {
warn!("collision detected between entities {e1} and {e2}");
// if one of the entities is the player and the other one a portal
if (*e1 == player || *e2 == player) && (*e1 == portal || *e2 == portal) {
warn!("portal collision detected");
}
}
}
}
}
the first warn! between the player and collision tiles works just fine, but nothing appears when i should be colliding with the triggers
just found out about CollidingEntities but that didn't give me any results either
^ this is basically what i have
i can't see what's wrong, but i cleaned it up a little
fn portal_detection(
mut reader: EventReader<CollisionStarted>,
player_query: Query<Entity, With<Player>>,
portal_query: Query<Entity, With<Portal>>,
) { let Ok(player) = player_query.get_single() else { error!("no player?"); }
for CollisionStarted(e1, e2) in reader.read() {
let (player_e, other_e) = if *e1 == player { (*e1, *e2) }
else if *e2 == player { (*e2, *e1) }
else { continue; }
for portal in portal_query.iter() {
if other_e == portal { warn!("success"); }
}
}
}
oh my god.
i just. forgot to add a transform to the portal spawn. groaaaaan.
the examples are still super useful to me, tysm!
doesn't it just spawn at 0 without transform?
guess so but i had no way to collide with it with the layout i have
Spent most of today trying to set up a testbed that would allow running all the 2D or 3D examples at once, and also added a way to reset examples. Only implemented it for two examples so far to just get it working
The goal is to have a similar thing as Box2D's demos, with a bunch of samples you can run, with UI for lots of configuration options
The tricky part is that I still want the examples to be useful for demonstration purposes and showing off APIs too, and you kinda have to set things up in a specific way so the tesbed can also run them
Right now I just create a struct for each example that defines the system configurations and the name of the example
pub fn main() {
App::new()
.add_plugins((
DefaultPlugins,
ExampleCommonPlugin,
PhysicsPlugins::default(),
MoveMarblesExample.plugin(),
))
.run();
}
pub struct MoveMarblesExample;
impl PhysicsExample for MoveMarblesExample {
fn name(&self) -> &str {
"Move Marbles"
}
fn setup(&self) -> SystemConfigs {
setup.into_configs()
}
fn fixed_update(&self) -> SystemConfigs {
movement.into_configs()
}
}
Ideally you could just use a plugin directly, but the testbed needs to add additional run conditions (or swap/reset worlds and schedules somehow, which I don't think is possible)
I think it's probably fine like this, the scheduling is rarely the focus in examples anyway, and in cases where it is, we can just have those be "normal" examples that aren't available in the testbed
Typically, just changing Transform scale #1124043933886976171 message
Unify dimensions so you can have 2D and 3D in the same app ๐
I think technically you could just have the examples in a separate crate that uses both crates... you'll have all the type names duplicated tho
Is there a way to exclude an entity from collisions?
I think your options would be collision post processing and making the collision layers not match
bevy_picking support!
https://github.com/Jondolf/avian/pull/554
Objective
Bevy 0.15 upstreams bevy_mod_picking as bevy_picking. Now that picking is first-party, we should add a collider picking backend, especially as bevy_mod_picking (which has an Avian backend...
I'll go over it again tomorrow and probably add a 2D example, it's getting really late here
(FYI @glacial nebula @bold garnet ๐)
Why do you do this bevy_picking thing instead of enabling bevy/bevy_picking trough a bevy_picking feature? ๐ค
It's also around for bevy_math for some reason
I think that one is for bevy_math/libm
Doesn't seem like it's exposed for bevy directly
Finally removed our insta snapshot stuff in favor of a transform hash for cross-platform determinism tests. Made the test much better too and added an example to visualize it
https://github.com/Jondolf/avian/pull/555
Begone unnecessary huge PR diffs and manual snapshot generation!
let's see if CI passes
also fixed some pretty nasty and obscure bugs I found
I wish my rollback was as deterministic as that example, it's somehow always just slightly off causing things to start moving at just the wrong angle creating tiny mispredictions which look less like mispredictions and more like jitter
Is it possible to apply an external torque around a specific point?
the former is generally better for compile times, if I understand what you mean
if you rely on bevy + features, your plugin can't start building until bevy and all transitive deps have finished building, even if your plugin only uses one tiny part of bevy
In this case avian did bevy and bevy_picking so it had both the annoying patch.crates-ioability of individual crates and blocking on bevy ๐
hey all, wondering if anyone has experienced little "hops" with dynamic character controllers in avian3d. basically, whenever my character moves horizontally when standing on flat ground, it gets some upward force. I don't have anything fancy setup, basically just the dynamic character controller example. I thought I'd ask here in case this is a known quick that is easily solved
probably ghost collision with triangle edge
hovering collider automatically solved it for me, so i don't remember if there was a proper fix
I see. I am just stepping away from using bevy_tnua's floating character controller as it wasn't playing well with lightyear... Is a hovering collider builtin to avian directly which I can use?
nah it's braindead simple to make it yourself
https://youtu.be/qdskE8PJy6Q
https://youtu.be/CdPYlj5uZeI
ah okay, thanks. I'll look into that!
and man, those 2 videos overshadow their actual game so hard it's strange that they didn't just convert into a tutorial channel ๐คฃ
haha. their tutorials seem very well done
What exactly is the heightfield collider?
A grid with a given height for each cell, useful for things like terrain
Also known as a heightmap, basically a collider for this
https://en.wikipedia.org/wiki/Heightmap
Oh i knew what a heightmap is, didnt know you could just do that
I'm working on optimizing my game a bit. I did a profile and am just wondering as this isn't something I've looked at to deeply before..
assuming I have several dynamic rigid bodies with cuboid colliders that I'm applying impulses to, is there anything I can do in "user code" to optimize this (it's a screenshot of the physics part of one frame) or is this pretty typical?
Yeah narrow phase collision detection (the blue block) and the contact solver are the main bottlenecks. There's not too much you can do on the user side, outside of things like avoiding complicated geometry (e.g. large/dense trimeshes)
Reducing the SubstepCount down from 6 can also help, but at some point it'll hurt stability
does making more granular collision layers help? Like, if I have a cube type that I only want to interact with one other type of cube, does setting up the layers that way reduce the collision checking?
It could maybe help slightly, but the broad phase already filters out entities whose AABBs aren't intersecting, so if they're far away they already shouldn't have collision checks
Optimizations for the solver are planned, but I keep getting other important (or more fun) things to work on :/
no worries and understandable. just wanted to see if there were any "low hanging fruit" I could look out for
Second stupid question, do physics work for entities in different plugins?
What do you mean by entities in different plugins? Entities don't belong to plugins, they just belong to... the ECS
Spawned in a different plugin*
I figuered it wouldnt but i am noticing it wasnt working so maybe i did something wrong
I have a stupid question too: can I define the rotation of a fixed joint between 2 dynamic bodies? I changed their Transform rotation but they keep sticking to each other with default rotation
Not really supported yet, though there's a PR to add this: #507
Haven't merged it yet since I need to verify that it works in 3D, and this also kinda overlaps with the joint overhaul I'm working on (among many other things, it should support proper "local frames" for joints, i.e. anchor offset + rotation offset)
A simple workaround that could maybe work depending on the use case is to instead use a child entity for the thing you want to rotate, and keep the parent rigid body as is
Made a quick proposal for reworking how we handle external forces and impulses. Not a very thought out or thorough design yet, but I do think we should rework things in some way
https://github.com/Jondolf/avian/discussions/558
Ideas and feedback welcome!
Thanks. For my use case I'll use a ball collider that doesn't need to be rotated
you can think of plugins as bundles, they're used just to group up stuff for convenience and don't really do anything special
Ok but wtf, i can see the colliders exist through the debug wireframe, run into them, no collision
Although only for trimesh, other shapes seem to work just fine
Hello, is avian2d have only event but not really collision collider?
Compount doesnt either, only basic shapes do
Genuinely have no idea what could be causing this
Hey guys, glad to see the Avian project is going well. I've just upgraded my codebase from 0.13 to 0.14, and xbpd still works great, so thanks for at least supporting it into 0.14. What's the transition like from xbpd to avian? Any big changes I should be aware of going in?
are you using CollisionLayers? What are the rigidbody types of the colliders involved?
There's a migration guide from bevy_xpbd to Avian here
I also have a blog post covering the biggest changes
https://joonaa.dev/blog/06/avian-0-1
The next release (coming after Bevy 0.15) also has a decent amount of changes, there'll be a migration guide and post for those too
No, static and dynamic
The normal colliders work fine, but the moment i switch to compound/trimesh i am able to clip right through, even if i am using the same points
Hello, is avian2d have only event but not really collision collider?
I create a bullet for attack detection but it really collision.
I'm not sure if I understood exactly what you mean, but:
- A
Collideron its own currently only detects collisions and sends collision events likeCollisionStarted. Objects can go through colliders with no "collision response". - To enable "collision response" for a
Collider, make it aRigidBody. That way, dynamic rigid bodies can bump into it. - If you want a
RigidBodythat has aColliderbut does not have collision response, you can add theSensorcomponent. This makes it behave like a standaloneCollideragain, but with the other features of rigid bodies.
Thanks for reply, Sensor works for me.
But i got tons of message
Dynamic rigid body Entity { index: 0, generation: 2 } has no mass or inertia. This can cause NaN values. Consider adding a `MassPropertiesBundle` or a `Collider` with mass.
It's really a Collider:
.insert(RigidBody::Dynamic)
.insert(Collider::circle(4.))
.insert(CollisionLayers::from_bits(
ATTACK_DUMMY_GROUP,
NORMAL_COLLIDER_GROUP & !ATTACK_DUMMY_GROUP,
))
.insert(Lifetime(5.))
.insert(YSort::default())
.insert(Sensor)
.insert(LinearVelocity(
fire_direction.truncate().normalize() * bullet_speed,
));
What I did wrong?
Unlike normal colliders, sensors currently don't get mass automatically since they're not really physical "things", just shapes for detecting intersections in some area. A common use case could be detecting when the player enters some area, or is close to a door, which doesn't need mass.
Dynamic rigid bodies do need mass though. You could add it manually like this:
.insert(MassPropertiesBundle::new_computed(&Collider::circle(4.), 1.0))
which basically computes the collider's mass based on the shape with a density of 1. For colliders that aren't sensors, you don't need this
Also FYI, if the bullet is moving very fast, it could be better to use ray casts or shape casts than colliders. Depends on what kind of bullets they are though, and what behavior you need
Thank you very much, this knowledge will be very helpful for me to develop other kinds of skills.
Wait what does RigidBody + Sensor get that just Collider + Senssor doesn't?
You can have a dynamic RigidBody that moves around and responds to velocity, external forces, and joints, but doesn't have collision response, only sensor-based collision detection
Oh, so it's like a kinematic body that also doesn't push thing?
not kinematic since it's still controlled by physics, but it just passes through things
Sensor just disables the contact solver essentially (and automatic mass computation)
and in the future it likely wouldn't compute actual contact data, but just do cheaper intersection tests
Hey, sorry it took me so long to get back to you as I've been hellishly busy at work. I'll give this a shout and work out how it works ๐
It works! Took me a little while to figure out how Rust wanted me to do the function for toggling inherited visibility (because I'm a Python/R data monkey at work and every day spent in R saps your will to program), but it works ๐
I didn't even think to try using queries with simple lists of entities
Now that I think about it, it's stupid I never even considered how the engine itself would be doing the selection of entities ๐
Thanks so much
Hey again! things are (almost) working to get my balloon simulation off the ground. I'm having trouble with external forces though.
- If I have my systems
force.set_force(my_vec3)on theExternalForceevery physics tick, the force accumulates over time. - If I add additional
ExternalForcecomponents to the entity, the magnitudes are correct but the object does not move.
It's not exactly clear to me when I should set_force vs apply_force. If I understand it right I'd want to apply_force to make it act in world space, and set_force to change the vector thereafter.
Driving me crazy. Attached a snippet similar to what im working with if you're curious.
I put in logs to show that when the new ExternalForce is added it is indeed running the apply_force and then running set_force each physics tick after that. The main ExternalForce component on the plugin is still zero but I thought that additional forces would be summed to the dynamic body
2024-11-14T02:27:53.430373Z INFO yahs::simulator::forces: applied new buoyant force: Vec3(0.0, 0.0, 0.0)
2024-11-14T02:27:53.430394Z INFO yahs::simulator::forces: applied new weight force: Vec3(0.0, 0.0, 0.0)
2024-11-14T02:27:53.457624Z INFO yahs::simulator::forces: updated weight force: Vec3(0.0, -53.10969, 0.0)
2024-11-14T02:27:53.457619Z INFO yahs::simulator::forces: updated buoyant force: Vec3(0.0, 50.412033, 0.0)
Is impulse and force impersistent practically the same thing?
Mostly, but force is in Newtons, impulse is in Newton seconds. Applying an impulse of 1 Ns for a frame will be "stronger" than a force of 1 N, because the force equivalent to the impulse will be force = impulse / delta_secs, and delta_secs is typically 1.0 / 60.0 or some other value smaller than 1.0
I want to rework how forces and impulses work though. Imo it doesn't make sense to have "persistent impulses", and no other engines have them
(I have a rough proposal for a new approach here)
Here it looks like you're not updating the actual ExternalForce component of the body, just values stored in your own components
apply_force adds a new force on top of the existing forces, set_force sets the total force to a specific value
IIRC the forces are currently persistent by default, so you need to manually clear them, but you can also set persistence to false, and they'll be cleared automatically every frame
And like I mentioned ^ I'd like to rework the force stuff, it's not ideal currently imo
I was about to ask this exact question and make almost the exact same video
is the solution "use vsync and lock the game in at 60fps"? Is there an alternative? (Might be a question for Jondolf / NiseVoid / Tim too since they were part of this conversation)
That's pretty much what I did. Increased the physics step to 100 fps (close to my dev V-sync), called it a day / pushed
the problem into the future. It reduced the issue to a minimum, but not entirely gone. I just know the basics about
physics simulation, would be very happy if someone could explain the correct solution.
To me it looks like a interpolation error. The stutter does not feel linear. But that's just a wild guess.
I thought it was related to schedule ordering + fluctuating frame rate
Okay, so the only way to move the body is to update the external force component created with the rigid body and other external forces are ignored? I thought avian would sum all external forces attached to a rigid body. I'm coming from an engineering background so I drew the force diagram and added all the force vectors.
Not to hard to add a system to do that myself. Feels like I am doing the Shrek walking through the velvet rope thing though. https://makeagif.com/i/yI54VY
What is the "avian" way to handle summing a bunch of independent forces like this? I guess the answer is to have only one system that sets the net force, not one system for each contributing force.
I thought avian would sum all external forces attached to a rigid body
If you are adding your own custom components (weight, buoyant) how is avian supposed to know they exist to sum them?
I guess the answer is to have only one system that sets the net force, not one system for each contributing force.
Forces can be summed, you could reset the external force on your entity at the start of every update, then add forces to it from multiple systems throughout the update.
it does look like here you're using set_force in the update rather than apply_force?
actually, I should add that I notice this stutter in one of my games but not another one which also made me think it was due to scheduling and fluctuating fps
I really hope so. If its a bug on our end, that would be great. The interpolating thing is was just a wild guess. I do not know, how the physics internal work.
Good point. I did this so I know which force is which when querying later. I didn't consider that wrapping the external force component doesn't actually add the component itself.
Awesome thanks all this got me out of my thought spiral! Hopefully I'll have a cool demo to share when I get it working
Did you every figure out the cause? Noticing the same issue with half-space and non-half-spaces.
FYI that warning has been
ed on the main branch
Most likely it's mainly just what Tim and Nise said. Since physics uses a fixed timestep (60 Hz in 0.1, and Bevy's 64 Hz on the main branch), it can sometimes run once per frame, and sometimes skip frames depending on the screen refresh rate. The solution is to use transform interpolation to visually smooth out the movement between fixed timesteps, but this isn't built-in yet. It should be in the next release though, and I also have a bevy_transform_interpolation crate (somewhat experimental)
You can also (1) increase the fixed timestep rate to match the refresh rate, or (2) use a variable timestep, but (1) can be more expensive at high refresh rates, and also makes behavior dependent on the frame rate, and (2) is even worse in terms of determinism, and can make behavior wonky if FPS is inconsistent
no rush/pressure, totally just curious, when would the next release be?
I may go with 2 after checking out that crate because what in life is determined anyway amirite
oh so the fix is already in avian main?
No, interpolation isn't on main yet, but main uses the Bevy 0.15 RC so it's "ready" in that sense. I want to add a few more things though before release (like the interpolation)
got it ๐ cool
I might also make a release just for the 0.15 migration without the other changes to ease migration but I'm not sure yet... It's a bit of a pain to do lol
I noticed this change that made FixedPostUpdate the default
https://github.com/Jondolf/avian/pull/457
does that mean this should use FixedPostUpdate instead of PostUpdate?
https://docs.rs/avian3d/latest/avian3d/#why-does-my-camera-following-jitter
I think camera following logic can just be in Update on main. You generally don't want it to use a fixed timestep since you want camera movement to be smooth and run every frame with some lerp
PostUpdate is also fine still, as long as it's before transform propagation
I tend to use PostUpdate for purely visual stuff, which cameras often are not, since pointing the camera at something usually has some non-simulation impacts like highlighting things or whatever
Also lerp in a variable delta context is wrong, but iirc 0.15 should have that thing mweatherley added
yeah stable interpolation with smooth_nudge would be what you actually want
hmm, maybe I should upgrade and then come back to this. Does there happen to be example code of like.. even an opinionated way to avoid the stuttering?
The opinionated way is using the interpolation
And a pretty popular opinion at that
I've been chewing on the interpolation stuff for a couple of days again, and experimenting with making bevy_transform_interpolation work nicely for it (e.g. support alternative component sources for start and end states, like PreviousRotation and Rotation in our case). For now, I think I won't use it for Avian though; making things properly generic is kinda tricky, and my approach there doesn't work well for transform extrapolation.
Instead, I'll probably just add PhysicsInterpolation and maybe PhysicsExtrapolation components to Avian, and tailor it just to physics entities. It's simpler and likely more efficient, and technically we could also take e.g. velocity into account for more accurate interpolation, which requires physics integration anyway
Of course people could still use bevy_transform_interpolation for general interpolation too if they wanted, since it works for any entity with a Transform
Considering Avian doesn't support motors and supposing I set a joint-based car up (1 chassis, 4 axle joints each with 1 wheel joint), how should I propel my car? Should I just add some ExternalForce (not torque) to each wheel? Or to the chassis? Other approaches? Or should I just drop it all...
I was eyeing on bevy_transform_interpolation to see if we could have a similar approach to bevy_rapier ๐ ; Iโll take this approach with a grain of salt then ๐
It works fine, it just duplicates some data for storing the start and end of the interpolation (like what bevy_rapier's TransformInterpolation already does). For physics, you have the separate physics position stored already, so ideally you can just use that, and only store the previous position and rotation as extra
And yeah extrapolation needs velocity so that needs physics integration anyway
In practice I would also expect at least 95% of things that really need to move at a fixed timestep to be physics entities, so I'm not sure how useful fully general transform interpolation would be
That being said, I've seen interest in adding more general interpolation support to Bevy itself eventually (not just for transforms afaik), and if/when that's a thing, we can consider if we can make use of it too. Though I'd still expect physics to want some of its own logic
even if it's not useful, it just makes sense to have
like if you eventually run into a case where you want something without physics in fixed update and then realize that you have to deal with transform being choppy, just using the usual approach is just nice
Quick question, because I swear I have seen it somewhere. Can I create a collision mesh from an imported mesh? If so how?
You can add ColliderConstructorHierarchy to the scene, it generates a collider for each mesh in that scene once it's loaded
Yes that was it! Thank you!
Do you have an example of something that changes transforms and must be in fixed update (for determinism or something else) but doesn't use physics?
I agree it'd be nice to have in theory though
does the netcode count?
physics or movement could be done server-side and clients would just receive positions with regular intervals
I feel like you might want something more custom for that, and it's something that the networking library would handle instead of the user (like lightyear iirc), but I know close to nothing about netcode so idk
i guess games without any physics in the first place would also benefit from that a lot
built-in transform interpolation is a physics-only thing in both Godot and Unity fwiw
and if you want it otherwise, just manually lerp/slerp where necessary
hmmm... yeah, maybe it's worth adding that question and link to discussion right in the docs
but intuitively it just seems like a good idea to have a common way to interpolate transforms with movement systems stuck in fixedupdate for any reason
i just dropped TransformationInterpolationPlugin into my app and it works great, thanks @vestal minnow
this would get extra tricky for floating origins
I have a thing where you can still modify Transform outside of fixed schedules (e.g. in Update or PostUpdate) and it'll be treated as "teleporting" the entity
So, only transform changes in fixed schedules get interpolated, and only if you don't also change transforms in non-fixed schedules
Wouldn't that mean that when crossing from one cell to the next, the object would jump/not interpolate?
i.e. when the object teleports its Transform
Possibly, yeah
It's only for the remainder of that one fixed timestep but might still be a bit annoying, hmm
what approach were you planning on taking for integrating with big_space?
iirc we had very different approaches in mind
I'd probably try your idea of physics islands
I'm not sure how well it'll work with the current architecture in terms of running physics in parallel for different islands, but we'll need to rework things anyway to do that for actual simulation islands
Also need to consider how this will work together with simulation islands
I guess technically these physics islands would already be a simpler form of simulation islands :p just based on proximity (I think?) and not constraints
Hmm you could probably parallelize simulation island building based on these proximity-based Islands
@vestal minnow A funny thing is ocurring with my collision layers when inside a collider that you can collide with, and I add a impulse force my character just jumps way higher
Here is a sample
Any ideas on what causes this ๐
How do you determine if the character can jump, and apply the jump impulse? It's hard to tell what the problem is, but it kinda looks like the impulse strength is doubled, so intuitively I would guess that maybe it detects both the ground and the other character as entities you can jump on, and then tries to jump on both of them for some reason
which would add the jump impulse twice
I'm just guessing based on what it looks like though
I think I already see the mistake
// Handle jumping.
if action_state.pressed(&CharacterAction::Jump) {
let ray_cast_origin = character.position.0
+ Vec3::new(
0.0,
-CHARACTER_CAPSULE_HEIGHT / 2.0 - CHARACTER_CAPSULE_RADIUS,
0.0,
);
// Only jump if the character is on the ground.
//
// Check if we are touching the ground by sending a ray from the bottom
// of the character downwards.
if spatial_query
.cast_ray(
ray_cast_origin,
Dir3::NEG_Y,
0.01,
true,
SpatialQueryFilter::from_excluded_entities([character.entity]),
)
.is_some()
{
character
.external_impulse
.apply_impulse(Vec3::new(0.0, 5.0, 0.0));
}
}
I forgot the spatial query filter
Might also want to use just_pressed to only apply the impulse once? I believe pressed is true for every frame the button is held down
Turn out yeah it laster for 4 frames
https://docs.rs/avian3d/latest/avian3d/spatial_query/struct.ShapeHitData.html
Here the how should I interpret the TOI?
Data related to a hit during a shapecast.
I am trying to create a kinematic character controller, and for the collide and slide algorithm I need the distance between the projection and hit.
It's essentially just the distance the shape traveled before the first hit
It's most likely getting renamed to just distance soon
that is much more intuitive. thank you
is it 1:1 to vec3 distances? so a distance of 1.0 is the same as vec3(0.0, 0.0, 1.0).length()?
Yep
May I ask if this is something that you come home from work and do? Did you have another big project in a physics engine before bevy?
I don't currently have a job, but I'm a first-year university student, and yeah I do this mainly as a hobby
No way. How old are you?
I didn't have prior experience with physics simulations before I started making physics stuff for Bevy, I mostly did web dev, some mobile development, tinkered with several languages and technologies, and occasionally did some stuff in Unity and Godot
I'm 19
Man I am 20, you make me feel obsolete. What are you studying in uni?
Dont take it the wrong way but I thought you are some 30 year old guy with 2 bachelors in computer science and a master in physics just cuz its fun.
(2 bscs of course I am joking)
It's basically just computer science (not that exact study programme, but largely equivalent)
(I'm from Finland)
I am from Hungary
haha no worries ๐
I'll take that as a compliment
This is so crazy. You will have the easiest time finding an internship.
Hey, I wanted to circle back on this. I tried this and it didn't work. Closest I could get was dividing by TimestepMode::FixedOnce::delta, but this caused some weird jitter with angular velocity.
My goal is something like a kinematic position-based rigidbody for use in a character controller. I'm considering forgoing use of velocity and using Position and Rotation directly.
So are you trying to implement a kinematic position-based character that has Position and NextPosition components, and derives the velocity based on them such that the body will end up at NextPosition by the end of the frame?
no way! ๐ณ you're too talented lol
haha thanks ๐
I'm the same age as you but I'm very far from making a physics engine ๐
Eh, I started by just copying a tutorial, and it took a long time and struggling with papers and math before I actually understood how things generally worked (and I still don't fully understand a lot). It's a ton of incremental learning and researching into what other engines do, and I feel like I'm still in the lower end of the learning curve
I've technically been working on this stuff for over two years now, though actively about one and a half years probably
the first commit in the repo is from May 29, 2022, although I remember playing around with Verlet integration and watching YT videos on physics simulation stuff before that
It's literally impossible for me to work on my project and study at the same time. I can only work efficiently on my project during the vacations...
it's impressive what you've done in ~2 years
learning physics is tough so making an engine sure is
development through the last year of high school with matriculation exams going on was pretty rough ๐
nah the impressive stuff the understanding papers at 19
that's a highly appreciated skill
The paper I was mainly using for bevy_xpbd (what Avian was before it was rebranded) is this one on XPBD
https://matthias-research.github.io/pages/publications/PBDBodies.pdf
As far as papers go, it's not too crazy, the algorithm is outlined pretty clearly, everything is in pretty self-contained sections, and the formulas are relatively simple (though I didn't understand a lot of them at first)
I've definitely seen some papers that are a lot more unreadable with my math knowledge though lol
this is what I am saying. You say eh it's hard but doable.
at 19 years old.
is there any way i can toggle physics simulation of entities and then resume them?
i'd like to make a system for volumes where physics is allowed; if anything is outside a physics zone, it will pause that entity until physics in that area is permitted.
For now, you could probably just add/remove the RigidBody component, or make the paused bodies kinematic or static. I also have a PR (#536) to add a RigidBodyDisabled component, which I'll most likely merge for the upcoming release
alright, i see! i should probably explain why i want this - i'm doing a minecraft clone (bc there aren't enough already) and want to generate a small mesh around physics bodies for collision (from the world geometry / voxel data).
could i just make the system for updating these collision meshes run before physics systems to ensure simulated objects don't go too fast, leave their calculated collision zone, and fall through / clip into the world?
Not sure if I quite understood what you mean by collision zones ๐ค Do you mean that you generate colliders only for "active" chunks, and want to disable physics for "inactive" chunks to prevent bodies from falling through? But yeah you can probably update them before physics
yeah basically what youre describing
can avian efficiently handle collisions with larger collision meshes? does parry spatially partition collision meshes?
Yeah, it uses a Bounding Volume Hierarchy (BVH) for each trimesh to partition the triangles. Not super fast but pretty decent afaik. I think it's mainly slow if you have a ton of small triangles densely packed together, since then you might be intersecting all of them at once and get way more hit tests than normal
oh, okay! thats great, because i can just generate the collision mesh for entire chunks at once.
there's a problem in many physics engines (including avian) where things sliding along touching / flush (but separate) faces will hitch. to solve this, i would probably merge contiguous chunk meshes. but how would i unmerge when the chunk unloads? do i need to store all the chunk meshes and the combined mesh so i can recombine them upon chunk unloads (without having to remesh everything)? i cant think of a way to solve this without doing really hacky stuff with caching and tagging regions of mesh data to specific chunks and then deleting those regions when chunks unload. there's gotta be a better way.
so ig my question is: do you know of a solution to the hitching problem?
(btw im talking about collision meshes here)
I had that problem in a car game I'm making and the "solution" I ended up going with was to make a floating car controller using raycasts and impulses to "float" the collider rather than having it slide along the face.
it's a bit of work, but in the end I don't have to worry about the world meshes as much
Edit: I think I'm just going crazy over frame rate inconsistency so ignore this
I'm trying to get to the bottom of this stutter in my game. This is a really simplified example where I have a cube spawned with a linear velocity, zero gravity, a camera following it with an offset on after(PhysicsSet::Sync).before(TransformSystem::TransformPropagate). I'm using the bevy_transform_interpolation crate and have time set with Time::from_hz(120.0) and running in release mode.
and to me, I still see these random stutters... do y'all see it too? Is this enough to rule out that it's caused by the physics engine?
Basically, yes. I've got this working perfectly fine in an minimal example, but in my actual game the angular velocity is not applied in full.
pub fn log_system(
physics_time_r: Res<Time<Physics>>,
mut player_character_q: Query<
(&Transform, &AngularVelocity, &Rotation),
With<PhaseTagComponent>,
>,
) {
for (transform, angular_velocity, rotation) in player_character_q.iter_mut() {
debug!(
"{:?}+{}={}?",
transform.rotation.to_euler(EulerRot::YXZ).0,
(angular_velocity.0 * physics_time_r.delta_seconds()).y,
rotation.0.to_euler(EulerRot::YXZ).0
);
}
}
This gives me outputs like -0.7853124+3.1415927=2.2909148? and then 2.2909148+0.06528074=2.3562312? . It seems to simply not being applied in full and takes two steps to apply the velocity.
Which is strange, because I have a minimal app with the same implemetnation and it works just fine.
Did you write the character controller yourself?
You can merge them, and then save the merged vertices indexes.
I do not have an example, because I have never seen anything like this, but I think it could be done.
yes, although the clip there is not using it at all. That's literally just spawning a collider with zero gravity and giving it a linear velocity of Vec3::Z. I think what I'm seeing there is related to framerate and not avian
So this is a dynamic controller and not a kinematic?
the one I made is dynamic
Ah okay I hoped that it is kinematic :D
have you seen bevy_tnua? I really like it for character controllers
I want to create my own, and I have tried understanding tnua but I just couldn't.
I am having some weird behaviour currently. I will probably fix it sooner or later. It would have been faster if I could ask someone.
have you seen the toyful games youtube video on character controllers?
Yeah but it is not what I am looking for.
hey how do I get rid of these messages if I am juz spawning a bunch of static colliders that is closesly together (they are not overlapping actually)
WARN avian2d::boom::narrow_phase: Entity { index: 451, generation: 1 } and Entity { index: 502, generation: 1 } are overlapping at spawn, which can result in explosive behavior.
for now just spread them apart further D;
well I can't really do that haha, cuz it's a terrain map and the visuals and collisions would be off ๐คฃ
huh, iirc static colliders aren't supposed to have that message
Yea, static-static doesn't even get to the plugin that produces that message, there were some bugs that made them show up with kinematics tho, despite the fact that kinematic bodies can't produce explosive behavior because they have no collision responses
Idk if the fix for that ever got merged
I am still in version 0.1 tho, not sure if I should upgrade? but I am using also leafwing 0.14 and bevy 0.14
i'd wait for 0.15 first, it shouldn't be that long now
but i don't think version matters
I see, I will dig into the source code I guess ๐คฃ
just remove rigidbody from terrain and see if it still shows messages
alright lemme test
it doesn't show warnings anymore
tho does it still collide
yeah, you only need RB on the thing that moves
if they're static, and not sensors, no
oh alright, didn't know it follows that
is it possible for avian to skip applying impulses for a frame?
I have an Update system "A" that applies an impulse to an entity
and a PostUpdate after PhysicsSet before TransformPropagate system B that reads the transform
and sometimes I'll get a frame where the transform in those two systems is the same and it's also the same when system A runs on the next frame
Edit: I believe what might be happening is since System A is on Update, if a frame takes longer than the fixed update, the impulses get made too late.
seems like I still need the RigidBody::Static for collision to work ๐คฃ
Yup, can confirm on 0.1.2. At least when using a trimesh collider for the ground.
Everything just falls through if terrain entity does not have RigidBody::Static.
I also noted a large performance issue for trimesh collision.
When not adding CollisionMargin to the terrain entity, rigid bodies seem to be unable to enter sleep/are woken up by something(maybe speculative collision?).
Fps start to drop very noticably when >1.5k capsules with locked rotation are falling onto the terrain.
Note:
The drop only starts to happen when they start colliding with the terrain.
While all are falling the fps are fine.
Adding the CollisionMargin to the trimesh collider entity reduces the severity of the fps drop but it is not prevented entirely.
Does anyone have any idea what can cause this behaviour?
The duck is moving forward by updating its LinearVelocity component.
The update happens in the Update schedule of bevy.
It looks like its position is reset if it starts moving.
Furthermore, it starts to look jumpy/shaky and starts to bounce after a few seconds of moving forwards.
It has a capsule collider component, and the ground is a trimesh collider.
Sidenote: Previously, i have been using rapier and there it was just sliding along the ground without the resetting/bounciness.
I am sure I am doing something wrong/missing something but for now I am not exactly sure what.
I've seen similar behaviors caused by different things.. might be helpful to know exactly what LinearVelocity you're setting it to and using the PhysicsDebugPlugin to see all the colliders visually to start with
When using PhysicsDebugPlugin it looks like this:
are you using LockedAxes to lock translation?
like this when its standing still, i guess the lines are overlapping with the mesh so sometimes they are not visible.
Linear Velocity change is just z axis but once it starts moving linear velocity changes on x and y too.
I am just using LockedAxes::ROTATION_LOCKED
Restitution is set to Restitution::PERFECTLY_INELASTIC
I know the kinematic character controller example isn't really intended for use, so I'm not trying to be critical with this but I thought it was interesting. I'm using the kinematic_controller_collisions from the kinematic character example, and when I walk my character over the edges of the triangles in my custom terrain they seem to bounce like I might expect them to do if the character went over a small ramp:
I had the same issue. You can follow the conversation starting with my message on how to fix it with a floating capsule: #1124043933886976171 message
It worked for me
Thanks!
I am curious if this would be fixed with a proper collide-and-slide implementation. I just don't know enough about this
Perhaps. I quite like the floating collider approach as it can give you slopes and stairs basically for free if you float high enough
That's fair
yeah, for 3d the floating collider will be good even if edge ghost collision bug gets fixed
HL-2 anniversary doc, and how they used a string comparsion scale for object masses when debugging ("mass of a food can", "racehorse", "space station"): https://youtu.be/YCjNT9qGjh4?t=2138
lmao
there's several tricks the comment about, for example increasing the friction of the player when closer to edges
I am curious if I want my collider to rotate so he stares at mouse direction should I try applying force or just apply directly into angvel?
depends on how u want it, but u cud also use angular velocity as well
btw is there a concept of physics world in avian? let's say I want to have world 1 and world 2 so that they do not collide/interact with each other, is it possible?
from my research it seems like it's not supported yet, tho would it help if I use separate bevy Worlds?
I have not used multiple worlds in one bevy app yet.
However, if systems are run on each world separately, it should work as avian uses bevy systems for the physics calculations.
If you just want a few entity collision kinds to completely ignore each other you could also use CollisionLayers (Note there are only 32 layers available)
I did some experimentations, and it seems really hard to get it working ๐ข
yeah that's the thing, ideally the server should be able to support as much game sessions as the server can handle haha
the only "easier" solution I came up with is to put them in different locations and simulate them altogether ๐ญ , for now precision isn't the issue yet...
I dont know what is usually the go tofor character controllers
if it's kinematic, just rotate it
nope dynamic
then maybe consider using some sort of physics, but I really don't think it will matter that much since avian won't just explode if you accidentally clip into another collider due to rotation
it really depends on your use case, if you want snappy rotation, then rotate the Rotation component, if you want physics based, then use AngularVelocity or force
wanna ask, does CollisionLayer also affect sensors?
yes, afaik sensors only prevent collision entities from being affected by physics.
Otherwise, they should behave like regular colliders.
I see, thanks!
if it's for the head, then it sounds like a job for inverse kinematics
I think it's not that important for rotation.
It's crucial for linear velocity/acceleration, because even the slight differences between working with the velocity and working with the acceleration can have big effects on where the character ends up. Also, changing the velocity directly makes it possible for the character to slightly phase into solid walls - something that doesn't happen with acceleration (ExternalForce really). On the other hand, using acceleration makes it easier to overshoot - especially if you are not using fixed timestep. With velocity it's much easier to stop exactly when you want to. Because of that, for Tnua's linear movement part I'm using acceleration in general but when the character stops, during the last frame, I switch velocity to guarantee it won't change the direction before stopping completely (especially important if some other system is looking at the direction of the velocity to decide where the character should be facing)
But for rotation? The difference will be quite minor. It will affect how quickly the character turns, but the difference will not be noticeable - and either way the character will end up facing the same direction.
I do suggest though that you use angular velocity, which makes the calculations simpler. Additionally, phasing into walls is not a problem with rotation - but overshooting is.
Okay, I've kept working on this for the past few days, and I might take back what I said; currently, I think I will use bevy_transform_interpolation for Avian as well.
I've reworked the structure a ton and made it more extensible, and in #4 I managed to implement decent transform extrapolation, and also added support for some shiny (optional) Hermite interpolation to produce more accurate motion by taking velocities into account for the interpolation. The velocity components aren't defined in the crate itself, but passed in using generics implementing a VelocitySource trait. For Avian, this means that the interpolation can just use LinearVelocity and AngularVelocity instead of storing duplicates.
As for my concern re: duplicate position components instead of using the physics position directly, I think I'm actually fine with it for now. It means that we don't have to worry about hierarchies (Position and Rotation in Avian are in global space, but the interpolated Transform isn't!), and it might make big_space support more straightforward.
I'm still working on this though, so of course I could change my mind for the millionth time ๐
Things I still need to do for bevy_transform_interpolation:
- Try to integrate it with
big_space - Test camera following scenarios
- Maybe move the actual easing from
PostUpdatetoRunFixedMainLoop, inRunFixedMainLoopSystem::AfterFixedMainLoop? (#2) - Rework module structure some more
- Add a 3D example or two
- Finally, add a
PhysicsInterpolationPluginor similar to Avian using it
Not currently possible, other than using separate Worlds (pain), collision layers (limited to 32 layers), or filtering collisions manually (relatively slow).
It's a bit tricky to support more than one physics instance since Avian uses the ECS directly, and the ECS doesn't really have proper multi-world support or partitioning. In the future, we will probably do a limited version of "multiple physics worlds" where you can just assign physics entities to worlds/groups using some PhysicsWorldId, and each world has its own acceleration structures and constraints, making them fully separate in terms of physics entities interacting with one another
I think I've narrowed down the source of the stuttering in my game
I have the camera follow in PostUpdate, impulses applied in FixedUpdate and every couple seconds I get a frame where the physics isn't run before PostUpdate runs (which updates the smooth camera)
so everything stays still but the camera moves which makes it stutter.
I think I can work around that now that I know it's happening.. I guess it makes sense, just an update that doesn't align with the physics fixed update
Ah yes problem is I have no idea how to conver mouse motion into angular velocity
But you know how to convert mouse motion to torque?
actually I have a questions, how does one filter collisions manually?
this can be solved using transform interpolation: https://github.com/Jondolf/bevy_transform_interpolation
let movement = action
.clamped_axis_pair(&PlayerAction::Move)
.map(|axis| axis.xy())
.unwrap_or_default()
.normalize_or_zero();
let desired_angle = movement.to_angle();
angular.0 += rotation.angle_between(Rotation::radians(desired_angle))
* spaceship.angular_acceleration
* time.delta_seconds();
here, movement is a Vec2 direction, and rotation is the Rotation component from the entity
this is juz one way, u cud formulize other ways to do it hahaha
I find it easier to keep a persistent representation of the direction you want your character to face, and use mouse positions to rotate that direction. This is easier than doing it with velocity, because you can just convert mouse movement units into radians with a simple multiplication. Unless your character is a plane/spaceship - keep the spinning and elevation separate to make the updates easier.
Once you have that, calculate the angular velocity required to rotate to that direction in a single frame - and clamp it by the maximum rotation speed you want to allow (you'll probably want to have separate limits for spinning and pitching). That's the angular velocity for that frame.
This does mean that the character will keep turning for a bit after the player stops moving the mouse. But:
- Unless you use very slow rotation limits, this will hardly be noticeable.
- If you use a third person camera, you can move the camera separately from the character so that the camera will respond immediately to the mouse motion, even if the character takes a bit more time to get there.
- If none of these solutions are applicable - you can just have that forward direction slowly "diminish" (using a weighted average) toward the actual direction every frame.
I am actually using that. I think the problem is that during that frame where the physics doesn't update nothing in the physics world moves but my camera is lerping closer to its target (which hasn't moved) and then on the next frame it kinda over compensates. My solution is to just not move the camera if the target's translation hasn't changed
that crate is good though, it definitely helped smooth everything out
im controling a spaceship haha, but yes I agree, rmb to use deltatime too!
ah I have similar issues as well, it's when my bullets are telelporting from one position to another due to object pooling
my current solution is to not interpolate it at the start haha, maybe you can remove interpolate when it's not moving?
ah, that's interesting, I may run into that at some point. I guess for now I just have to "pause" the camera for a frame which is easy enough without having to add/remove components
Hi! How do I show the collision shape in Avian in the 3D space for debug reasons?
A plugin that renders physics objects and properties for debugging purposes. It is not enabled by default and must be added manually.
This is actually getting funny. Quick description: I am currently trying to implement a collide and slide algorithm. I am using the cast_shape function to manually check collision. If I press forward or/and left it works as expected, if however I press backward/right it for some what reason makes a collision at a distance of 0.0. I cannot debug it. The blue line - velocity - touches the ground everywhere. Everything shown in the visual is the same as in the cast_shape function.
The object is not moving in any direction. It has no LinearVelocity set.
Could this be a bug?
(please)
Hard to tell what's happening there, I'd probably log the shape cast directions and make sure they look correct for each input direction
Also FYI there's a few existing collide and slide implementations for Avian floating around, like this one in vidar by UB
aceeri also has one, but I can't find it rn with Discord's search
Oh wow thank you so much!
They do! Also the blue line that is shown is the direction times the max distance.
@vestal minnow using bevy_transformation_interpolation i experience a regression between HEAD and the previous commit. interpolation works great on the previous, but when i use the latest:
2024-11-21T22:52:18.270855Z INFO bevy_diagnostic::system_information_diagnostics_plugin::internal: SystemInfo { os: "Linux 21.3 Linux Mint", kernel: "6.8.0-49-generic", cpu: "12th Gen Intel(R) Core(TM) i9-12900K", core_count: "16", memory: "62.6 GiB" }
2024-11-21T22:52:18.371795Z INFO bevy_render::renderer: AdapterInfo { name: "NVIDIA GeForce RTX 3090", vendor: 4318, device: 8708, device_type: DiscreteGpu, driver: "NVIDIA", driver_info: "535.183.01", backend: Vulkan }
2024-11-21T22:52:18.749330Z INFO bevy_winit::system: Creating new window "App" (0v1#4294967296)
2024-11-21T22:52:18.749486Z INFO winit::platform_impl::linux::x11::window: Guessed window scale factor: 1
thread '<unnamed>' panicked at /home/ty/.cargo/git/checkouts/bevy_transform_interpolation-06af9eb63201b40c/1ee1c33/src/lib.rs:321:75:
called `Option::unwrap()` on a `None` value
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `bevy_transform_interpolation::reset_easing_states_on_transform_change`!
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`!
Segmentation fault (core dumped)
error: Recipe `local` failed on line 5 with exit code 139
Thanks for reporting, should hopefully be fixed now
nice! thanks
Anyone know how mass is handled when not explicitly set ?
from the collider: https://docs.rs/avian3d/latest/avian3d/dynamics/rigid_body/struct.ColliderMassProperties.html
An automatically added component that contains the read-only mass properties of a Collider. The density used for computing the mass properties can be configured using the ColliderDensity component.
Thanks
https://docs.rs/avian3d/latest/avian3d/collision/struct.Collisions.html
Maybe this can help you.
A resource that stores all collision pairs.
Looking back at your original question and what is written in the docs.
You can probably create a CollisionWorld component with an id and attach this to your colliding entities.
Then retain only those collisions where both share the same CollisionWorld id in manual collision filtering.
ohhh that sounds like a plausible idea!
I got my force systems working with bevy_trait_query! My force components impl the Force trait. Each one gets updated in a system set just before the physics updates. In the prepare phase, a system gathers all components that implement Force sets the external force to the sum. I am approximating drag by using the bounding sphere as the thing making drag. Still working on a system that does differential drag based on the mesh. Some experiments showed it could work if I'm clever.
It's not much but it's there. I think I'm finally getting the hang of Bevy and Avian. Thanks yall for answering my noob questions lately. Next thing is to add force debug vector gizmos and attach a dangly tether to the bottom for fun
Hmm, weird why would i map a mouse to x.y if he already is 2d?
Hmm yours make more sense that way I always have the go to
that's juz leafwing semantics xd, u can juz think of movement as a Vec2 direction
@vestal minnow did "Block" come up as a name for a collision library before?
I don't think so
i was working on adding block and parry to the game and thought it'd be a good name xD
repel ๐ค
i mean, you could think of minecraft/building blocks which kinda also relate to collisions a lot better
if you wanna pair meme with avian then i'll have to think harder D:
nah I don't actually want that haha
"angry". it's a well known fact that angry avians like to collide into stuff
there are so many names that are super effective in that context xD
Fixed a scheduling issue in bevy_transform_interpolation btw, it was causing problems for camera following logic in Update
https://github.com/Jondolf/bevy_transform_interpolation/pull/5
It's pretty nice how Avian's new default scheduling setup (FixedPostUpdate) and this interpolation stuff simplify the camera ordering shenanigans you used to need for camera following logic
// Before
app.add_systems(
PostUpdate,
camera_follow_player
.after(PhysicsSet::Sync)
.before(TransformSystem::TransformPropagate),
);
// Now
app.add_systems(Update, camera_follow_player);
of course you could still use PostUpdate too for camera following, but either way you don't need to order things relative to physics
is it 0-lag though
define 0-lag, interpolation can never not be behind true positions
Or you mean the camera following? It shouldn't lag behind the rendered transforms of the entities
i mean if the game is at 60 fps, is that still the case?
If the fixed timestep matches the screen refresh rate then you're just running fixed update every frame, and the interpolation shouldn't have an effect
wasn't it 64 though
yes
just means that for some frames, it'll run fixed update twice or zero times, and when it's zero times, it should get interpolated
or no it should always run once or twice I think
I'm confusing myself, it's late
at 60 fps each frame is 16ms, so i really don't want any delay there ๐
i was planning on just not using interpolation for now, but if there's no cost then i'll have to try it
it's at least super easy to just try and see if it helps, just add the dep and plugin, and enable it for everything or for specific entities
Or for Avian 0.2 I'll add a PhysicsInterpolationPlugin or similar that just uses bevy_transform_interpolation and sets things up nicer for physics
It is really strange, but my game (with default PhysicsPlugins) always crashes after adding mesh colliders. This is my system for adding mesh collider (during Update stage):
pub fn add_mesh_colliders(
mut commands: Commands,
query: Query<
(Entity, &Handle<Mesh>),
(
With<RequireMeshCollider>,
Without<MeshColliderAdded>,
Without<MeshColliderError>,
),
>,
meshes: Res<Assets<Mesh>>,
) {
for (entity, mesh_handle) in query.iter() {
let Some(mesh) = meshes.get(mesh_handle) else {
continue;
};
let Some(collider) = Collider::convex_decomposition_from_mesh(mesh) else {
error!("Invalid collider mesh");
commands.entity(entity).insert(MeshColliderError);
continue;
};
debug!("Adding mesh collider");
commands
.entity(entity)
.insert((collider, RigidBody::Static, MeshColliderAdded));
}
}
And this is error message:
thread 'Compute Task Pool (7)' panicked at /home/artushak/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glam-0.27.0/src/f32/mat3.rs:458:9:
assertion failed: det != 0.0
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `avian3d::collision::collider::backend::update_collider_mass_properties<avian3d::collision::collider::parry::Collider>`!
Can it happen due to static rigid body entity having parent entities without any physics-related components?
Very interesting, adding capsule collider instead of the mesh one causes the same crash
Even when I simply spawn:
let cube_mesh = Capsule3dMeshBuilder::new(0.35, 1.1, 10, 10).build();
let collider = Collider::capsule(0.35, 1.5);
let cube_mesh_handle = meshes.add(cube_mesh);
commands.spawn((
PbrBundle {
mesh: cube_mesh_handle,
transform: Transform::from_xyz(0.0, 2.0, 10.0),
..default()
},
RigidBody::Static,
collider,
));
game crashes, but if I spawn
let cube_mesh = Capsule3dMeshBuilder::new(0.35, 1.1, 10, 10).build();
let collider = Collider::capsule(0.35, 1.5);
let cube_mesh_handle = meshes.add(cube_mesh);
commands.spawn((
PbrBundle {
mesh: cube_mesh_handle,
transform: Transform::from_xyz(0.0, 2.0, 10.0),
..default()
},
collider,
));
it does not
Hi!
Is there a way to find the closest collider to a point?
I'm trying to implement basic obstacle avoidance, but i don't want to just on random raycasts.
Hi, I am new to avian, is there any way to visually debug collisions et forces applied on rigid bodies ?
Here comes the minimal reproducible exampleโข:
use avian3d::prelude::*;
use bevy::{prelude::*, render::mesh::Capsule3dMeshBuilder};
pub fn test_spawn1(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut local_flag: Local<u8>,
) {
debug!("Local counter is {}", *local_flag);
if *local_flag == 128 {
debug!("Spawning debug capsule collider");
let cube_mesh = Capsule3dMeshBuilder::new(0.35, 1.1, 10, 10).build();
let collider = Collider::capsule(0.35, 1.5);
let cube_mesh_handle = meshes.add(cube_mesh);
commands.spawn((
PbrBundle {
mesh: cube_mesh_handle,
transform: Transform::from_xyz(0.0, 2.0, 10.0),
..default()
},
RigidBody::Static,
collider,
));
*local_flag += 1;
} else if *local_flag < 128 {
*local_flag += 1;
}
}
fn main() {
let mut app = App::new();
app.add_plugins(DefaultPlugins);
app.add_plugins(PhysicsPlugins::default());
app.add_systems(Startup, move |mut commands: Commands| {
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(0.0, 40.0, 0.0).looking_at(Vec3::ZERO, Vec3::Z),
..default()
});
});
app.add_systems(Update, test_spawn1);
app.run();
}
And, alas, it crashes.
Alright, I'll try to remove most of my dependencies and run this example again.
I have figured it out: the reason was this dependency in my game's Cargo.toml:
glam = { version = "^0.27.0", features = ["std", "glam-assert", "rand"] }
yeah the issue is most likely glam-assert in that case
it can panic for a ton of pretty small things
and physics code is quite math-heavy so it's not uncommon to hit those assertions
Yup, there is SpatialQuery::project_point
https://docs.rs/avian3d/0.1.2/avian3d/spatial_query/struct.SpatialQuery.html#method.project_point
A system parameter for performing spatial queries.
You can add the PhysicsDebugPlugin to enable debug rendering for physics. Collisions won't be visualized by default, but you can configure the PhysicsGizmos like this:
app.insert_gizmo_config(
PhysicsGizmos::default().with_contact_normal_color(foo_color),
GizmoConfig::default(),
);
IIRC the contact normal should be scaled by the contact force or impulse by default, and you can also adjust the scale using with_contact_normal_scale
Thx, I will try this!
hi, in which schedule shud I be checking for collisions?
https://github.com/Vrixyz/bevy_rapier/pull/28 fyi ; a (wip) proof of concept example to use bevy_transform_interpolation with bevy_rapier ; I'd love to strip interpolation-specific code from bevy_rapier and benefit from shared codebase ๐คฉ
Is it possible to make a capsule collider, but rotated by 90 degrees? I'm making a top-down view game, so my player entity points to the right by default. I could make it so that my character points up instead, but it will make the rotation logic in other systems more annoying.
Basically my situation:
Oh this works:
Collider::compound(vec![(
vec2(0.0, 0.0),
Rotation::degrees(90.0),
Collider::capsule(12.0, 24.0),
)])
Does it make sense to mutate Rotation directly for kinematic bodies? I need it to point to a specific angle, so AngularVelocity won't work for my case.
Sometimes my RevoluteJoint snap on the other side of the angle limits set by with_angle_limits, how can I prevent that ?
Alternatively try the capsule_endpoints constructor, it takes the points that make up the line at the center if you fully remove the radius, should be slightly faster as it's not a compound collider
Cool! I also just made a PR to add built-in physics interpolation support for Avian, powered by bevy_transform_interpolation
(also see #showcase message)
Worth noting that I have a PR ready for bevy_transform_interpolation that adds support for extrapolation and Hermite interpolation, renames some types, and reworks a bunch of docs. My PR for Avian uses that branch, but it can't be merged yet since it depends on a fix on Bevy's main branch that isn't in the RC
Thanks, I'll try that too.
Changing Rotation or Transform rotation is generally fine, but collisions with other objects while rotating might not work quite as well since the rotation won't be substepped, and CCD (continuous collision detection) also won't account for the rotational motion
If correct collision responses are desired, setting angular velocity so that it results in the desired rotation in a known amount of time (say 1 full tick) would be the way to go
Ok makes sense. Also, if you want to tween/animate kinematic rigid bodies (is this a good idea in the first place?), does it matter when the system runs? I'm currently using PostUpdate + .before(PhysicsSet::StepSimulation), but I'm not sure if this is right.
Anywhere before physics should be fine I think
If it runs after physics that's fine too, it just runs for the next frame ... As long as it doesn't run in the same schedule with no ordering relative to physics, since that would cause inconsistent ordering
Ok thanks for the advice!
Also, are these issues also relevant if you're just using kinematic bodies? Since they're not moved by the engine, I'd assume there'd be less potential issues.
Kinematic bodies are still moved by the velocity components like dynamic bodies, in the substepping loop. I believe they do also support sweep-based CCD (which is opt-in). They just don't react to any forces, collisions, or joints
Oh yeah forgot about that.
Oh and FYI a third approach would be to just make the collider a child entity, and rotate that by 90 degrees independently of the rest of the player. But yeah capsule_endpoints should be good
@vestal minnow A quick questioneriino is there a problem in changing rotation directly I know it is not supposed to be the go to, but do you think that is gonna cause some weird things to occur with a dynamic body.
#1124043933886976171 message
It's fine for some things, but for continuous rotation I would generally recommend changing velocity or applying a torque instead
you can always try it and see if you get problems for your use case, if not then it's probably fine
let target_rotation = Quat::from_euler(EulerRot::YXZ, camera_rotation.y, 0.0, 0.0);
let current_rotation = character.rotation.0;
let delta_quat = target_rotation * current_rotation.conjugate();
let (axis, angle) = delta_quat.to_axis_angle();
let angular_velocity = axis * (angle / time.delta_seconds());
if angle > 1e-5 {
// Avoid numerical instability for very small angles
character.angular_velocity.0 = angular_velocity;
} else {
return;
}``` is this how you would convert the difference between rotations into angular velocity?
but yeah as a general rule of thumb, use velocity or forces unless you explicitly want to "teleport" the body to a specific position/orientation
Yeah I noticed he sometimes just passed through floor
And then went up again
Thing is I cant balance out it is angular velocity, when I do via it.
It goes cucko
It works
But it goes cucko I wonder why
Is camera_rotation a quaternion? The y component isn't exactly an angle I think
It is a vec2 giving me the yaw and pitch from camera rotation
fn camera_rotate_to(
q_transform: Query<&Transform, With<MarkerMainCamera>>,
mut player_action_state: Query<&mut ActionState<PlayerAction>, With<Predicted>>,
) {
if let Ok(cam_transform) = q_transform.get_single() {
let (yaw, pitch, _) = cam_transform.rotation.to_euler(EulerRot::YXZ);
if let Ok(mut action_state) = player_action_state.get_single_mut() {
action_state.set_axis_pair(&PlayerAction::RotateToCamera, Vec2::new(pitch, yaw));
}
}
}```
This guy
right, makes sense
Agh I am guessing i would need a pid to ensure he stabilizes
Is there a way to turn off overlap warnings for kinematic bodies? I don't have any dynamic bodies in my game, so it's not an issue. It looks like that it still prints a warning even if you have attached a Sensor.
Ah, it looks like it was fixed: https://github.com/Jondolf/avian/commit/571dcc668a5fa27537a33c0d1810f42d41a39894, but missed the 0.1.2 window by 5 days ๐ฉ. Could it be backported, since most people is going to be stuck with 0.14 for a while?
Also, it looks like that this logging system is no longer a thing in main, or at least I can't find it. Was it just removed or replaced by something else?
It was removed, since it's not nearly as relevant in Avian as it was in bevy_xpbd, and I've only seen people be annoyed by the spam :P It's also pretty straightforward for users to add the warnings manually in app code if they want
https://github.com/Jondolf/avian/pull/547
I'm not sure if I want to make a cherry picked patch release this late in the cycle just to remove a warning ๐ค
if people really want it then I could, it's just pretty small and also technically removing existing behavior
Would really appreciate this if it's not too much churn ๐
I'll probably be stuck with 0.14 for like 1-2 months while waiting my plugins to update. I need to spawn a bunch of bodies really close together (bullethell-ish thing) and my console is basically constantly filled with the warnings.
It seems that ConvexHullFromMesh doesn't do any sort of internal caching of a generated collider for a Mesh, meaning that it seems to be recalculating the collider for each copy of that mesh that I add. Is that right ? If so, how can I cache the generated colliders in a nice way ?
Hmm, I don't think there's a very nice way to do this with automatic collider generation right now ๐ค
If you can generate one Collider in some way, you can just clone that without cloning the actual data, since internally it stores an Arc<dyn Shape> which is cheap to clone.
You could create the collider manually with Collider::convex_hull_from_mesh, you just need access to the Mesh for that
hey folks, i think i have a silly question, but i don't know how to proceed. in my game there's a Dir3 that keeps getting denormalized over time - it starts with length 1 and keeps increasing until it panics within a few seconds. here are the last log entries. any ideas how to best debug something like this?
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 1.0099094.
0: bevy_ecs::system::function_system::system
with name="avian3d::spatial_query::update_ray_caster_positions"
at /Users/mario/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.0-rc.3/src/system/function_system.rs:65
thread 'main' panicked at /Users/mario/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_math-0.15.0-rc.3/src/direction.rs:63:9:
Error: The vector given to `Dir3::new_unchecked` is not normalized. The length is 1.0099764.
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `avian3d::spatial_query::update_ray_caster_positions`!
Encountered a panic in system `avian3d::schedule::run_physics_schedule`!
Encountered a panic in system `bevy_app::main_schedule::FixedMain::run_fixed_main`!
Encountered a panic in system `bevy_time::fixed::run_fixed_main_schedule`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
or should I post it in another channel? ๐ถ
Oh boy
That means messing with loading events and stuff
Any idea on how to streamline this so it's more convenient for users ?
Maybe the component could include a cache_name: Option<String> field that will store it in a Resource CachedColliders(HashMap<String, Collider>), then subsequent calls with the same cache_name can check that resource for a collider if there is one, and use that ?
I'm not convinced of my design pattern, but just a basic idea of how something like that could work ?
We've had the idea of "colliders as assets" for larger shapes like trimeshes and convex polyhedra, and using asset preprocessing to generate colliders for scenes at build-time to reduce startup times. Then you could just pass those collider asset handles around. Afaik there are still some blockers here though, and Bevy's asset preprocessing functionality is pretty half-baked, so it probably isn't very viable just yet
Something like this could probably work
I've seen this a couple of times but haven't been able to reproduce it properly
Is the RayCaster on a dynamic or kinematic rigid body? Or something else
its a kinematic body
It should be normalizing rotation every frame for kinematic bodies too so I'm not sure why it'd become denormalized over time
(btw the panic should only happen with debug_assertions enabled, so it shouldn't happen in release mode at least)
i cant debug the assertion in new_unchecked, but i could clone the source and insert an if and set a breakpoint ๐ค i will give it a try
You can also set up a rule to just hide the warning I think ๐ค
Just for the overlap warning? Not really seeing anything, at least in 0.1.2. It's only gated behind debug_assertions.
I think I've seen other people disable it trough a rule on bevy's LogPlugin
Hi, I'll ask again with more details. I have been trying to make landing legs for my spaceship, currently the code for them looks like this :
let leg_normal = position.cross(Vec3::Y).normalize();
let leg_entity = parent.spawn((
PbrBundle {
transform: Transform {
translation: position,
rotation: Quat::from_axis_angle(leg_normal, 0.5),
..default()
},
mesh: meshes.add(Cylinder::new(0.15, 1.0)),
material: materials.add(Color::WHITE),
..default()
},
LandingLeg,
Collider::cylinder(0.15, 1.0),
CollisionMargin(0.2),
RigidBody::Dynamic,
ExternalTorque::new(-2.0 * leg_normal),
SweptCcd::default()
)).id();
parent.spawn(RevoluteJoint::new(ship_entity, leg_entity)
.with_aligned_axis(leg_normal)
.with_angular_velocity_damping(0.5)
.with_angle_limits(0.2, 0.6)
.with_local_anchor_1(position)
.with_local_anchor_2(Vec3::Y * 0.5)
);
They have a RevoluteJoint that link them to the ship with angle limits and external torque to act like a spring that put them back in position
However, when they hit something, they go off the limits (below 0.2 and above 0.6) as you can see here :
.
Hmm, hard to tell ๐ค It kinda looks like the joint stiffness is too low, but I don't think that should be an issue here
I did find one bug related to joint limits recently, which could maybe be related, not sure. That one should be fixed on the main branch
I will try to rebuild with the main branch and update you about that
Also, ive seen this issue that is similar : https://github.com/Jondolf/avian/issues/553
The workaround is kind of working but it makes my ship shaking
I'm trying to work on finishing the mass rework again, it's such a pain
give me back my Jacobians and Lagrange multipliers 
Current issue is that idk how I would detect if the components were added manually or through required components
i.e. in this case
RigidBody+Collider+Mass(5.0)
the manually specified mass should probably override the initial value
but if Mass isn't provided, it should be computed from the collider
but Mass is required for RigidBody, so it exists in both cases
Seems like you should make mass an enum with an Auto variant, and have a system that calculates the value for components set to Auto.
Much like Val::Px vs Val::Auto
Yeah I kinda had something like that at one point, I've gone through a billion designs
You could even have a private ComputedMass component
I also had that design :P
Otherwise I donโt think it should be required
The current design idea is roughly this, after several iterations
https://github.com/Jondolf/avian/discussions/499#discussioncomment-10922998
I don't really want a "manual mass vs. computed mass" split, or enums
I'm largely going for how Box2D's mass properties work, but in an ECS context with a bit more flexibility
I.e.
- Mass is established from attached colliders based on their densities by default
- Adding, removing, and modifying colliders affects the body's mass properties
- Mass properties can be set manually at runtime
- Automatic mass computation can be explicitly disabled (with marker components)
And in our case also - If a collider entity has
Mass,AngularInertia, orCenterOfMassspecified at spawn, they override the initial values - A
MassHelpersystem param can be used to do mass computations and updates that require access to hierarchies or several different components
would it be easier if you did not use required components and instead used a builder?
that way, you would know which components the user has provided and which they want computed
I don't see how a builder would necessarily help, I think the same could be done by not having the mass components be required components and just checking if they were added
Just semantically, Mass should 1000% be a required component for dynamic rigid bodies
(not necessarily for static or kinematic)
there's a proposal to give the custom constructor access to the components that require it
fair enough. it just sounded above like you were having trouble checking whether they were added manually
so if A requires B, it can give it a constructor fn(A) -> B
I'd like if Ref<Mass> had an .is_explicit_component() method
go review that pr i guess
i.e. "not inserted as required component"
that information is already stored in the bundle info
but not exposed for the component
I'll look into adding that
Do you have a link? I can't seem to find it
Or do you mean this? #general message
I think that'd mainly be useful for me if it can return None to skip insertion depending on some predicate
which might be contentious
Is it possible to run avian3d on a headless server app? When I add minimal plugins I get complaints that avian collision collider need mesh resource from bevy_render
https://github.com/Jondolf/avian/issues/505
Sounds like this issue. Does the change I commented on this issue solve it?
This is exactly the problem Iโm encountering. I do think your comment is gonna solve my issue. Iโll report back when Iโve tried it
@vestal minnow I debugged it. It always happens here: https://github.com/Jondolf/avian/blob/f951ed38ed4e03d00b61d772ae21b8c953dd5ba3/src/spatial_query/mod.rs#L273
The rotation Quaternion keeps getting denormalized over time until it crashes. Any clue why it happens? ๐ค I don't exactly understand whats going on in this function with the global und parent stuff, right now.
thank you, this fixed it!
Is there a provided method to apply an impulse to the Ancestor of Colliders, and have that propogate sensibly through the Hierarchy ?
Or just some way of determining the "primary" rigidbody in a hierarchy or something ?
Basically it's just really awkward to apply an impulse to an object in my scene :/
How do I maintain a non-collider Entity's Transform constant relative to another Collider Entity's Transform ?
I fixed it. I used to update the rotation in the Update schedule by setting the Transform componenent. I thought they will be in sync after one frame. However, now I also update the Rotation component and it works. I have some strange behavior with my character since updating to the main branch of avian (and bevy 0.15-rc.3). Do we have a changelog or migration guide or something for avian? It would be cool to review the changes for possible incompatibilities with my code.
These are probably the biggest breaking changes so far in this cycle, the PR descriptions should have migration guides.
https://github.com/Jondolf/avian/pulls?q=is%3Apr+is%3Aclosed+merged%3A>2024-08-09+label%3AC-Breaking-Change+
For the actual release I will write a proper migration guide, and a blog post covering the changes, like I did for 0.1 (see the GitHub release and blog post)
I'm not sure what you mean by propagating impulses ๐ค Impulses are only for dynamic rigid bodies, they need to take mass into account
You can apply an impulse to the rigid body entity with the ExternalImpulse component
I intend to rework the force and impulse API at some point though, I'm not entirely satisfied with it
What do you mean by primary rigid body?
You generally shouldn't nest rigid bodies in hierarchies
Well it's like for example a car that has a parent entity, then all of its rigid bodies as children. The parent thing doesn't have a rigid body
I don't know how best to deal with that kind of situation. Maybe I have a marker component. But I'm importing a car from Blender, so it means some modifying of the loaded scene to give it a marker component. idk, i'm just not sure what to do
Do you need them to be separate rigid bodies? Typically if you load a model from Blender like that, you'd have just one rigid body with several child colliders
Oh I didn't know that
So parent car container entity would be a rigid body, then children of it would just be colliders, but not rigid bodies ?
If you want stuff like physically simulated wheels attached to the car with joints, they'd need to be separate rigid bodies since they're simulated separately, but if you want just one physics object with many shapes rigidly attached to it, then yeah they'd just be child collider entities
There's also the ColliderConstructorHierarchy component for automatically generating colliders for child entities in a scene, but that of course doesn't have the caching thing either if you had many instances of the same scene
So the issue I have now is that I'm getting warnings about it having no mass
Cus the Entity with the RigidBody doesn't have a collider itself. The children have colliders and mass, but it doesn't seem be getting respected ?
It should have mass, but not before the scene is loaded and the colliders are actually inserted. The warning is just sent before this, though it probably should be changed to wait somehow
Hmm, that's strange
Might be something to do with the order that things are getting added
idk
Cus maybe im adding things later than expected because I'm caching stuff first, idk
You should probably use ColliderDensity for the collider, and not use MassPropertiesBundle there
Okay
How does that work if MassPropertiesBundle::new_computed(&collider, 5.), needs to be pre-computed ?
I think the way it currently works is that the components in MassPropertiesBundle only work for rigid bodies, and do nothing on a standalone collider entity. Colliders use ColliderMassProperties instead, and that is computed at runtime based on the shape and ColliderDensity. The Mass of the rigid body is the sum of the masses of all attached colliders
Afaik you can't really precompute mass properties for colliders currently
Gotcha
The way mass works currently is confusing and kinda footgunny, which is why I've been working on trying to redesign it
With my new designs I think your code would work, i.e. you can set the mass of a collider with MassPropertiesBundle or its individual components
No problem I don't really mind either way atm - I just couldn't get it to work cus I didn't understand. ColliderDensity worked for me, thanks
How does Friction behave ? Does friction need to be in Entities with Collider ? Or can I have them in just the parent Entity (with the RigidBody) ?
Currently you can have it just on the rigid body and it'll be used for all attached colliders, unless they have their own Friction explicitly specified
do heightfield colliders always have to be square?
when I try to add less rows than columns it doesn't look like I expect
this looks right
but if I remove a row it looks like it expects the missing row to be there
Will collision reporting become triggers one day? I wonder what's the overhead of just running commands.trigger on every collision by default.
Remember me? It was a bug, for some reason the ignore_origin_penetration did not work, I filtered out the entity at the beginning, now it works fine.
More context: I cast_shape to query for hits along the velocity to implement the collide_and_slide. I checked the source code of vidar - awesome thanks again! - and I copied the part that filters out the entity itself, now it does not collide with itself. All the math checks out so it is a bug in Avian itself.
Greetings. Thanks for the great crate. I noticed when I clone the repo and run the examples they are locked to 144 hz. However, if I copy and paste the example into a new project it is NOT locked to any framerate. Can you share how you were able to lock the framerate? Cheers.
I think inserting resource like this should fix it when you build the bevy app:
app.insert_resource(Time::new_with(Physics::fixed_once_hz(FIXED_TIMESTEP_HZ)));
Actually nvm donโt think thatโs it
You can try it
Also donโt think avian physics is related to frame rate itself, you can just define how many times physics run per frame. Fixed frame rate is set by the schedulerunner.
Like this:
App::new()
.add_plugins(
DefaultPlugins
.set(ScheduleRunnerPlugin::run_loop(Duration::from_secs_f64(
1.0 / 60.0,
)))```
Hmm I think this is a bug, I made a PR with a fix here
It's kinda confusing though, I'm not 100% sure if the inner vectors should represent rows or columns. It's mainly a matter of choice
I think Glam's matrices use a column-major order, and input vectors are the columns, even though visually they look like rows when laid out table-like
But especially for heightfields, that representation might just be confusing
There will be some form of per-entity collision event listeners, either with observers, or with some custom component that registers a one-shot system and runs that.
I've tried the observer route a couple of times, but I'd like the events to be opt-in at the entity-level, and I don't really want the observer events to be sent globally (the buffered events already exist for that) so I haven't been entirely satisfied with that approach
I don't think the examples do anything special here, most of them are just using DefaultPlugins with the default configuration. FPS should be capped to the display refresh rate with PresentMode::Fifo (configurable through the primary_window of WindowPlugin), and that is the default for apps
For example I'm currently on a 60 Hz monitor, and the examples are capped to 60 FPS for me
Bevy version mismatch?
whats supposed to be the bevy version
0.14
yeah its 0.14
If you're using Avian 0.1 and not the main branch, then yeah 0.14
so i still have that error
any other dependencies that could be using a different Bevy version?
might also want to run cargo update and/or cargo clean just in case if not
Also on the bevy screen it just shows all black, are all collider shapes automatically colored black?
colliders aren't rendered unless you have debug rendering for physics enabled
how do you enable this
for a game you'd use meshes and/or sprites to render your entities, but if you specifically want physics debug rendering, you can add the PhysicsDebugPlugin
A plugin that renders physics objects and properties for debugging purposes. It is not enabled by default and must be added manually.
gosh the error is bothering me
i have no idea why its acting like that
it's really frustrating because errors like these pop up, then i'd have to make a whole bug report about it with the chance of being ignored by Jetbrains teams because it's not a severe issue, it would've been nicer for RustRover to not be closed source so it'd be easier to contribute through there to fix stupid errors like these which would be ignored anyway
If the game compiles and runs fine but you still get the error in your editor, you might need to restart Rust Analyzer? (or that looks like RustRover, iirc it has its own thing)
yeah i restarted everything, nothing works
hmm I'm not sure then, I haven't used RustRover so I can't help there unfortunately
Okay I have yet another revised version of the mass rework proposal, separating Mass and ComputedMass. I was against it at one point, but I think it does make things much simpler and allows the user-facing API and overall behavior to be nicer.
https://github.com/Jondolf/avian/discussions/499#discussioncomment-11410922
I think the public api component / private computed components is going to be an increasingly common pattern.
and I don't really want the observer events to be sent globally
fwiw, this is howbevy_pickingis implemented right now. The pointer event is triggered usingcommands.trigger_targetsfor the affected entities, then cloned and sent to the normal event writer.
Is there any situation in which changing the translation of an entity won't move it in Avian?
fn threat_collector_follow_system(
character_query: Query<(&ThreatCollector, &Target, &Transform)>,
mut threat_collector_query: Query<&mut Transform, Without<ThreatCollector>>,
) {
for (threat_collector, target, character_transform) in character_query.iter() {
if let Ok(mut threat_collector_transform) = threat_collector_query.get_mut(threat_collector.0) {
let direction = (target.0 - character_transform.translation).normalize_or_zero();
println!("pos before: {:?}", threat_collector_transform.translation);
threat_collector_transform.translation = target.0; //threat_collector_transform.translation + direction * 10.0;
println!("pos after : {:?}", threat_collector_transform.translation);
continue;
}
}
}
The translation changes, and the ThreatCollector has the correct entity reference.
let threat_detector = commands.spawn((
Collider::cylinder(10.0, 10.0),
Transform::default(),
ThreatCollectorOwner(player_id),
Sensor,
CollisionLayers::new([Layer::Sensor], [Layer::Character]),
OwnerBundle::new(),
)).id();
... the threat collector if that helps.
Hmm, I might just make a minimal 0.15 migration release tomorrow, and do the full feature release (0.3 I guess?) in a week or two. I really want to land the mass property rework properly, and need some more time to finish it, clean up and merge a few other open PRs, and do all the release prep
Make sure you have a GlobalTransform too. In Bevy 0.15 it's required by Transform, so it should get added automatically, but not in 0.14
This just becomes messy and I'd need to redo the core 0.15 migration to not have the new stuff :/
I'd also like to just call the new release 0.2 and not do a tiny release followed by a huge 0.3
I could also just have a bevy-0.15 branch with the minimal migration path and not do a crates.io release before the full release, idk
is this zed?
RustRover
what's the rush? folks that can't wait for the proper release can use main
@vestal minnow Mr Jondolf question, besides sleeping is there any other state based logic envolving components?
I'm building a boid system in my game that already uses Avian and I'm curious if it's even worth building a specialized spatial partitioning system? I don't know how physics works but I assume there's some sort of spatial partitioning going on to avoid unnecessary collision checks. If that's the case, couldn't I just do a sphere cast for anything on with "Layer::Boid"?
I feel like this is the exact problem a physics engine solves but maybe I'm missing something
yeah, that's something it should solve