#Avian Physics
1 messages Ā· Page 46 of 1
So I think that's a bug with 2D picking in general, or an unexpected behavior if it isn't a bug (I could imagine that the point query has a tolerance, but I can't find evidence of that)
From what I'm reading, it looks like a spatial query (specifically SpatialQuery::point_intersections_callback) is documented to find all entities with a collider that contains the given point, but that delegates to the BVH, which as far as I can tell only checks the AABBs in the tree and never checks intersection with the actual collider. I could be wrong on this; I'm still very new to the codebase, but I don't see a direct point-against-collider check anywhere in the call tree starting from the spatial query.
@vestal minnow These are my findings. Let me know if there's any other way I can help, including making a PR (and what the PR should do; is the documentation wrong, or is the code wrong? or are neither wrong and i'm misreading something š)
If you want to try what I have out, I have a branch on my fork with the example shown in the video: https://github.com/rdrpenguin04/avian/blob/rdr-2d-in-perspective-picking/crates/avian2d/examples/picking_2d_in_perspective.rs as well as my other change to the picking plugin
Ah, yeah that's definitely a regression. Pushed a fix here
https://github.com/avianphysics/avian/pull/961
Seems like it works when using both my fix and your perspective fix!
I would appreciate a PR with the perspective fix in src/picking/mod.rs
We can add the example too if you want, no strong opinion there
PR has been submitted š https://github.com/avianphysics/avian/pull/962
Objective
Allow using perspective cameras with the 2D physics plugin
Solution
Follow the ray that bevy_picking gives to its intersection with the Z axis rather than truncating the value to 2D
Testi...
Thanks! I'll review and merge later today, and make a 0.6.1 patch release with this (and some other fixes) tomorrow
Awesome! š
Is this issue on anyone's radar? š„ŗ https://github.com/avianphysics/avian/issues/946
Problem When building games where projectiles are used to destroy objects, it is common to despawn both the projectile and the hit object on collision. Using version 0.6.0, this leads to a crash. S...
Ohh sorry I think I missed that one or forgot about it! It looks like the same problem as the very recent issue:
https://github.com/avianphysics/avian/issues/957
If it is that, it should be fixed on the main branch already
And will be fixed in the upcoming patch release
It actually is fixed š thank you!
Closed the issue ā
damn you went down a rabbit hole glad y'all were able to figure it out haha
i really like how this turned out due to me using avian. Raising and lowering the gates using distance joints makes the movement look really really good
the little shake when it reaches the top and botton positions are just wonderful
(this is a model of a furnace I have worked with in real life, and the gates there do the exact same shakes, which is really nice to be able to model with just three ropes and a system)
don't mean to get too off topic for the thread, but your job looks kinda terrifying lol
how tall are those doors in real life?
like 2m tall maybe? A bit taller than me at least
the scale is very off in the model right now
also this is a furnace, which is why I'm using a scary red glow lol
based on a 40mw submerged arc furnace
a physics debug view if anyone's curious (distance joints on the gates, prismatic joints on the rods)
Alright, my use case is getting more and more... funny.
I'm switching to basically precisely imitating SSBM's Environment Collision Box model. This means that I have four points that move with the character, changing position depending on the animation. These four points in SSBM always formed a kite, but they can generally be any quadrilateral (I don't think being a kite was necessary for any particular logic). I presently use MoveAndSlide, which takes a Collider as input and sweeps it along its velocity vector, making any adjustments to velocity necessary along the way. ... But now I have four colliders.
This gives me three questions:
- What's the most idiomatic way to make a point collider? I could do
circle(0.0),rectangle(0.0, 0.0),segment(vec2(0.0, 0.0), vec2(0.0, 0.0)), or a number of other things; which one is subjectively cleanest and/or objectively fastest? - Can you make a compound collider where you can independently transform the individual parts? I could believe the answer to be no just because this would require a lot of AABB calculation, and it also just wouldn't work well with
MoveAndSlideanyway; teleportation in physics engines is bad. Which leads me to... - What's a good way to make the
MoveAndSlidealgorithm work with a set of several colliders? A more sane usecase than mine would be move-and-slide-ing a character with a swishing tail or bulky arms or something like that which should push against the geometry.
Lmk if I'm not helping, but why not just use a convex polyline with 4 points? You end up with just one collider so that resolves point #3 and #1, and you aren't dealing with "infinitely thin" colliders and are therefore less likely to have weird issues with characters getting stuck on other infinitely thin surfaces like concave polygons. I know you'd be altering the collider with every state change, to which I say again, AABB/BVH recalcs aren't THAT expensive, they're O(n) or better. So unless you have thousands of characters I wouldn't worry about it and follow the old idiom of profile first optimize second.
Point #2 is still unresolved- Having dealt with a similar but unrelated issue (implementing an HL2 style gravity gun where holding an object adds a physics exception between the holder and the object, which means you can "teleport" it into yourself by picking it up moving it into you and dropping it), you may need to use SpatialQuery to depenetrate your character when their collider changes manually. Though maybe test with MoveAndSlide first, it has two depen steps, I just don't know if they handle colliders that are already penetrating when the step begins.
The biggest problem I think is that I need to edit the collider in realtime, which... there doesn't seem to exist a way to do so without creating a fresh collider for each change
Like, even using SharedShape directly only gives me an Arc, and it looks like the code expects no interior mutability, so the best I can do to change the collider is to just make an entirely new collider, which feels significantly worse
(plus, the MoveAndSlide algorithm then has no clue what happened, and then you're right, I'd need to depenetrate manually, which sounds not-fun to do; at that point I may as well make my own move and slide impl because the collider will sometimes be changine frame to frame)
Making your own move and slide isn't that hard, also have done that before. The nice thing is you can just look at the source code of the existing implementation and tweak the parts you need to
I mean, I know it seems really inefficient but have you tried it? I feel like I keep smashing the "premature optimization is the root of all evil" button but I would be shocked if you came anywhere close to dropping a frame. I've generated like, 64^3 colliders in 400ms in Godot before with GDScript without dropping a frame. I bet Avian will handle it lol
That's fair; it also just doesn't seem like the right solution intuitively, which is why I'm trying to find another answer
I can see that. Well, I'll shut my yapper and leave room for someone else to make suggestions lol
You're good š
try cargo update
yeah š thats what worked
What's the most idiomatic way to make a point collider?
Probably a tiny circle/sphere
Can you make a compound collider where you can independently transform the individual parts?
Yeah,Collider::compoundtakes a vec of shapes and their positions and rotations, or alternatively you can just add the colliders as child entities and give them differentTransforms
What's a good way to make the
MoveAndSlidealgorithm work with a set of several colliders?
This would require usingCollider::compoundsince it needs one shape (even if it consists of multiple sub-shapes) to use for the shape casts and contact queries
In general though, changing colliders dynamically is kinda wonky and probably won't give very good results since it can make you suddenly clip into geometry with the new shape etc.
You can use a different hitbox and hurtbox every frame and during animation, but changing the actual collider that collides with the environment feels a bit sketchier
But it should probably be fine if you really need it
Alright; I'll let you know what happens!
I think there was an undocumented change w collider scaling last update, a collider that scaled with transform before no longer does so
soo i want to cast a ray with the spacialquery cast_ray and i want to exclude the entity that "is casting the ray"
do I query for the entity or is there some way to fetch this entity from its attstched components?
How is your system determining where to cast the ray from? If you have a query reading something like &GlobalTransform for it, you can add Entity to the QueryData to
https://codeberg.org/gobbe/brumm/src/branch/main/src/bil.rs exact code here (raycast at line 136)
either way it querys for the wheel entity and then sends a ray from entities global position
downwards
has anyone else run into this panic?
thread 'main' (504637) panicked at avian/crates/avian3d/../../src/data_structures/stable_vec.rs:334:13:
no element at index 5 in StableVec::index_mut
It started for me on 17d868e1 BVH Broad Phase and Collider Trees (#927)
the release I just published fixes one known BVH crash, but that one might be different
ah, let me try that
most likely different, the fixed one is a None unwrap after spawning/despawning entities in a collision event observer
though I guess there could be other ways it manifests too
it didn't fix it.. but I think it's related to despawning an entity
Encountered a panic in system
avian3d::collider_tree::update::update_moved_collider_aabbs<avian3d::collision::collider::parry::Collider>!
Encountered a panic in systemavian3d::schedule::run_physics_schedule!
Encountered a panic in systembevy_app::main_schedule::FixedMain::run_fixed_main!
Encountered a panic in systembevy_time::fixed::run_fixed_main_schedule!
Encountered a panic in systembevy_app::main_schedule::Main::run_main!
I rewrote this
https://github.com/avianphysics/avian/blob/v0.6.1/src/collider_tree/update.rs#L996
to be this so it just checks instead
let trailing_zeros = bits.trailing_zeros();
let proxy_id = ProxyId::new(i as u32 * 64 + trailing_zeros);
if let Some(proxy) = tree.proxies.get_mut(proxy_id.index()) {
let entity = proxy.collider;
if let Ok(enlarged_aabb) = aabbs.get(entity) {
// Update the proxy's AABB.
update_proxy_fn(tree, proxy_id, Aabb::from(enlarged_aabb.get()));
// Record the moved proxy.
let proxy_key = ColliderTreeProxyKey::new(proxy_id, tree_type);
if moved_proxies.insert(proxy_key) {
tree.moved_proxies.push(proxy_id);
}
}
};
// Clear the least significant set bit
bits &= bits - 1;
and that stops the panic for me... I think it's like.. the proxy is set for the entity, and then the entity despawns and then it breaks here
I'm not sure if the above is necessarily a fix.. this prevents the panic and can get my game running, but it seems like collisions aren't always being detected š¤
Hi guys
I have a crush on this line :
let proxy2 = tree.get_proxy(proxy_id2).unwrap();
on ..\avian3d-0.6.0\src\collision\broad_phase\bvh_broad_phase.rs
anyone have this issue?
the erreur is :
21:33:30 [windows] called `Option::unwrap()` on a `None` value
21:33:30 [windows] stack backtrace:
21:33:30 [windows] note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
21:33:30 [windows] Encountered a panic in system `avian3d::collision::broad_phase::bvh_broad_phase::collect_collision_pairs<()>`!
21:33:30 [windows] Encountered a panic in system `avian3d::schedule::run_physics_schedule`!
21:33:30 [windows] Encountered a panic in system `bevy_app::main_schedule::FixedMain::run_fixed_main`!
21:33:30 [windows] Encountered a panic in system `bevy_time::fixed::run_fixed_main_schedule`!
21:33:30 [windows] Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
21:33:30 [dev] Application [windows] exited with error: exit code: 101```
Try updating to 0.6.1; there were a couple of crashes fixed
Is the ColliderDensity component always guaranteed to be present on a valid collider?
that is, if I spawn a collider as a child of a rigidbody, will it have the ColliderDensity component with a value of 1.0 inserted by default, or do I have to account for this and query for Option<ColliderDensity>?
I will but tomorrow š
Source of the Rust file src/collision/collider/parry/mod.rs.
woah, that's the most concise answer I've received in quite a long time
appreciate it hahaha
thanks
ā¤ļø
o7
it's fine now no crush register, Thanks
is there a way to get the entity from MoveAndSlide::intersections? It seems like it only returns physical information about the hit (normal, position, some other more niche but useful stuff) but not what actual entity it's currently talking about having found. It would be useful for the controller I'm writing to get both pieces of information from this API (I'm using it to check grounding)
by default does SpacialQuery.cast_ray() only include objects with a rigidbody and a collider or is a mere mesh + transform enough?
definitely doesn't pay attention to Mesh
Needs at least a collider, and there probably needs to be a rigidbody in either the same entity as the collider or an ancestor
does shapecasting work with voxel colliders?
If I remember correctly it should only need a collider, since the cast apparently can also hit sensors (forgot to reply @heady oasis)
yes but voxels don't support other non-convex or compound shapes, that's a limitation on Parry's side
gotcha, that should be fine for me, just trying to debug an issue with my tank shapecasting not getting the correct points to push off of
that might be worth mentioning in the docs though
I remember seeing something about that in the rapier/parry release
actually does not also not work against other voxel colliders too?
since they are non-convex
I'll test it
I think that should work but not 100% sure
main confusion to me is what these yellow spheres and arrows are doin over here lol
ok ya the difference between hit.point1/point2 are pretty big for some reason
odd
Is there a way to snapshot some of the physics environment and query it in background threads / bevy tasks? im aware the intersections and cast results would be stale but in my context thats acceptable.
Usual disclaimer: I'm not an Avian expert just tossing some ideas out there
I imagine because Avian is designed to use the ECS "as much as possible," the way to do this is to query whatever entities you care about in a system on a timer and clone them off to a separate sub-app or similar structure, and do whatever computation you need to do on that subapp.
Yeah, but afaict id have to provide my own broad and narrow phase solution.
I... Believe subapps have their own set of plugins
tbh i didnt consider a subapp, just jumped to bevy tasks.
It might be a bit janky, I know the maintainers are still discussing a successor to subapps as a multiple worlds approach so documentation might be sparse
But yeah maybe a subapp with the Avian plugin loaded and you just clone over whatever entities you need to that subapp?
It's more manual work than like, Jolt's snapshot function where it'll just archive the world state and any deltas for you
Which is what I'm guessing you're looking for
yeah that sounds like what im after
is there a better way to have a controller using MoveAndSlide collide with entities it bumps into? Currently I'm applying a slightly larger "real" collider to the entity than is used for the move & slide so that it will slightly clip in and collide
the KCC examples in the repo have a basic implementation for it, it's basically the same as what bevy_ahoy does
https://github.com/avianphysics/avian/blob/25db6df55aaa1fa460b005d3ee2f341cbf10b918/crates/avian3d/examples/kinematic_character_3d/plugin.rs#L456
however it's certainly not perfect, the current version often makes tiny objects fly away
to be clear i don't just want to apply forces, I mean for CollisionStart events to fire. It's fine if it doesn't inherently apply forces
ah
no good way currently apart from manually triggering the events
or a larger "real" collider like you're doing
definitely think there is a slight bug with the voxel collider shapecasting, I'll try to make a minimal repro at some point but it might be on the parry level
its completely work-aroundable, but my guess is the 2nd hit point is on a single voxel that isn't being translated to its actual position in the voxel collider
Hi, Iām new to Avian and Iāve run into a couple of issues that might be bugsāor possibly just gaps in my understanding.
First, I noticed that when an entity does not have a Transform component, the Colliderās AABB seems to shrink to an extremely small size. This causes raycasting to behave incorrectly.
Second, when there is no Transform component, the PhysicsDebugPlugin also fails to render the collider. Iām not sure whether this is because the collider becomes too small to visualize, or if the debug rendering system explicitly depends on Transform.
I would also like to kindly request that Avian be updated to support the Bevy 0.19-dev branch. Since this branch has just merged BSN, Iām very excited about it and canāt wait to start using it.ort the Bevy 0.19-dev branch. Since this branch has just merged BSN, Iām very excited about it and canāt wait to start using it.
Thanks!
I believe Avian as a whole relies on the Transform component existing; it gets copied to the Avian-specific translation and rotation components, sure, but I believe Transform is still required to exist
Adding a Transform::default() should help; maybe Transform should be added as a required component?
I understand that Avian already provides its own components for position, rotation, and so on, so Iām confused about why it still depends on Transform.
In my project, many entities are intentionally designed without Transform, which is how I ran into this issue. As a temporary workaround, I added Transform components to those entities, and it fixed the problemābut it feels unsatisfactory.
Directly modifying Avianās Position and related components works fine. The only remaining issue now seems to be the dependency of scale on the Transform component.
Definitely shouldn't depend on Transform for the core simulation, unless there has been some recent regression there
We have a bunch of tests that only use Position and Rotation and work fine
But I'll test once I get home
Scale and entity hierarchies might not fully work without transforms but otherwise it should be fine afaik
Yes, thatās exactly the issue I ran into the scale doesnāt work.
Yeah, simulation and debug rendering without Transform definitely works
just scale doesn't
I would also like to kindly request that Avian be updated to support the Bevy 0.19-dev branch
There will be an Avian 0.7-rc release when Bevy's own 0.19 release candidate comes out (some time within a week probably?). I believe @untold peak has a local 0.19 branch for Avian already, which will probably be up fairly soon
i am working on this now yes
I intend to also experiment with some collider Template stuff once it's out
@vestal minnow how do you handle bevy_heavy and bevy_transform_interpolation
for your version upgrades
update them with a bevy version bump
and bump the 0.X.0 version of the crate
I tested the following code,I just confirmed that when I remove the Transform component, my raycasting fails and nothing is drawn.
WITHIN A WEEK???
whoa, i really need to return to bevy again
ye i've forked them as well
i'll get them all PRd shortly
just fyi, they will be tracking bevy main
as i needed to in order to get jackdaw to compile with the avian deps
but hopefully the breaking changes will all be resolved for avian, and you just need to change to 0.19.0 once it's cut
Oh, my mistake. I customized a plugin and disabled some features I didnāt need. But I donāt think what I disabled would affect scale, right?"
I found the problem: I had disabled the PhysicsTransformPlugin because I didnāt have a Transform and didnāt need to sync data, and thatās when this issue occurred.
should have a bunch of pr's coming now @vestal minnow
i've set it to track bevy main on the main branches of the subcrates, just shout if you would prefer to leave individual bevy tags
I think I'll merge them once 0.19-rc is out if that's fine (assuming that happens relatively soon), in the meanwhile it's fine to track bevy main
i could setup bevy-main branches on each if you like
ok yea that's fine, i can just point my local avian integration in jackdaw to my forks
When generating collision from mesh, is there a way to reduce resolution of the collision? I have a very dense mesh and I definitely doesn't need such dense collision from it
You could downres the mesh first or you could try convex_decomposition_from_mesh_with_config, Iām not sure exactly how all the params work but resolution is probably a good start
Hereās an example of using convex decomposition to reduce hull complexity from the vhacd repo, theyāve got a description of all the params on their readme https://github.com/Unity-Technologies/VHACD#parameters
Does it work with open meshes? Like Planes, chunks, parts of the terrain etc?
Not sure! Youāll have to try it. I think avian treats faces in open meshes as thin and double sided but Iām not at my laptop so I canāt check
Ok, thanks
Seems like it worked on the flat surfaces
But its not exactly what I need. These are the params I used:
let vertices: Vec<Vec3> = buffer
.positions
.iter()
.copied()
.map(Vec3::from_array)
.collect();
let indices: Vec<[u32; 3]> = buffer
.indices
.chunks_exact(3)
.map(|tri| [tri[0], tri[1], tri[2]])
.collect();
let params = VhacdParameters {
resolution: 32,
max_convex_hulls: 8,
plane_downsampling: 8,
convex_hull_downsampling: 8,
..default()
};
let chunk_collider = Collider::convex_decomposition_with_config(vertices, indices, params);
is there some reason SpatialQueryFilter takes a LayerMask instead of CollisionLayers? it seems to implicitly compare with CollisionLayers::new(LayerMask::ALL, self.mask), i'm migrating from rapier and have invisible walls on a layer that excludes bullets (which works for projectiles but not hitscan/raycast)
I think you might need to set fill_mode to surface only or flood-fill with detect cavities enabled, but I havenāt used that myself so I donāt know for sure
In both cases it still happens
Hmm, I donāt know sorry. Does the mesh have disconnected parts? That might be related
I remember a while back using joints meant the game couldn't be used commercially (I think it was joints anyway)
I'm pretty certain this got changed in recent versions, but is 0.3 one of those versions?
Aren't joints still XPBD-based? I know rigidbody integration was moved to an inertia-based implementation but I don't think joints were.
Joints still use XPBD yes, the rest is impulse-based
In practice the risk is extremely small (many MIT implementations already exist, the authors of XPBD said they're not aware of restrictions there, and Jolt also uses XPBD for soft bodies, and Godot uses Jolt) but the patent does technically exist so it's just something to be aware of
we do still plan on switching joints to something else eventually
other things have just been a higher priority for now
How can I use ray casts with open colliders? I have a chunk, that is just a piece of a mesh, and so its open. My problem is, when I cast ray trough that collider, its being ignored.
I use trimesh_from_mesh to create a collider
let mesh = construct_mesh(&buffer);
let mesh_data = MeshData::consume_surface_nets_buffer(buffer);
let chunk_collider = Collider::trimesh_from_mesh(&mesh).unwrap();
And then just add it into the entity:
commands.entity(chunk_entity).insert((
Mesh3d(mesh_handle),
MeshMaterial3d(handle.clone()),
chunk_collider,
CollisionMargin(0.1),
//DebugRender::collider(Color::srgb(0.0, 1.0, 0.0)),
MeshSaveSize::from_mesh_data(&mesh_data),
));
When I visualised the collider, it looked fine.
I use just simple ray cast:
if let Some(hit) = spatial_query.cast_ray(
origin,
direction,
max_distance,
solid,
&filter,
) {
But it returns none when pointed at the chunk
I find it really nice how the mass of the rigidbody gets distributed after changing the colliders' and their mass distirbutions
and it topples and loses its balance without applying any force
š
How does it work? Is it procedural or does it have pre set breaking points?
well calling it "procedural" would be a huge overassesment
it's just a voronoi diagram
with some randomness
In my game I only need ray and shape casting. Would it be possible to feature-gate other things like transform interpolation?
Why might my avian3d colliders (walls) mostly only work on one side?
I even enabled SweptCcd
which side? what shape are they?
I'll get a video later. But it's just a normal wall. I'm not sure if there are any specific sides, as I'm talking about a bunch of them with similar effects.
From one side I can walk through the wall. And from the other I get pushed on top of it.
I forget. Is there a debug mode to view the colliders?
Are they cuboid colliders or convex hulls or trimeshes or?
PhysicsDebugPlugin should add them
Currently ConvexHullFromMesh.
If it helps, i'm using skein, so I'm attaching a colliderconstructor to a mesh in Blender.
These are the assets I'm trying to apply colliders to:
https://loafbrr.itch.io/interiors-a
I'm wondering if the walls are too thin
I suppose I can somehow create a cuboid collider to encompass both sides of the wall. So the collider would encompass the entire wall "space".
I have simialr issue, but my problem is that they don't work at all
Here's a video showcasing my collider problem.
If anyone has any idea what's causing this, please let me know.
Maybe it's something with my player collider?
This is weird; i'm even walking through cuboid colliders.
Just made sure i'm using the latest version. Still no difference.
Solved it. I needed to add static rigid bodies
I had "ColliderDisabled", dang...
Doesn't avian have any automatic way to determine whenever collision should be enabled or disable, or should I manually manage that?
...under what conditions?
usually enabling/disabling collisions depends heavily on the game
I ask cause if I remember well engines like Unreal can determine collisions by themselves, based on e.g. distance. Just want to know if am I doing anything wrong, or is it by design
Like if you get far away from a physics object it "turns off"? Is that what you're thinking?
As far as I know, unreal uses octree based on distance to determine which colliders should be able to interact with each other to minimize amount of computations
oh, yeah Avian does that
it's called Broad Phase
you don't really have to meaningfully worry about it. ColliderDisabled is mainly for like, game mechanic purposes, i.e. turning off a player's hitbox during iframes.
Btw. If I have 2 Colliders that touch each other, does they generate collision events and constantly check each other? I have tightly packed chunks, with colliders touching each other on the edges. Should I do something about that? Might that cause lag I experience? Or the mere presence of not-disabled collisions is causing that?
Should I somehow set that colliders of entities that use ChunkTag ignore other colliders of entities that use ChunkTag?
static bodies don't check for collisions between each other, so it's not a problem if they overlap
if they're not both static then they will check for collisions and have some overhead, yeah
(on Avian 0.6)
Time to update and test, then
Seems like updating to 0.6 fixed my issue, thanks for the tip
When can trimesh_from_mesh return None? I guess when the mesh is empty but are there other examples?
https://docs.rs/avian3d/0.6.1/src/avian3d/collision/collider/parry/mod.rs.html#1499 https://docs.rs/parry3d/0.26.0/parry3d/shape/enum.TopologyError.html
Errors that occur when computing or validating triangle mesh topology.
Source of the Rust file src/collision/collider/parry/mod.rs.
non-float points, zero length edges, weird winding, etc
Hi there, I'm trying to modify the transform of a child item of a physics entity, basically trying to make an icon stay the same angle regardless of object angle.
When I get very fast rotating object I still get an angle on the object's map icon as shown (slightly slanted and flickering X)
So far i've tried a whole bunch of combinations of schedules for my system so that it runs after the interpolation, but before the transform propagation... And I have not been able to do so...
Would any one have an idea of where in the scheadule i'm supposed to insert my system?
Any help would be extremely appreciated !
Here are are a few tries i did:
app.add_systems(
PostUpdate,
update_rotation
.before(TransformSystems::Propagate)
.after(PhysicsSystems::Last),
);
app.add_systems(
PostUpdate,
update_rotation
.after(TransformSystems::Propagate)
);
app.add_systems(Last, update_rotation);
A component that specifies which translational and rotational axes of a rigid body are locked.
but for that kind of thing i usually just make a new relationship that only syncs translation
could modify just the GlobalTransform instead i suppose? either way you'd be doing and immediately undoing work
Ah, I'll have to look into relationships then most likely.
Thank you so much for your answer!
if a dynamic rigidbody collides with a static rigidbody, will it trigger a Change<Transform> on the static transform
I know it won't actually change the values, but does it cause a trigger
because I just found a dormant bug in my code and I think it's caused by this, I hope at least
It shouldn't, but I'd have to test to make sure
is there an example showing avian physics and bigspace playing nice together? a quick discord/git search suggests there isn't.
Check in with the big space thread in #1034543904478998539, the author was definitely showing off some physics engine stuff earlier
Idk if it's avian but
it's rapier
ah, my bad
I worked a bit on the child until I realised that it doesn't matter, I still need to insert myself at the correct spot in the scheadule, otherwise my icon is delayed if the unit is fast. Or if the icon should rotate, the icon will rotate late.
But at least I have the child working xD
So for now i'm still trying to insert myself before the global transform update, but after the physics interpolation update.
physics/interp shouldn't be anywhere after fixed
Odd...
I've been trying to get it but the debug gizmo is still ahead of my sprite
app.add_systems(
PostUpdate,
update_icon_position.before(TransformSystems::Propagate),
);
Nevermind.... It's fixed by doing it in last instead of postupdate!
Thank you so much for all the help!
what would be the easiest way to create a "inverse capsule" collider? E.g. a sort of arena where you can be inside of
several halfspaces
is there any way to debug why PhysicsDebugPlugin isn't rendering anything? The physics work but the debug renders never show, even though I have debug-plugin in the features of avian2d. I'm wondering if bevy itself needs some feature I didn't enable or something
do you have bevy_gizmos_render for Bevy?
That was it thanks! is this missing in the docs ? Would you support a PR with log::warn! in case it's not there when the plugin is being built?
The documentation says CcdPlugin is included PhysicsPlugins, but I don't see it there š¤
It's missing in the table in the docs and I don't see it in the PhysicsPlugins group in the code.
it's in SolverPlugins which is in PhysicsPlugins
it's documented for that
https://docs.rs/avian3d/latest/avian3d/dynamics/solver/struct.SolverPlugins.html
A plugin group that contains Avianās default solver plugins.
Hmm, I believe one of the reasons bevy_gizmo_render is separate from bevy_gizmo in Bevy is to allow alternate rendering backends. I think it'd be strange for Avian to enforce a specific renderer when it doesn't really care about that, it just needs a gizmo API to call (which is provided by bevy_gizmo)
but we could add a mention of it in docs somewhere
Ah, missed it, thank you š
In my game I only need ray and shape casting. Would it be possible to feature-gate other things like transform interpolation?
if you only need ray and shape casting then thats just parry isnt it?
i think i've seen that brought up before, and the problem is parry doesn't have a very bevy-friendly API
you need to write lots of glue code to get the two to play nice
Exactly!
That's why I asking if Jondolf would be open to something like this or the plan is to use Peck for cases like this in the future.
yay!
I solved my spring jiggle by moving the system from Update into PhysicsSchedule with .before(PhysicsStepSystems::First), but I wonder if there's a friendlier way?
You should do Physics stuff on FixedUpdate
Update will have jiggle
I have another problem with my grabbing mechanism. The spring works fine for linear constrained things, but with a RevoluteJoint it seems to do really nasty stuff with the velocity_at_point method.
My code looks like the following every fixed update:
// mut target: Single<(Entity, &GlobalTransform, Forces, &CursorTarget)>,
// mut cursor: Single<(Entity, &mut Position)>,
if let Some((_, ray)) = rays.iter().next() {
cursor.1.0 = ray.origin + ray.direction * cursor.2.depth;
}
let anchor = target.3.anchor;
let want = cursor.1.0;
let am = target
.1
.mul_transform(Transform::from_translation(anchor))
.translation();
gizmos.sphere(
Isometry3d::from_translation(want),
0.01,
Color::Srgba(Srgba::GREEN),
);
gizmos.sphere(
Isometry3d::from_translation(am),
0.01,
Color::Srgba(Srgba::RED),
);
let force = (want - am) * 20.0 - (target.2.velocity_at_point(am) * 5.0);
gizmos.arrow(am, am + force, Color::Srgba(Srgba::BLUE));
println!("{force}");
target.2.apply_force_at_point(force, am);
and the further away I am from the joint, the worse it gets
anyone know what I can do to fix this?
Would you say 0.6.1 is more stable than the latest 0.5?
I'm close to a steam demo and people are still having crashes due to parry
(But in the last two times I tried migrating to an 0.6 the game crashed in the first minute or so)
you can tell bevy to just log and keep going if a system errors
what is actually causing the crashes? parry is decently mature for the rust world, maybe not as much as something like Jolt or Box2d but regular crashes shouldn't be common
I had a parry crash on 0.5 and upgrading to 0.6.1 fixed it for me
It was also really straightforward. Literally had to change 0 code
I think it was this one, or at least similar:
#1124043933886976171 message
yeah that crash was because of Parry's BVH, which we no longer use š (we switched to obvhs)
Wait you can? There's a way to catch panics always? š®
It doesn't happen very often, but once every 20 sessions when you have 2k play sessions is a hundred crashes
I already changed all &mut CollisionLayers to try_insert so I'm ready to move once stable
nah that's for systems that return Results, or for commands that fail, not for actual panics or unwraps
Rust does have catch_unwind, but it's not a full panic recovery thing, mostly useful for e.g. saving progress or logs to a file before quitting for example
I see
I already am printing the crash log to a file so release builds can share them after crashes
As head of Avian, would you say 0.6.1 is more stable?
It's faster and fixes some crashes (like the BVH crash Big Yolk was seeing before), but also potentially introduces a few new obscure ones
I didn't see any Avian crashes in the Bevy jam game we did with 0.6, but it depends on the game and what weird things one might be doing
Source of the Rust file src/schedule/executor/single_threaded.rs.
(correct but i wanted to get details)
notably entity cloning has never been fully supported, and entity disabling is supported but is fairly bug-prone in general (not just in Avian but in all of Bevy)
-# (also technically every panic unwind goes to a catch_unwind, there's one right around main() that handles actually quitting the process on panic)
Like I donāt understand what happens here. When I grab further away and just slightly move my mouse the arrow is already pretty large and makes the door spin weirdly sideways. But shouldnāt the torque thatās being added because of the further distance do the opposite? Or is there some weird edge case that I need to manually add torque on velocity_at_point?
what happens if you turn the force down
you mean the * 20.0?
or just dragging down?
I made the * 20.0 a * 0.2 but it still multiplies till it gets too big and crashes
tho normal dragging for linear things is unusable
huuuh
I don't even have to move my cursor
somethings definitely off with the apply_force_at_point to velocity_at_point thing
okay without moving my mouse, I currently do this:
let anchor = target.3.anchor;
let want = cursor.1.0;
let am = target
.1
.mul_transform(Transform::from_translation(anchor))
.translation();
gizmos.sphere(
Isometry3d::from_translation(want),
0.01,
Color::Srgba(Srgba::GREEN),
);
gizmos.sphere(
Isometry3d::from_translation(am),
0.01,
Color::Srgba(Srgba::RED),
);
let force = (want - am) * 0.2 - (target.2.velocity_at_point(am) * 5.0);
gizmos.arrow(am, am + force, Color::Srgba(Srgba::BLUE));
target.2.apply_force_at_point(force, am);
println!("{force:.8} -> {:.8}", target.2.velocity_at_point(am));
and get the following result
with a damping of 0 or with a damping of 100 it both gets worse
why does it do such weird feedback for revolute joints š
Ok so I updated to 0.6.1 and will be now reverting back to 0.5
After about 30 seconds of gameplay I get:
no element at index 1 in StableVec::index_mut
Encountered a panic in system `avian2d::collider_tree::update::update_moved_collider_aabbs<avian2d::collision::collider::parry::Collider>`!
Encountered a panic in system `avian2d::schedule::run_physics_schedule`!
Encountered a panic in system `bevy_app::main_schedule::FixedMain::run_fixed_main`!
Encountered a panic in system `bevy_time::fixed::run_fixed_main_schedule`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!```
is it possible to use Position rather than translation? this might be a tnua issue. also maybe an xy problem. what i'm trying to do is keep track of a very precise position value, but keep the translation locked to a large pixel grid
if i round() the translation value on FixedUpdate, there is a strange shimmering. if i do the same on Update, the movement only updates every few frames for some reason, but is not shimmery
it's kinda jerky
i'll record a video to show the different outcomes
can replace the sync systems
PhysicsPlugins::default().build().disable::<PhysicsTransformPlugin>()
alright, it looks good now, but collision seems to be disabled
does anyone know why that is?
are you initializing position and rotation?
try enabling the debug plugin
How can I remove impact force? When I hit a wall it causes player(With sphere collision) to rotate. I want it to just stop, without any turning, rotating, impact forces etc.
Kinematic body instead of dynamic?
When I used Kinematic Body collisions doesn't work. I also still want to use forces like e.g. Gravity,
fixedaxes?
Whats that?
A component that specifies which translational and rotational axes of a rigid body are locked.
Got the desired effect with:
RigidBody::Dynamic,
LockedAxes::ROTATION_LOCKED,
Restitution::new(0.0),
Friction::new(1.0),
Thanks
Hello everyone. Does anybody know how can I get "the actual velocity" of a body in avian2d?
For example if i have a body that has a non-zero velocity but is stuck at a wall, i want to know that "the actual velocity" is zero
Dumb answer: Make a system and component which just tracks changes to Transform frame over frame and calculates velocity from that.
Maybe smarter answer: ContactPoint has a field which returns the delta velocity of a collision, which I think would be useful with this.
Data associated with a contact point in a ContactManifold.
isn't linear velocity already the actual velocity? why do you need that in the first place?
Now that you asked i doubt myself š. I am not at pc so I will double check tomorrow, but i think it's not actual velocity.
I need it to tie walking animation speed to it. So that when my guy is walking into the wall he doesn't move legs.
How often does Avian update physics? During Update, FixedUpdate, some other thing? I want to cast shape every physics update
But, from what I see shape_cast returns only 1 hit. I want to make a character that sticks to the ground, basically a spider, so having more points would help to stabilize it. How should I approach that?
you'll need raycasts for IK anyway, so probably that
and it's in fixed(post)update
note: do not put your systems in FixedPostUpdate, learned that the hard way. Avian does not like it when you delete entities while it is updating physics.
call shape_cast multiple times
So put it in the fixed update, right?
confirmed - linear velocity is not "actual velocity", even if the object is stuck it will still show some velocity. At least in my case, as I apply it manually to move the character
No, LinearVelocity is a Way to apply velocity
It need Have a AssemblyLinearVelocity to know the actual
Hi folks !
is there any way to automatically create a Collider on the root entity , when using ColliderConstructorHierarchy with gltf scenes ? Thanks !
ie
commands.spawn((
Name::new("Test"),
SceneRoot(
asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/power_cable_coil.glb")),
),
ColliderConstructorHierarchy {
default_constructor: Some(ColliderConstructor::ConvexHullFromMesh),
..Default::default()
},
// automatic root collider ?
RigidBody::Dynamic,
Mass(20.0),
));
The colliders are on the entities that have the meshes, which for glTFs are always child entities afaik
You could implement some custom thing that collects all meshes and creates a single compound collider, but that's not a built-in feature currently
I implemented what Jondolf mentioned for my game, feel free to use it:
https://github.com/simgine/simgine/blob/project_harmonia/base/src/combined_scene_collider.rs
can't you schedule your check before you modify LV?
if he modify the vector velocity
it wont show on LV
Ok thanks a lot for the information ! Btw, Avian is absolutely fantastic, the features , performance & API is a joy !
Wow, very nice , thanks a lot ! I had started on implementing it, but this is cleaner , thanks š
When I do this:
commands.entity(e).insert((
RigidBody::Dynamic,
Transform::from_translation(position)
));
the entity will always go to (0,0,0) in the world instead of my position. It seems like RigidBody::Dynamic inserting Position::PLACEHOLDER is overwriting the Transform that I inserted? On further testing this works fine for example:
commands.entity(e).insert((
RigidBody::Dynamic,
Transform::from_translation(position)
));
// just re-inserting transform AFTER RigidBody
commands.entity(e).insert(Transform::from_translation(position);
Is this intended behavior? I ended up doing this:
commands.entity(e).insert((
RigidBody::Dynamic,
Position::new(position),
Transform::from_translation(position)
));
Hi, I am currently creating a game where a player with a rectangle (or round_rectangle) collider is walking on a 2d tilemap. each stone has itās own static collider. I move the player by changing itās velocity. The player still walks into walls when it collides with two blocks standing next to each other and only gets pushed out slowly. How can I fix that?
Thanks for your help!
I currently apply a big force one time at a rigidbody which is axis locked and on a prismatic joint. Currently, when it's at the end, it just stops. How can I make it "rebounce" a bit easily?
Yo @vestal minnow I think I found an issue, but I'm not sure whether it's intended or not, so asking here b4 opening an issue/pr in github
Resizing the collider/s of an sleeping rigidbody doesn't wake it up (Haven't checked but changing the transform overall probably doesn't)
Which basically puts the rigidbody in a physically inaccurate position until it's waken up somehow and re-checked.
Is this intended behavior? or would you accept a PR that makes transform propagation wake up the body if it's sleeping?
Changing the translation or rotation does wake it up, but changing scale doesn't currently. I'd accept a PR to allow changing scale to wake up entities
as a workaround in user code, you can just .try_remove::<Sleeping>() when changing scale, or alternatively use commands.queue(WakeBody(entity))
There's a few physics engines that have a joint limit restitution for this (PhysX comes to mind), but we don't have that built-in currently. You could make the limit itself soft by changing its compliance, but that'll just make it springy and not "bounce" against a hard limit
you could also manually try to detect when it hits the limit, compute the velocity at that point, and then apply some rebound impulse to emulate the effect
just a bit more complicated
Look up "ghost collisions" in this Discord or in the repo. But for this case:
- If you used
Collider::voxelsfor the tilemap, it wouldn't have the problem (except maybe at the edges between different colliders...) - Adding
SpeculativeMargin::ZEROshould also make it less of a problem, with the caveat that your character could technically clip into or through walls at high enough speeds, since it disables speculative collision - There are some more specialized solutions that you could try, like the approach in this article
Thank you :) I just tried collision compound and it is working now
Not intended behavior, but I'm not too surprised it's broken there š¤ the transform initialization logic is very scuffed haha
would be good to try making it more robust though
Had me going for like 3 hours lol. Makes sense though
yeah, that's what I'm doing
When I'm setting movement direction I'm modifying LinearVelocity, but then I'm overwriting Velocity set by ConstantLocalLinearAcceleration. How should I resolve this? I suppose creating my own component for things like gravity isn't the ideal solution, since ConstantLocalLinearAcceleration exists for a reason, right? I also can't just leave Y axis for the gravity, and modify other axes since gravity in my project can be from any direction
The other question is, how can I reset acceleration? It seems like its being added indefenitely:
/// Applies [`ConstantLocalLinearAcceleration`] to the accumulated local acceleration.
fn apply_constant_local_linear_acceleration(
mut bodies: Query<(
&mut AccumulatedLocalAcceleration,
&ConstantLocalLinearAcceleration,
)>,
) {
bodies
.iter_mut()
.for_each(|(mut acceleration, constant_acceleration)| {
acceleration.linear += constant_acceleration.0;
})
}
But clear_accumulated_local_acceleration is private.
what counts as a "very high subset count"?
0.6 seems to have breaking CollisionLayers changes
it's been changed to an immutable component i see
hey there! I have an Avian plugin crate that is getting ready for a 0.1.0 release, is there any convention on crate names? I was thinking on going with avian_<specific-plugin>, but I don't want to ruff feathers
is it possible to enable/disable debug gizmos in runtime without having to manually do for each entity
Yeah I have a checkbox that does this, gimme like 10 minutes to wake up and I'll send it to you
tyty
fn toggle_physics_debug_vis(gizmo_config_store: ResMut<GizmoConfigStore>) {
gizmo_config_store.config_mut::<PhysicsGizmos>().0.enabled
}
set that to alse to turn them off and true to turn them on
nope, people just call their crates whatever they want
avian_* is fairly common, see for example avian_pickup or avian_rerecast . If it's something that a physics engine would not be expected to have built-in, go for it! But if it's a more general name like avian_solver or avian_collision, or you're otherwise unsure if it's okay to claim, it's good to ask first
There's no specific naming scheme though, some might have a bevy_X crate and the Avian integration is bevy_X_avian, or some crates might use a fully unrelated name, like bevy_ahoy
Honestly that sentence might be kinda outdated or inaccurate, I think if you have so many substeps where numerical issues actually become a problem, your performance would probably be dead anyway
I don't have any specific numbers there
i ended up increasing the fixed schedule rate for my usecase
mostly just tune it such that stability is good enough while things still run well
and everything seems fine
yeah that works too, the effect is slightly different but both can improve stability
256 Hz feels a bit on the high end, but if it works well, then that's fine
had issues with ghost collisions
yeah that makes sense
if a high speed object moved towards a wall, and a spike was behind that wall, it would hit both the wall and the spike
so i increased the physics rate to x4, which still caused the ghost collision
so i required the object to collide with the spike for 4 frames in a row
and that finally fixed it
which is why i did fixed update rate instead of substepping
there's SweptCcd that you could use instead of speculative collision (or alongside it) that likely wouldn't have that issue, although it has its own caveats
i did use sweptccd
hmm okay
sweptccd is on the entire process
im curious why the ball collides with the spike for multiple frames in a row though
when there is a ghost collision, why isn't it just a one frame ghost collision?
not sure, hard to tell without running the scene
I would intuitively expect it to be at most two timesteps, ideally one
same but I don't have much understanding of physics simulation
hmm
seems to be 2 frames actually
2 frames of ghost collision
even without the absurd high fix timestep rate setting a 3 frame requirement seems to fix it
yippee slight improvement
thanks! I think it's fine then, I don't expect avian to have it built-in š
I want to use a param set within collision hooks but since it's not mutable access i'm not able to
i want to create multiple different checks in a row, and don't want to deal with query conflicts
is there a way to make this work, or should i just use a few with<> and without<>s
what's the difference between these two?
One returns a vector (direction), one returns a magnitude / number (length)
Pretty much what the doc comment says. If you have two opposing impulses (e.g. an object wedged between two surfaces), then they could cancel out and the total impulse vector would be near zero; but the scalar impulse magnitude would be the sum of the magnitudes of the individual impulses, disregarding direction, making it non-zero
The vector is useful for "what is the final impulse acting on this body" and the scalar magnitude is useful for "how much impulses are being exerted on this body in total" (could be used for some threshold for breaking the object into pieces under high pressure)
Yup, the latter is what I ended up implementing, and magnitude worked perfectly for that
If you really need to use mutable logic, you can queue a command with commands.queue(...), which has exclusive world access
Or run a one-shot-system
With commands.run_system(...) IIRC
which would let you easily use system parameters
there's also something like run_system_with if you need to pass input
The caveat is that you can't modify the contact there directly anymore, and it's run deferred
(since it's a command)
I see, well the goal would be to modify the contact
but that seems really useful for code organization in general
The reason mutable access isn't allowed in the hook is because it's run inside a parallel loop where it's computing contacts, and so it can't provide safe mutable access to the hooks from multiple threads simultaneously
the provided commands are the main "escape hatch" to still allow safe deferred mutation that is run outside the parallel loop
I guess we could mayyybe also provide some unsafe variant that does allow mutable access to some capacity, but I haven't looked at how viable that is, seems sketchy at best
that makes sense yeah
the difficulty for me is that you can only have one set of collision hooks
and i have multiple different checks and effects I'm implementing
which can cause conflicting queries
even though the queries are done separately
Yeahh I think you need With and Without filters then unfortunately, if ParamSet requires mutable access :/
it feels kinda weird if it requires that though
yup makes sense, tyty
finally found a decent way to check which collider is which component
what I was doing before
should work great for handling collision events in non-observer scenarios
maybe could be a macro? it's a common pattern I encounter
setting a rigidbody through transform seems to cause
tiny tiny floating point differences in position and rotation
:(
so the same transform can seemingly have slightly different rigidbody situations
unsure if this makes sense, but that's the behavior I'm seeing
will try setting position and rotation directly maybe,
or write my own syncing system?
Is there a way to change LinearVelocity but in local space?
Or maybe a way to apply force just for 1 tick, without accumulating/accelerating. So if this is just a single force and its removed then in the next tick entity just stops. Doesn't decelerate, just stops
what are you actually doing in your game? Is this a momentum-preserving dash?
I want to create a movement system where gravity is not working in just 1 direction. Basically, its perpendicular to the wall character is standing on. I've seen examples where movement was done via setting LinearVelocity component, but this unfortunately resets ConstantLocalLinearAcceleration.
I'm simply trying to create 3 axis movement system
I think you're looking for the Forces QueryData: https://docs.rs/avian2d/latest/avian2d/dynamics/rigid_body/forces/index.html#one-time-forces-and-impulses
External forces, impulses, and acceleration for dynamic rigid bodies.
I think the Constant* components will be less ergonomic because you'll be changing them pretty much every frame anyways as you only get one per entity
I tried using ConstantForce, but it accelerating, and decelerating
yeah I don't think they're going to help you very much
you should be using Forces::apply_force
it's a per-frame force application
i'm assuming you have like, "gravity areas" or some such which apply gravity to an entity
you'd essentially have a sensor that checks for overlap with your gravity areas with your entities which you are applying gravity to, then calculate apply_force for each one based on the sum of forces desired from all overlapping areas.
Yes, basically every character is checking if its on the wall, if not, it applies gravity on itself
yeah try Forces. The intention of the various Constant* components is, I suspect, just ease of use. If you want to get that granular you're gonna want to use the lower-level API.
Using apply_force works like using ConstantForce. So its accelerating, and then decelerating
What does this mean exactly? Can you describe in more detail how the rigidbodies are behaving in a way you don't want?
mario galaxy?
are you adding or setting LV?
When I press a button instead of going at the given speed and then immediately stopping when button is released, itās gaining speed over time and then loses it over time when button is released
Ye, something like that:
https://youtu.be/iFAT6BqhE5A?t=29830
I've tried both setting and adding LV(Linear Velocity), but both has problems. Setting it resets other velocities like ConstantLocalLinearAcceleration, and adding it causes accumulation
This video shows off a Complete Walkthrough of all 120 Stars in Super Mario Galaxy for the Wii. This is an instructional video that shows the viewer how to complete the entire game by showing off all the star coins and secret exits for all galaxies in the game, along with all green stars.
Subscribe to NintendoCentral: āŗ https://www.youtube.c...
So the tl;Dr is that Super Mario Galaxy has cartoon physics and you can't achieve that by just setting acceleration or LV on a rigidbody. You need a character controller, not realistic rigidbody simulation.
You can write your own character controller from scratch but this is pretty nontrivial. Doing it with a kinematic body is easier because you set velocity and call a move-and-slide function, but then you often have to handle stairstepping and other little details. Rigidbodies are harder as you've encountered because you have to carefully calculate acceleration to achieve desired velocities.
You'll want to check out bevy_tnua and bevy_ahoy at least to read the code, if not to try them out and seeing if they will support Mario Galaxy style movement.
bevy_tnua also links to some good reference videos on YT that explain how it was made, which may help you.
You... might be able to achieve it by setting LV directly which is actually a decently unusual property of Avian
But not by accumulating it
I don't meen cartoon physics, just sticking to the walls, like on this video fragment I found. Can also be like this scene from Berserk, or this mod from minecraft:
https://www.youtube.com/shorts/wtCgQ9JIYdw?feature=share
I have all the stuff required for rotating player according to the fall and stick it, so I sort of have the controller, just need a way to move the player
Can you send a video/gif of your character controller in-engine with one of your existing solutions? It'd help to see what exactly is going wrong.
I maintain you need some kind of character controller logic to handle your acceleration in order to cleanly limit your character to a maximum velocity.
For example this blog post goes over the Source engine's player character controller with some explanation: https://adrianb.io/2015/02/14/bunnyhop.html
This is version using forces.apply_force, and it feels like moving on ice
for (_, player_transform, _player, mut forces) in player_query.iter_mut() {
let mut fly_direction = input.movement.x * player_transform.forward();
fly_direction += input.movement.y * player_transform.right();
let mut normal_dir = Vec3::ZERO;
if let Some(normalized_direction) = fly_direction.try_normalize() {
normal_dir = normalized_direction;
}
//linear_velocity.0 = normal_dir * 8.;
forces.apply_force(normal_dir * 8.);
Yeah read the article I sent you :P and do some digging into what a character controller is. The tnua and ahoy repos are good places to start as well.
Physics engines don't really consider it their responsibility to make characters feel good, and characters running on raw acceleration or directly setting velocity to constant values don't feel very good, as you described "sliding on ice." You need to introduce additional dynamics like friction, max velocity capping and altering acceleration depending on current speed.
Welp, I guess its time to learn then, thanks for the calrifications
i did that with the very very valet controller, everything was mostly fine except camera, i couldn't figure out how to make it not nauseating in first person
you just need directional damping
I see there is LinearDamping, but I don't see anything related to directional damping
DIY š
Forking time? xD
you can use linear, you'll just have to account for unwanted damping on the gravity axis too
Well, after setting gravity to the level of Jupiter's, I think it works fine with damping
you can do more fun stuff if you make a directional one anyway, check very very valet's car video
This one?
https://youtu.be/CdPYlj5uZeI
A detailed look at how we made our custom raycast-based car physics in Unity for our game Very Very Valet - available for Nintendo Switch, PS5, and Steam.
BUY NOW!! https://toyful.games/vvv-buy
~ More from Toyful Games ~
- Physics Based Character Controller in Unity: https://youtu.be/qdskE8PJy6Q
- Instant "Game Feel" Tutorial: https://youtu.be/...
I love this crate
In my game I support pause. When the game is paused, time dilation is set to 0, everything freezes. FixedUpdate doesn't run.
But users can move objects during pause.
To pick objects I use avian and I'd like to keep it functional during pause. Just for testing I set the Avian schedule to PostUpdate. But it still breaks. On the video you can see that I can move objects freely while the game is unpaused. But once I pause the game, I can move any object only once. After that hovering over the object does nothing (you can see white outline when the object is hovered).
I tried using regular ray-casting instead of picking and it has the same issue - it breaks when the time is frozen š¢
Hello. I have problems with a "car simulation" using Avian3d.
I have pretty simple setup with main car body, wheels connected to it using RevoluteJoint. Car behaves extremely bad, bumps even on a slightly varying polygonal surfaces and get stuck into the ground quite fast. Where should I look to solve this problem?
I use Ccd, all bodies have masses, car has angular inertia
https://gist.github.com/BlazarBlade/395132e8eccc92da410f55d9a838c329
I forgot to convert my video into Discord-friendly format and unfortunately Discord doesn't allow edit attachments. So here is the video in a new message.
Can you try adding the update_moved_collider_aabbs system to run while the game is paused?
that should in theory update the spatial query BVH when you've moved colliders around
we should probably expose a more user-facing system or API for it
I tried this:
.add_systems(PostUpdate, update_moved_collider_aabbs::<Collider>)
But the issue is still present š¤
It was with manual shape casting. Let me try picking. I could be a multisystem issue š¤
No, same problem.
@vestal minnow wait, no, picking works.
RayCast still breaks.
@vestal minnow
Sorry, just to clarify - clicking on colliders works via picking works. After I apply movement (done via transform manipulation and unrelated to picking and avian) - the collider is correctly updated when I add the suggested update_moved_collider_aabbs.
But the mentioned RayCast component is still broken. Its global direction always points to [1, 0, 0], no matter how I update its local direction.
oh yea RayCaster and ShapeCaster are separate from that stuff š¤ I suppose we could probably move their update logic out of the PhysicsSchedule so that they'd be updated even when the simulation is paused
That would be nice.
Do you want me to open an issue?
Yup, that'd be nice, thanks!
Hmm does the SweptCcd actually help here or is it better if you remove it?
I feel like it might be some pathological case where it's detecting that it should stop at each of the edges which makes movement very stuttery/bumpy, and more generally you're probably seeing ghost collisions (you can search this discord or the repo or the internet for them)
personally for vehicle sim I would probably start with a raycast-based vehicle controller
there's also this
https://youtu.be/CdPYlj5uZeI
A detailed look at how we made our custom raycast-based car physics in Unity for our game Very Very Valet - available for Nintendo Switch, PS5, and Steam.
BUY NOW!! https://toyful.games/vvv-buy
~ More from Toyful Games ~
- Physics Based Character Controller in Unity: https://youtu.be/qdskE8PJy6Q
- Instant "Game Feel" Tutorial: https://youtu.be/...
you can make one with raw physics simulation and contacts too, but it'll probably just be more painful and you'll have less control
Basically I have ported it to the bevy and avian, but it breaks on high speeds. Thats why i decided to switch to ccd with real wheels
I think it can be solved with several raycasts, but it would require some sort of intermediate step just before the collision
Looks like its a bug https://github.com/avianphysics/avian/issues/705
Unfortunately its a show-stopper, with extremely high compilation times i have to switch back to c# š
did you FIX_INTERNAL_EDGES on that mesh?
Can't I have both Collider and Mesh3d in the same query?
It helped just a little bit, there are a lot of issues with instability. I've tried godot collision engine, and behaved much better, pretty stable on any meshes
Yeah of course they're unrelated. Share your query?
pub fn dig(
_: On<Fire<Dig>>,
camera_query: Query<(&ChildOf, &GlobalTransform), (With<LocalEntity>, With<Camera3d>)>,
spatial_query: SpatialQuery,
mut chunk_state_monitor: ResMut<ChunkStateMonitor>,
mut mesh_data_query: Query<(&mut MeshData, &mut Mesh3d, &mut Collider)>,
mut meshes: ResMut<Assets<Mesh>>,
mut gizmo_assets: ResMut<Assets<GizmoAsset>>,
mut commands: Commands,
) -> Result {
...Yeah nothing out of the ordinary. What happens? Does the query just not return anything?
I'm getting an error when I start the game. This started to show up after I've added Collider to the query
error[B0001]: Query<(Position, Rotation, Collider), ()> in system neklurgle::game::plugins::player::input::inputs::dig::dig accesses component(s) Collider in a way that conflicts with a previous system parameter. Consider using `Without<T>` to create disjoint Queries or merging conflicting Queries into a `ParamSet`. See: https://bevy.org/learn/errors/b0001
Okay I was thinking it was going to be a conflict of some kind
SpatialQuery conflicts:
https://docs.rs/avian3d/latest/src/avian3d/spatial_query/system_param.rs.html#60-64
What can I do about it?
Essentially what the compiler error says
Your mesh_data_query queries Collider
So does SpatialQuery
So you either need to colocated both in a single ParamSet, use a QueryLens on SpatialQuery to extract the Collider query and remove it from mesh_data_query or... Find a way to use Without on mesh_data_query.
This is one of the parts of Bevy that is difficult and annoying.
Might be able to advise better if you share the whole system but no guarantees. Sometimes the right option here is to break things up into multiple systems
Here is the whole system
Ok, I went with the ParamSet
I'm trying to implement a simple door opening animation from Blender. For some reason, the animation isn't moving the collider when playing, only the visible mesh. Why might this be the case?
'regular' animations are gpu-side only
Define "regular". As I have an old map with an animation that still seems to work without this problem. I've yet to find out why
the type you'd load from a gltf or similar
what's the old animation? could be that a root bone will be read back or something, or maybe it had special handling
can you use position and rotation in non physics objects?
Here's a screenshot of the working door in Blender:
The collider seems to move with the animation in this one
opposed to
This one, where the collider stays still:
I can try and provide short videos demostrating
where's the collider in that second hierarchy?
The second one i'm trying to just use the mesh of the door. The first one only has a seperate collider mesh because I was testing something a year or so ago.
https://docs.rs/avian3d/0.6.1/src/avian3d/physics_transform/mod.rs.html#254-257 if they have https://docs.rs/avian3d/latest/avian3d/physics_transform/struct.ApplyPosToTransform.html
Marker component indicating that the position_to_transform system should be applied to this entity.
Source of the Rust file src/physics_transform/mod.rs.
i see
I can't tell if someone else has already reported this as an issue, or if it might be my code, but I'm using apply_force_at_point with two points on the opposite side of the center of mass, as shown, at points that follow points on the body, dependent on rotation, and such that the resultant force should produce 0 torque, but which results in a torque that acts to align the body's rotation with the direction of velocity while moving with a high amount of velocity
something that seemed to mostly fix the issue was adding the body's velocity * dt to the point's translation, which leads me to believe that the transform is being updated somehow before the physics engine's center of mass is, despite me setting the body's transform anywhere
Are you doing your physics update in FixedUpdate, because that's where avian runs, and it can cause those kinds of problems when your running your physics logic on Update
is there a way to get the collision impulse magnitude before the collision happens inside of modify_contacts?
Previous impulse yes, current impulse no. The solver is what computes and applies contact impulses, and it has to run after collision detection
However there's a normal_speed associated with each point
I'm trying to test a breakable object that doesn't collide if the object is fast enough
like angry birds ice
That tells you how fast the shapes are approaching or separating at that point
which can be used to emulate "contact strength", ignoring mass
impulses can be a little fiddly since the time step affects them and I believe speculative collision can also lead to impulses being a bit dampened sometimes
so normal impulse would be the previous, and normal_speed is the current?
and if i add together all the points' normal_speeds * mass it should be some form of magnitude?
normal_impulse is the latest computed impulse. If you were reading it after the physics step, it would be the "current" impulse. But you're reading it during collision detection, before the solver has run, so it's effectively the impulse from the previous timestep, not the impulse of the updated contact
Adding together normal_speeds is maybe a bit sketchy, you probably just want to pick the largest one
i.e. "how fast are these shapes approaching each other"
i see
(or separating from each other if they were overlapping)
it depends on what you want as the heuristic for how "hard" the objects hit each other
I need some knowledge. Is it the cube made of voronoi cells or is the cube "voronoied" at realtime?
that'd probably be it then
worked, thanks
the effect I described is still happening a little bit, but it's mild enough that I'm not that worried about it
"voronoied" in real time, also remeshed in real time to the voronoi cell shapes
Do you have any public repo where can I see how its done?
private for now, but I'm thinking about making it into a crate if I make it generic enough
right now it fits a very specific usecase where colliders and meshses are basically 1:1 and also they're simple low-poly shapes
which wouldn't work for most games really
Is there a way to debug spatial_query.cast_shape with gizmos or something that will let me know where my shape is?
I'm casting a cylinder atm, i've tried drawing with gizmos.circle but i just can't get it to make sense and lign up
Yup, exactly how it works in my case
What movie is it from?
labyrinth
1986?
with david bowe
Hello š
I'm having some trouble trying to use point projection with a trimesh collider. Specifically the ColliderConstructor::TrimeshFromMesh .
If I use a cuboid or ConvexHullFromMesh the spatial query correctly determines is_inside but with a trimesh it seems to consider everything as being outside. Is this just a limitation due to trimeshes being an arbitrary shape compared to a convex hull that guarantees being a closed shape? or is there something fishy going on under the hood?
for context i'm just using a bevy cuboid as the mesh for the collider and want to get the distance from an arbitrary point to the closest surface on the collider
Triangle meshes are hollow, they don't have any solid volume even if they are closed
Conceptually it's just a bunch of infinitesimally thin triangles that form a mesh
ahh ok, gotcha
any pointers on finding out if a point is "inside" a trimesh using the API? i didn't have good results with convex decomposition but if that's the right way then i'll rush headlong into that instead
Are separate simulation contexts implemented yet?
I remember seeing discussions about this.
Oh man I remember this algorithm from like 10 years ago-
The tl;Dr is you have to random raycast to infinity (or at least the AABB boundary of the mesh) and count the number of intersections and normals of those intersections. This is a raycast through all, not one with a limited number of hits.
This is only guaranteed to work for manifold meshes.
There's a much faster check if you have the SDF of the mesh but most people do not.
If I recall Avian doesn't natively support them yet but you can use multiple SubApps/multiple worlds.
Or... Maybe there was some limitation there too. My memory's foggy.
This is great, thanks!
Incidentally I do have the SDF for some meshes as I wanted to use the point projection to cut through it. Figured projection would be easier than generating an sdf for an arbitrary mesh, but I'm gonna spelunk into that as well to compare both methods. Exciting!
i mean, checking for whether or not an SDF contains a point is trivial
it's just sdf(my_point) < 0.
Yea. I hope it's similarly straight forward to generate an sdf
I can't see why it wouldn't be if I use both point projection and the raycast check you outlined
Well- Usually meshes are generating from SDFs, not the other way around
Or you happen to have data which is mathematically equivalent to an SDF
that's why I said "most people don't have one," because unless you're creating SDFs for terrain or some kind of generative geometry, it's usually easier to just do the raycast check as opposed to try and back out an SDF from a mesh
I have enhanced determinism enabled, but collision events don't seem to maintain the same ordering
it's really weird, it alternates between entity 318 and entity 320 colliding first
seemingly every other run
adding/removing ColliderDisabled seems to alter the order of collision events, very strange :(
removing collision events and disabling the rigidbody instead fixes this, but very jank solution
is there a meaningful difference between RigidBody::Static and RigidBody::Kinematic for Sensors?
Hello, is there a reason why CollisionLayers is marker as an Immutable component ? should we not edit it and re-insert it to override it ?
the idea is that if you want to change it you insert a CollisionLayers component on an existing entity and it replaces the previous CollisionLayers.
Mainly that the static rigid body is static (cannot have velocity etc.), while kinematic bodies can have velocity
It's to minimize change detection overhead, for most apps I would expect modifying collision layers to be a very sparse and rare operation, and so having systems iterate over all colliders to see if their layers changed is unnecessary overhead
By reinserting and having observers react to it, the change is also applied "immediately" for spatial queries
etc., unlike when using standard systems with change detection
But we might revert this and make it mutable again if/when pcwalton's change indices land, since that should make the overhead negligible
Thanks ! I'm migrating an old game and this surprised me. I would argue that altering collision layers is more frequent than we expect, even though probably not on a large scale.
An other question, there used to be a ExternalImpulse component I could insert in a command to add impulse velocity to a rigidbody, are we expected to use the Forces query params ? Is there a way to use this in a Command?
Yeah, Forces is the main force and impulse API now... in a Command (or instead of a command) I would maybe consider running a one-shot system via run_system, that way you can easily use system parameters and queries
in theory you can also cache a SystemState with the query in a resource or something, and in the command, access the system state in a resource_scope, but that's pretty inconvenient
Alright! I think I need to rework the associated logic anyway
is there a way to check if rigidbody is on floor/wall/ceiling
or does it require manual mathematics
nothing built-in as far as I'm aware, but the math isn't hard, lmk if you want a high-level description.
If you need this for a character controller, I'm pretty sure bevy_tnua has this built-in.
Would it be possible / how difficult would it be to use avian for collision detection, but use custom code for integration and collision response? Is there a sub-dep that I should be using directly?
For #1, the general consensus is that you can use Parry (the collision detection library Avian uses under the hood) directly if you want, but it has no ECS bindings, so the API will feel very much so like you're calling out to a separate library, instead of like a bunch of components and systems that integrate with Bevy. You will also have to write glue code to, for example, synchronize entities/components with Parry's data structures (which is what Avian does under the hood). Jondolf's also working on an in-house collision detection library intended to replace Parry one day, but it's not done yet, FWIW.
For #2: Depends on what exactly you want to do.
Kinematic RigidBodies aren't the same as custom integration but if all you need is to directly control the position/velocity of specific bodies, and manually control how they are affected by other bodies, they're the simplest. The only tricky part is you don't really have fully direct control over how the Kinematic body affects other Dynamic bodies.
You can use CustomPositionIntegration and CustomVelocityIntegration markers to disable built-in integration for Avian on a per-entity basis. (I think) you'll want to add your own systems in the same place in the schedule schedule as the built-in integrate_positions and integrate_velocities systems which perform custom integration for those and only those bodies.
Alternatively you could take a look at the plugins added by PhysicsPlugins, and remove the IntegratorPlugin entirely if you want to do custom integration for every single body- You'd probably want to start by copying the code for IntegratorPlugin and modifying it. This is the nuclear option if your game's entire dynamics differ from the default lifelike ones Avian provides.
sooo.. I have two entities and I wanna get entity 1's position when they collide
if you just want which two entities are colliding and only need the like, origin position: https://docs.rs/avian2d/latest/avian2d/collision/collider/struct.CollidingEntities.html or https://docs.rs/avian2d/latest/avian2d/collision/index.html#collision-events depending on whether you want a system or observer.
if you want the actual point at which the two entities are touching: https://docs.rs/avian2d/latest/avian2d/collision/contact_types/struct.Collisions.html
A component for reading which entities are colliding with a collider entity. Must be added manually for desired colliders.
A SystemParam for accessing and querying collision data.
Collision detection for Colliders.
The plan is to use my existing position/velocity system for all objects, I just need to know when they collide.
all I want is just to place a .observe on entity 1
check when it collides with entity 2
do stuff with where entity 1 ended up
ooor loop through all collisions that happened this tick
check if collider1 or 2 is entity 1 and vise versa
"collision happened"
but that feels like a bad aproach tbh
first thought
// .observe
query : Query<&entity1> // error[E0277] the trait `IntoObserverSystem` is not implemented
// then do
if query.contains(collider1){
// get position out of query this way
}
you could go either with parry or avian for this. Parry has no built-in broad phase, so if that matters to you you'd need to reimplement it which isn't trivial, but otherwise it has what you need. With Avian, if you're working with position/velocity and want objects to depenetrate, i.e. if two objects touch they don't enter one another's collider, you could use Kinematic bodies which have velocity/position set manually. You could also use sensors if you want no dynamics whatsoever and want to granularly control everything yourself.
fn my_system(query: Query<Entity, &MyMarkerComponent, &CollidingEntities>) {
for (entity, my_marker, colliding_entities) in query {
for other in colliding_entities {
// do stuff
}
}
}
Broad-phase was one of the problems I was hoping to farm out.
I'd stick with Avian then. If you are using none of the dynamics (i.e. no RigidBody::Dynamic), then the performance cost for the "extra parts" of Avian will be nil. Again, you can always put together your own plugin that excludes systems related to physics engine dynamics. The only concern would be extra binary size/compile time but unless your deployment target is a gameboy it won't matter.
do static rigidbody have forces
are static rigid bodies included when querying forces
if not
oh wait i could just
forces_query: Query<Forces>,
rigid_body_query: Query<&RigidBody>,
and does forces.apply_force(force) work on kinematic rigidbody
@vestal minnow ran into a weird obscure bug with avian2d.
I have a scene full of static rigidbodies, and their global translation is updated almost every frame (seemingly by avian, since if I remove the rigidbodies altogether it stops being updated), even if no entity in the scene is moving. It's a huge problem because their z is updated as well, and it seems to jump around a bit, e.g. entities have it set to 50.0 when they spawn, but some frames it changes to like, 50.00001 and then back the next frame.
I'm sorting the objects by their z and this is causing massive visual glitches :)
I feel like, at the very least, avian2d shouldn't touch or do any computations with the z value
hm apparently interpolation might be the culprit; @quick sluice can provide more details, it's their project that I encountered this on
So the visual glitch does not exist when the PhysicsInterpolationPlugin is set to default. It exists when the translation is extra - or interpolated.
I am using avian2d.
Hi, is there a way to change entity from static to dynamic rigidbody? Doing the other way around works perfectly with this code
commands
.entity(root)
.remove::<RigidBody>()
.insert(RigidBody::Static);
and trying to do the opposite like so makes entity ignore all the colliders and infinitely fall
commands
.entity(root)
.remove::<RigidBody>()
.insert(RigidBody::Dynamic);
if you remove the .remove::<_>() line does it work
hmm, it works this way, but that is not my actual issue. What i try to do is separate one dynamic body (root) without collider but with children that have colliders into 2 dynamic bodies, i initially used cloning but removed it to find the source of the issue. here group are those entities with colliders but without rigidbodies
let new_root = commands
.spawn_empty()
.insert((
RigidBody::Dynamic,
))
.id();
commands.entity(root).detach_children(&group);
commands.entity(new_root).add_children(&group);
and it still have the same issue as if i was removing and inserting
what if it's let new_root = commands.spawn(RigidBody::Dynamic).id();?
the same
it might be related to colliders Bounding Volume Hierarchy (BVH) or Islands
is there a way to temporary disable those to see if it fixes the issue?
also sometimes both old and new rigidbodies break and then one fall down and the 2nd one flies up
There can only be one component of a given type per entity so removing is redundant
Ok, so i was able to fix the issue via setting dynamic after reparenting; via setting dynamic in different system like so
let new_root = commands
.entity(root)
.clone_and_spawn_with_opt_in(|builder| {
builder.allow::<(Name, Transform, Visibility, RigidBody)>();
})
.insert((TransitioningToDynamic {},))
.id();
commands.entity(root).detach_children(&group);
commands.entity(new_root).add_children(&group);
#[derive(Component)]
pub struct TransitioningToDynamic {}
pub fn transition_to_dynamic(
mut commands: Commands,
ent: Query<Entity, With<TransitioningToDynamic>>,
) {
for entity in ent {
commands
.entity(entity)
.insert(RigidBody::Dynamic)
.remove::<TransitioningToDynamic>();
}
}
I am also not able to replicate with minimal setup
#[derive(Component)]
struct Root {}
#[derive(Component)]
struct Red {}
fn separate(
mut commands: Commands,
keys: Res<ButtonInput<KeyCode>>,
root: Single<Entity, With<Root>>,
red: Single<Entity, With<Red>>,
) {
if keys.just_pressed(KeyCode::Space) {
let root = root.into_inner();
let new_root = commands.spawn((Root {}, RigidBody::Dynamic)).id();
let red = red.into_inner();
commands.entity(root).detach_children(&[red]);
commands.entity(new_root).add_children(&[red]);
}
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands.spawn((
Root {},
Transform::from_xyz(0.0, 4.0, 0.0).with_rotation(Quat::from_rotation_x(1.)),
RigidBody::Dynamic,
children![
(
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
Transform::from_xyz(-1., 0.0, 0.0),
Collider::cuboid(1.0, 1.0, 1.0)
),
(
Red {},
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
MeshMaterial3d(materials.add(Color::srgb_u8(255, 144, 144))),
Transform::from_xyz(1., 0.0, 0.0),
Collider::cuboid(1.0, 1.0, 1.0)
)
],
));
}
oh, actually when i look at it, it inserts dynamic for dynamic too and that actually seems to fix those broken bodies
It seems to me that it its easier to make analytic collision solver for my special case, rather than try to fix mesh collisions. The reasons are:
- sphere colliders are literally stopped by ghost collisions even in a situations they are not supposed to collide, and this is 100% reproducible;
- fixing meshes does not helps;
- raycasting does works, but with caveats;
- for wheeled car, raycastsed "wheels" can stuck in the geometry on high speed, and without any tweaks are unable to recover;
- prismatic joints are not solving this problem at all, creating ghost "pull" forces, and pushing car with mass into the ground;
- the only way to solve this, is to create "kinematic" objects for the "wheel" joints, but this looks awful;
Maybe I'm doing something wrong, but I've tried different methods of handling and without any noticeable success. The last idea was on the ray cast enable collider, so prismatic joint would work correctly, but that would make system even harder to maintain
Basically i need hermite splines, they can be subdivided to find right "t" position, then i need reprojection into the extrusion slice, and I'll get correct solid, rather than hard-to-handle mesh
wdym stuck in the geometry
Imagine that wheel travels from "not inside track" into "inside track", raycasted "wheel" must apply correct impulse to move car chassis such that wheel will be lifted into the correct position above the surface. There can be a special case when raycast from the wheel position will be inside "ground" too.
Mesh is not solid, so I either have to create more raycasts from above, or do something else
let me make a screenshot
Basically it looks like this, wheel raycasts cant push car from the ground fast enough, so they are clipping
you mean the wheel model clipping?
yes, and that should not happen. there are cases when on the high speed whole wheels with raycast points go under the track, and there are no ways them to recover, because they are under the mesh, and cant register any collisions
especially this
Thats exactly why I'm complaining about it.
I cant use swept spherical colliders for the wheels, if they worked properly, that would solve all problems
do you need the wheels to be specifically outside of the car?
red box is a cuboid collider with swept ccd. and as you can see, even this dont solve issues with incorrect collision registration
yeah, but you can at least reduce the issue by making the rays start from inside that collider
it looks like I'm pushing current physics system waaay beyond its capabilities. analytical collisions would solve this task perfectly well, but I dont know where to start
try using shapecasts
i do spherecasts right now
for anyone doing car physics, this is interesting https://youtube.com/shorts/lsaTt030jVY?si=1AR8mFUwyZfX4m4c
shapecast with extra steps
yeah seems like more work both on compute and LoC
I refer people to this video if they want simple car physics
https://youtu.be/SKXqWcaoTGE?t=260
In this 2017 GDC talk, Naughty Dog's Edward Pereira breaks down individual physical elements that went into Uncharted 4's 4x4, such as tire collision response and the motor simulation, then explains how Naughty Dog tuned it to handle the rugged terrain of Madagascar.
Register for GDC: https://ubm.io/2yWXW38
Join the GDC mailing list: http://w...
hey everyone, wanted to ask if there is any way for a CollisionStart event to have a non-finite vec3 in avian3d in collisions.manifolds.first().points.first(). Not sure if it makes any difference but this would be for 2 kinematic objects with one having a much higher mass than the other
new video from 1 of developers of very very valet
In this video I explain the methodology and techniques I used to make the physical-yet-arcadey physics in my game Parking Garage Rally Circuit, including a (possibly misguided) observation about Mario Kart that influenced my entire process.
More about the game: https://www.walaber.com/parking-garage-rally-circuit
Chapters:
0:00 - What to Expec...
@dull dew @prisma raft @fathom cedar
Are there any areas where I can reduce the performance overhead of the physics engine itself? I am trying to run around 500 bevy worlds with each 200 objects (all in one process) and it seems like the cpu spikes mainly because of the physics overhead itself since 50 worlds with 2000 entities work fine. I have the exactly same result with rapier
parry supports sphere raycast out of the box, there are no problems with raycasting itself, but there are no reliable ways to do raycasts on high speed, such that bumps would be correctly simulated
already did that, im stuck with physics stability and collision detections for (at least) shperical colliders, that are not properly working
as I already said:
- I cant use spherical colliders because of phantom collisions/forces;
- I can simulate spring forces, BUT, there are two both non working ways
- prismatic joints are not supposed to work with the simulated raycasted "wheels"
- custom simulated joints suffer from ground clipping
it might work with simple scenes, but dont work at all with fast paced rally / racing game
Im using procedurally generated roads from the hermite splines, that are baked into the meshes at runtime. I cant do it offline (in any editor like blender or houdini), because level editor is supposed to work inside app
raycasted wheel is already a custom primatic joint, why would you combine them? or am i misunderstanding something?
Thats the essential question. The main problem is that car chassis must be pushed out of any collision surface without applying impulse and momentum. Its constraint solving, that is available only with joints. I cant just apply any (basically very large) impulse to move chassis out of the ground for exactly one frame and immidiately cancel it out. This also true for momentum
It basically a hard stopping constraint, that cant be simulated using phantom forces
why do you want to push chassis for 1 frame, do you need to make your car without any suspension?
I need suspension to work like:
- spring to absorb any impacts;
- damper, to avoid any oscillation;
- be preloaded, such that it will already have some force applied;
- also have HARD STOP (bumper), such that it cant be pushed any furhter
in case when suspension reached in min limit, it cant be pushed any further, and this is a hard constraint
only in this case car would not dive under the collision sufrace
...but all of that should already be handled by raycasted wheel
but it does?
how?
how does a spring not have a min length constraint?
or are we thinking of different things?
how you can ensure and apply force / impulse to correct situation when wheel is under the ground on the next frame?
why would it be underground in the first place?
because car is moving, and environment does have bumps and ramps. if car is moving fast, then without swept ccd you cant detect situation, when wheel is under the surface
thats why swept ccd exisits in the first place
this is kinematic picture. if wheel is under the ground, you cant just move car upwards without applying any force or impulse. its not how physics works
to avoid situations like this you have to apply hard constraint, such that movement beyond this limit is prohibited
when wheel hits bumps or ramps, it moves up, to whatever point shapecast hits, or do you mean the flat bumps where wheels would just look weird if they teleported?
how can you teleport wheel? i mean in physical sence, which impulse should be applied?
you can basically make wheel a kinematic body, such that it will have constraints, but thats extremely hacky and buggy
whats the point of physical engine in this situation?
wait, what point do you cast your shape from?
it does not matters, you can cast just from chassis
so are you trying to solve a visual bug, not physics?
its a physical bug in the first place
the only question is, how do you correct wheel and chassis position:
if due to high speed and without swept ccd wheel goes under the ground reaching below allowed min suspension lenght
you cant just apply impulses and forces, because it would work like a phantom force, and look ugly
so we've been talking about different things after all š« you're thinking about a collider, while i'm thinking about shapecast
either way if you'd run into a bump that's so high your wheels would have to be underground, the car should flip over instead
shapecast should behave exactly as collider in order to be consistent
there must be no frames then wheel visual is under the ground because shapecaster and suspension didn't had enough time to push car away from the ground
i mean, im not trying to write toy example. i want to make it look and work realistically
what kind of car though? in realistic scenarios you'd either crash the car itself, or the bump would just make you fly up
here is how it was fixed for kinematic bodies, its move and slide:
https://joonaa.dev/blog/12/avian-0-6
its basically move-and-slide case
If you really interested in digging into this case and helping me out, please write your own car model, and make it work. Otherwise i dont see any point in explaining it any further
for the reference, speed limits are like those: https://www.youtube.com/watch?v=zTYJJad6aJQ
i see, the ray/shapecast wheels weren't made for this case at all, but trackmania is a good example of how sticking to 1 genre for 20 years allows you to refine the mechanics š
I watched this yesterday! It's a good video breakdown of arcade style car physics. Did not realise he worked on very very valet.
English isn't my first language, so I want to understand exactly which parts of my explanations and clarifications might have been unclear.
I've tried to describe a specific issue with the engine that, so far, can't be resolved without writing my own physics handler. It is possible to extend the engine strictly for my specific needs, but I donāt yet know where exactly to start
they weren't just unclear, they were misleading š
i'm not sure how you'd extend it without fully understanding it first, so i think that'd be the start?
I've just re-read it again, and cant find any obvious flaw aside that actual case (very high car speed) is not mentioned
you were re-reading while understanding the context, and what your special case is
Can I take this to mean that the question was phrased in too technical a manner, without explicitly explaining why other approaches wouldnāt work, given the taskās complexityāwhich is unusual for hobby projects?
no, it means only what it said, your imagination filled the gaps while reading my message, just like your imagination filled the gaps while asking the questions š«
there are several quite interesting points on how to handle ground penetration, overall its great video, thanks!
I'm new to Avian- are there tools that would help me visualize the trajectory of a physical object? Think parabola of something shot out of a cannon while affected by gravity.
It's for debugging so happy to use bevy gizmos for showing the trajectory, but I'm wondering if Avian has anything to calculate paths like this.
I think perhaps this is equal to simulating the rigid body's position for the next N ticks?
I don't know that Avian really has built-in utilities to make this any easier- What's your usecase?
I'm testing Avian and I'm going to shoot some heavy projectiles (i.e. cannonballs) with some rng, and I'd like to be able to debug visualize their trajectories.
Could also be nice in a type of game where you plan to "lob" some object in an arc, and you want to let the player know the trajectory (pool/snooker, golf, ..)
So, I think most games do this by just using a shapecast (or even a raycast) that emulates the properties and simulation of the rigidbody
If it's parabolic all you have to account for is gravity, possibly with linear drag. You'd probably want to lock the rotation of the rigidbody entirely.
I'm not really aware of any physics engines that let you like, step a rigidbody into the future n times.
If you REALLY want a high-fidelity prediction I wonder if you could do a partial clone of the world and then run the physics schedule n times. But that's a lot more involved than a shapecast.
there are a few crates that do this in one form or another, mainly network crates which do it for rollback (part of rollback is stepping N ticks into the future, including physics)
Iāve also seen this standalone crate that seems to do exactly this: https://discord.com/channels/691052431525675048/1488695835486326866
but yeah an actual separate physics simulation to show the trajectory is not usually worth it, unless itās a very core mechanic of the gameplay and there are too many factors into play to just determine it directly
It's not a core mechanic, I just hoped there were some helpers for this in Avian to avoid papercuts like e.g. a future refactor in 6 months which changes linear drag somewhere else, gravity, or some unknown unknowns..
Yeah afraid the answer is no, and I think that would be the case for most physics engines frankly. I think it would honestly be a pretty cool feature though, like a predict_step of some kind where you can plug in various properties to get a prediction assuming the rest of the world is static.
Yep exactly, "where is this in N ticks assuming no other changes" would be very nice and help avoid creating crude emulations
yeah but i find that for a lot of games it's not just running physics but also other collision systems and such
which would be impossible to do predictively without proper simulation?
like a pinball bumper
Agreed which is why I'm guessing most physics engines don't have it.
Though for pinball you could use the "simulate the entire world forward by n frames" approach that the various networking libraries use.
yeah, at that point it would need to be entire world simulation
which wouldn't be relevant for physics
but it could be interesting maybe to atleast have a "project body x secs later"?
hmm, in the cannonball example it wouldn't help much i feel
yeah I think you really have 2 practical choices in the vast majority of games:
- shapecast n times, syncing up the length of the shapecast with the length of the delta, and reusing as much "game logic" as possible to make it mostly match how the rigidbody will behave
- clone-the-world and simulate into the future
I don't think a middle path really exists. I think the most useful thing would be to expose a RigidBody::integrate to make it easier to clone the integration of Lin/Angvel.
i think in cannonball case you don't need to simulate game logic too much
but you do need some sort of shapecast arc?
could also be cool for pool indicators
or maybe jumpking style rigidbody games?
pogostuck
trying to make radial gravity causes an infinite speed loop
this is following the example here
i believe it's because the acceleration is applied at the same direction throughout the timestep, and so when the ball moves + acceleration staying the same causes a push
possibly like this
reducing subset count seems to reduce but not mitigate the effect
i think true radial gravity would need a apply_linear_acceleration_towards(Vec2)
changing this to directly modify the linear velocity seems to work, as it's not applied continiously
what is direction.truncate()?
I see trunc() in the method docs but not truncate()
which appears to integer-ize each component by rounding down
yeah not sure why that is necessary?
maybe remove it?
i don't have it
oh that's the example my bad
I thought that was your code lol
yeah
if you're happy with the linear velocity approach go nuts, happy to read over your code if you want help with using Forces
the forces code is quite similar
just applying acceleration towards the center
im quite confident it's not possible to do with forces without modifying avian
im pretty sure this is the situation
I wonder if this is because of substeps
reducing substeps seems to reduce the effect
you could put the gravity inside the integration set and use the velocity as a second input
i almost wonder if this is something Avian should publicly expose as part of the API as this feels like a fairly common usecase that should be straightforward to get correct
Like a way to override or add to rigidbody integration like you can in Godot
what does this mean?
order the gravity system between something in the avian 'internals'
and use a gravity approximation that understands current velocity
@glossy holly https://docs.rs/avian2d/latest/avian2d/dynamics/solver/schedule/enum.SolverSystems.html#variant.PreSubstep
substepping isn't like an internal engine black box, it's a system set you can put your own systems in
System sets for the constraint solver.
you have to be careful to schedule them at the right time in the substepping loop
but it would let you access the actual position/velocity of the rigidbody during the substeps and update the direction of radial gravity to reflect the actual position of the body during substeps
yeah I feel like Avian should be exposing a public CustomIntegration schedule which you can assign systems to which run either before or after built-in engine integration, and maybe a DisableIntegration marker component to disable built-in integration or something like that
I think SubstepSchedule in particular is the one you'd want to run systems like this in
yeah im messing around with that but its breaking some of my other effects
we have a CustomPositionIntegration component, which is useful for e.g. custom movement logic using MoveAndSlide, but we don't currently have a CustomVelocityIntegration component
trying to run it before ApplyConstantForces currently applies a crash
actually no
hi john physics
we do have CustomVelocityIntegration :P
A marker component for bodies that use custom velocity integration.
A marker component for bodies that use custom position integration.
yeah
would it ever make sense to implement an "apply_force_towards" another body?
in engine
oh wait
i bet i could use a fixed joint with point compliance for gravity too if I wanted
lmao
that seems quite game-specific
yeah im fine with the velocity solve
the substepschedule solution seems to have problems
We should definitely add some examples for implementing radial gravity and gravity fields and whatnot properly
and possibly some first-party functionality
similar to Godot's area influence
Oh I totally missed those components
yeah scheduling in the internal schedules can be kinda tricky and also can change a lot between releases
if that wouldn't be proper, what would be?
referencing here
maybe having a PreSubstep/PostSubstep schedules could allow this functionality, and be more universally useful?
they already exist and aren't in the substep loop so they'd need a different name...
It's like "pre loop" and "post loop"
oh true forgot about those
yeah
I think PreSubstep is a better name for inloop tbf, feels closer to PreUpdate
Well it depends on the desired accuracy. I would start by just modifying LinearVelocity in FixedUpdate, but if that's not accurate enough (i.e. objects diverge from the orbit under radial gravity) then it could be integrated into the actual simulation loop, similar to what you're trying to do
linearvelocity is good enough for my usecase, but i think it is technically less accurate than applying a continuous acc or force
it is less accurate but whether that matters depends on the project
yeah but my original radial implementation following the example was quite noticable lol
troll physics 
yup that example isn't great hehe, like you speculated I think it's because the acceleration direction is only accurate for the first substep, since the direction remains constant across the substeps when it should really change as the shape orbits
and so the acceleration has a tangential component that speeds you up
even reducing it to a single substep still resulted in some acceleration, although less
same error will still be there if you use the same naiive approximation yeah
iirc there's a substantially better approximation made by just swapping the order of operations somehow
that's explicit vs. semi-implicit Euler (aka symplectic Euler)
semi-implicit is the stable one that most game physics engines use, Avian included
"stable" as in it preserves energy over long periods without artificially adding any energy
(but may dampen over time)
Would you accept a PR that adds a warning describing the details of this to the radial example and Forces?
IDK how exactly to approach adding custom integration to the substep but some extra docs might be helpful for the next time someone encounters tyjks.
I would maybe replace the radial gravity example for apply_linear_acceleration with something else altogether (maybe just a custom gravity field that points in some specific direction), since it can't really be used for good radial gravity as noticed by nukeexplosions
Ahh maybe with a note about non-constant force fields?
Yup it'd be good to have a warning about how the acceleration direction and magnitude remain constant across the whole physics timestep, which can result in inaccurate results for e.g. non-uniform gravity fields
I could also try messing around with adding a dedicated SystemSet for running systems at specific points in the substep, but I don't wanna overcommit lol
I think it would also be good to document the situation where you would modify linear_velocity rather than apply_linear_velocity?
Yeah for a more-accurate-but-not-perfect result that's easy to implement
you mean apply_linear_acceleration?
yeah
hmm not sure how useful modifying linear_velocity for acceleration would be outside of this usecase
but having to figure that out was still a little obtuse i guess
@vestal minnow I have noticed an issue where random meshes in my scene become visible. I tracked it down to avian3d::debug_render::change_mesh_visibility. store.is_changed fires a lot, even when no debug rendering is enabled (a UI system of mine is doing this). Should this function set visibility to Visibility::Inherited instead of Visibility::Visible, perhaps?
(Making that workaround works for me, btw. I can make a PR if needed) (I did it: https://github.com/avianphysics/avian/pull/981)
If I modify or insert a Collider, I assume that I have to wait until the next frame for the Collisions SystemParam to be updated in the event that modifications to that Collider result in it either beginning to, or ceasing collision with another?
Is there any kind of 'Collider Instancing'? If I spawn e.g. 1000 of the same colliders will it make a difference over spawning 1000 of different colliders(let assume that the total amount of vertices, indices etc. remains the same)
I don't think it's automatic but a lot of duplicates will make a difference. You can pool them manually by creating Colliders through Shapes that manually track a SharedShape. Avian uses Parry for shapes atm, so see https://docs.rs/parry3d/latest/parry3d/shape/struct.SharedShape.html which answers the questions in more detail.
A reference-counted, shareable geometric shape.
okay, more interesting question-
I know it's possible to run the entire PhysicsSchedule manually with world.run_schedule(PhysicsSchedule);
Is it possible to just run BroadPhase and NarrowPhase in order to update the contact graph?
I have a system that essentially wants to do all of the following in one frame:
- Perform spatial queries (raycasts), and then modify/add colliders depending on the results of those queries
- Recalculate the contact graph
- Do 1 again, until all modifications/additions are exhausted and the contact graph is stable and needs no further modifications (or an infinite loop is detected, in which case there is a special handler)
I'm gonna start with just running the PhysicsSchedule as many times as I need to, but I know that I don't need to run Solver, Sleeping, and SpatialQuery. All of the Colliders in question are Sensors, so dynamics will never be affected by this particular system (though it can indirectly affect dynamics ex. by applying forces to bodies, that can wait until the next frame).
(to give a more tangible mental image- I'm trying to resolve Ghostbusters-style laser beam intersections in 2d space. If there's a bunch of laser emitters, mirrors, splitters, etc. I need to calculate what the network of intersections actually looks like)
you could add a run condition to the unneeded systems;' sets
I think I would need to make a copy of PhysicsPlugin for that right?
'cuz I'd need to alter the initial registration of those systems
just app.configure_sets(PhysicsSchedule, PhysicsStepSystems::Solver.run_if(|r:Res<_>| r.should_solve()))
okay yeah and I essentially just set that resource's value at the beginning of my exclusive system and toggle it back off at the end
okay that's pretty straightforward...
following this approach, would you apply buoyancy unevenly by maybe applying the force at the average of the sampled points?
buoyancy forces can be applied at the center of displaced mass, which is pretty close
yup makes sense
water physics in avian2d
this is really cool
reminds me of a gamemode I used to play... I think it was in Team Fortress 2? Where the water would rise and the goal was to be the last one standing
may haveb een garrysmod
tyty
might need more drag
yeah I added configurable angular and linear damping that scales depending on % of body in the water
not going to have anything going quickly sideways on the edge?
I guess I could implement better drag but idk it's not super significant to my game
hey folks, wrote an Avian plugin for a Flight Dynamic Model: #showcase message
(I hope the crate name is ok, avian_fdm, it's not published yet, I'm happy changing the name if needed)
Anyone currently working on/maintaining an updated 0.19-dev branch? The one in PR#965 broke w/ the Bevy PR#24164 yesterday
Is there any recommendations for how to do ragdolling with .glb meshes w/ skeletons in Avian?
Would I have to just spawn my .glb -> find the entity in the world -> put the colliders on the bones?
i'd imagine it'd be easier to use Skein and attach the colliders there
I am very new to Bevy/Avian so I apologise if this is obvious, but is there a convenient way to "subtract" a shape from a collider (eg. take a cuboid collider and cut the bottom of a sphere out of it to create a "dish" shaped collider)?
nope
Alright, thanks
i have a hacked together solution of something similar by using collision filtering
but it creates somewhat janky behavior
It was just for a tiny procrastination toy anyway, more reason to just get on with my actual project š
i remember someone asking me something similar to this in the Godot server regarding a banana-shaped collider, I don't think any physics engines support this, but it does make me wonder what an SDF-based collision engine would look like and whether it would be really cool and useful or horrifically inefficient.
Maybe a project for the far future lol
ive seen a video about this actually
i think most people use sdf + marching cubes/squares approach
but sdf collisions are also possible
ive looked up on this before though
and subtract functions break the "validity" of an sdf
which doesn't work for pure sdf based physics
My motivation when starting this project was to build an engine that enables high fidelity modifications to world geometry during gameplay. In most games, the game world is relatively static. In the games where geometry is dynamic - like Minecraft or No Man's Sky - modifications to the world are usually relatively crude and low-fidelity.
My en...
here's someone that did marching cubes approach
so tl;dr is it's way more complicated than just using raw SDFs
here's the research i saw on raw sdf collisions
from what i understand though, they sample points on the sdf and gradient descent to find collision points
but they preallocate those points
which also doesn't work w dynamically generated sdfs
tldr pure sdf physics works but doesn't work w dynamic subtracts and such
someone had sdf colliders specifically in avian
Hi, I am someone š
My impl doesn't work on just any arbitrary combination of shapes. But if the goal is jist subtracting on some shapes rarely, turning it into a mesh is probably easier. Since then the rest of collision still work fine as-is
hihi can I see it
The more I do this the more I feel like a really good meshing algorithm ends up being the solution to a ton of problems in the videogame world.
Kinda like how a single excellent general-purpose database is often a better solution to most problems in the webdev world than a bunch of specialized options.
@vestal minnow ya ever gonna make use of your reserve? https://crates.io/crates/avian
crates.io serves as a central registry for sharing crates, which are packages or libraries written in Rust that you can use to enhance your projects
feels like should have the various avian's under it as features?
@untold peak are you planning to update your bsn branch to work on latest bevy soon? otherwise I might fork yours and fix the issues introduced last week so i can move to latest more easily
These are my changes from a branch off bevy main a few weeks ago
Iāve been waiting for the dust to settle on bsn with 0.19 release (not a RC) before doing a full migration in jackdaw
All good, I just updated off yours, going to put a PR up for parry to update glam so we can make it more simple
I put a PR up for parry to update to newer glamx and have an updated avian branch (starting with cherry picking your fixes) using that ā can put up a PR once I do a little more testing
When is Avian going to be compatible with Bevy 0.19-rc1?
Hopefully at some point yes, it's a bit awkward atm since the 2d and 3d features are mutually exclusive, so in that sense it's nicer to have them as separate crates
But if/when we refactor things such that 2D and 3D are more cleanly split and can be enabled simultaneously, it'd be neat to use avian
I believe @velvet patio was working on a branch for it (see the message above yours)
I've been sick this past week and also have other work to do, so I haven't had much time or energy for it. But I'm starting to feel better now, so hopefully we can get an RC release done in the next few days
I have one working w/ latest git main but needs some patching in your workspace.to use the parry branch I have on glamx 0.2ā¦
Your health is what matters most ā look after yourself first. Wishing you a speedy recovery.
I did put up https://github.com/dimforge/parry/pull/418 but it is just sitting there. Feel free to take my changes or I can put a PR up for avian if easier or helpful
Hey, Can I ask a question here? I have made my question on #1507360724102676671 message but not sure if someone who can maybe answer will notice over there. Thanks
Hope you get well soon. Remember that you are allowed to rest after getting sick š
I would like to save forces to the file and apply them to the player again when they load. How should I do it? I mean, just in avian, I have whole saving mechanism in place. What data should I save, and how should I reapply it again
Hi, could I get a reminder on which of Position or Transform should be used? Should Position considered internal to avian and the user should always be modifying transform?
Correct. Either you use Transform, or you disable the Transform -> Position propagation
funny seeing you ask this here since I look this up for Lightyear constantly and Iām pretty sure itās the opposite haha
(since like, Transform is used internally for interpolation so youāre generally expected to change Position, or just use forces, might be remembering it wrong though)
FWIW, there is a resource PhysicsTransformConfig where you can configure this logic. The default is to propagate Transform edits to Position and Position edits to Transform. along with a few other knobs.
imo use Position inside your physics schedule and Transform in Update
That depends on the avian mode used in lightyear. With mode=Transform, you are supposed to only interact with Transform. But I wanted to know what the recommendation is on the avian side
In general, Transform in user code, and Position inside the PhysicsSchedule
hi
so I got hit a perf cliff with ColliderTreeOptimization defaults that I feel is worth flagging. App streams in a few hundred Static trimesh terrain colliders from a worldgen pipeline. Worldgen runs heavy stuff on AsyncComputeTaskPool (density compute, meshing, BVH builds).
Chrome trace at defaults:
PhysicsSchedule total 36s (72% of update)
block_on_optimize⦠mean 36ms / tick, max 730ms
I have 20Hz physics, small tree, low moved_ratio. The optimization work itself doesnt seem expensive, the cost is the wait.
optimize_trees spawns onto AsyncComputeTaskPool (default use_async_tasks = true on native). My worldgen tasks were saturating that pool, so the optimize task got queued behind them. block_on_optimize_trees then sat on the main thread waiting for the queue to drain. As more frames piled up without optimize running, each eventual completion was catastrophic.
Flipped use_async_tasks = false:
PhysicsSchedule total 0.8s (1.6% of update)
optimize mean 0.79ms / tick, max 7.7ms
Same algorithm, same tree, same data. 45Ć drop on mean, 95Ć on max.
tldr; this just moves the work to the main thread synchronously. Cheap for my small static-terrain tree, but a larger / more dynamic tree would eat the cost directly into frame budget instead of (in the happy case) overlapping with simulation. So false isn't a strict upgrade, it just trades latency for predictability. my case benefits because the work itself is sub-ms but the async wait was unbounded under contention.
Default is reasonable when AsyncComputeTaskPool is mostly idle, but any app doing its own bulk compute on that pool hits this silently. Wondering if there's room for a dedicated pool, contention detection, or at least a doc warning?
Versions: avian3d 0.6.1, Bevy 0.18.1, Linux x86_64.
would be happy to get any pointers, suggestions, etc - I am still kinda new to all of these
Why am I gettings this warning? I have all the components in MassPropertiesBundle and the entity has a collider
Collider::circle(16.0),
Mass(10.0),
CenterOfMass,
AngularInertia,
Dynamic rigid body 1298v1 has no mass or inertia. This can cause NaN values. Consider adding a `MassPropertiesBundle` or a `Collider` with mass.
what's the entity's transform scale?
1.0, 1.0, 1.0
share spawning/mutation code?
Had a heightfield collider question. The terrain in my game is chunked. I have heightfield colliders for each chunk. I have some real time terrain deformation and currently have to rebuild the whole heightfield collider for the chunk.
Would it be possible for Avian to support partial updates of heightfield colliders instead of replacing the whole collider? (Not trying to demand a feature, just wondering if there are plans to do this)
Afaict parry doesn't support this, so unless it is added there, Jondolf has no real control over this (until peck is done, I guess?)
Damn okay š guess I could always fork Parry and Avian ><
This is very interesting! Would definitely be useful to mention this in the docs somewhere. If there's some way to detect contention automatically and fall back to the main thread, that could be good to try too.
I believe one of the problems here is that Bevy currently has a 50%/25%/25% split between Compute, AsyncCompute, and IO task pools, which means that any given operation can only be scheduled for a subset of threads. So even if you have lots of free IO or Compute threads, you're limited to just a few AsyncCompute threads, which in your case easily saturates the pool and leads to this contention. There's a PR that aims to fix it, but it's in draft :/
https://github.com/bevyengine/bevy/pull/20699
But yeah in your case I think it makes sense to set use_async_tasks: false. The idea with the async task is to hide the cost of the BVH rebuild/optimization by running it in parallel with the narrow phase and solver where the BVH is not needed. This is also what Box2D does. But the contention obviously makes it not worth it with how the task pools currently work
Yeah like Nise said, I don't think Parry has a way to mutate an existing heightfield other than setting the cell status or some flags related to internal edges. You can't move the actual vertices without reconstructing the heightfield afaik
I don't see a fundamental reason why it couldn't be supported, so I'll probably try to support it in Peck when we implement heightfields for it
Ooo thanks for the reply
it might be worth noting the warning only appears once when the entity spawns, not every update
#[derive(Component, Reflect, Debug)]
#[reflect(Component)]
#[require(
Sensor,
CollidingEntities,
RigidBody::Dynamic,
CollisionLayers::player_pickup(),
Collider::circle(16.0),
// setting mass to a non zero value (I tested 10.0) does not solve the issue
Mass::ZERO,
CenterOfMass,
AngularInertia,
Visibility
)]
pub enum Pickupable {...}
// Activated by a chain of observers started in `FixedUpdate`
commands.spawn((
Name::new("GiftPickup"),
Sprite::from_atlas_image( atlas.image.clone(), TextureAtlas { layout: atlas.layout.clone(), index: 80, },),
Transform { translation: transform.translation(), ..default() },
LockedAxes::ROTATION_LOCKED,
Pickupable::None,
CollisionLayers::player_pickup(),
MagnetizedPickup::default(),
GiftOnPickup,
GameEntity,
// tried adding computed on spawn but it didn't fix the issue
(ComputedMass::new(1.0), ComputedAngularInertia::new(1.0), ComputedCenterOfMass::new(0.0, 0.0),),
));
You're requiring default AngularInertia here, which I believe is zero. Mass and AngularInertia are only meant to be added (with non-zero values) if you want to override the values that are automatically computed for colliders
You shouldn't need any of those mass property components there unless you specifically want to set them
That body has a collider, so it should get some mass properties automatically
also see docs here for general mass property stuff
https://docs.rs/avian2d/latest/avian2d/dynamics/rigid_body/mass_properties/index.html
Mass property functionality for rigid bodies and colliders.
I believe another thing that can sometimes cause the warning is if the z component of Transform::scale is 0, that one is a bug
The issue is with the sensor component. Sensor doesn't require any components so why would that happen?
// no warning
#[require(
// Sensor,
CollidingEntities,
CollisionLayers::player_pickup(),
LinearVelocity::default(),
Collider::circle(16.0),
RigidBody::Dynamic,
Visibility
)]
your component requires default mass properties components so they will still be added.
ah okay so that is this subtle detail in the Sensor docs
https://docs.rs/avian2d/latest/avian2d/collision/collider/struct.Sensor.html
this is consistent with Unity and Godot, though it is a bit footgunny perhaps
So in this case you do need to manually set both Mass and AngularInertia :/ but both need to be set to a non-zero value
That worked, thank you!
you can also use MassPropertiesBundle::from_shape(&collider, 1.0) to derive all of the mass properties from the shape
either way works
Is there a reason (or am I doing something wrong) that I can't use &mut CollisionLayers in a query? For example
mut blocks: Query<(
Entity,
&mut MeshMaterial2d<ColorMaterial>,
&mut CollisionLayers,
)>,
gives the following error:
type mismatch resolving `<CollisionLayers as Component>::Mutability == Mutable`
required for `&mut avian2d::prelude::CollisionLayers` to implement `QueryData`
1 redundant requirement hidden
required for `(Entity, &mut MeshMaterial2d<ColorMaterial>, &mut CollisionLayers)` to implement `QueryData`
It works if CollisionLayers is not mut, but I need to change it in this system
CollisionLayers was made into an immutable component recently. In order to update it, use a mut commands: Commands system parameter and then commands.entity(your_entity).insert(CollisionLayers::new(...)). You shouldn't need to query for CollisionLayers at all unless you need to reference its previous state.
inserting a new copy will replace the old copy with the new one
Hey, is there a proper way to take control over the physics stepping of Avian? I want to run the systems of my simulation in lock-step with avian physics and want to be able to pause/resume the simulation.
My current solution feels a bit clumsy:
- pausing the Time<Physics> in the PreStartup
(Ideally I want to add the PhysicsPlugin/ insert the Time::<Physics> resource such that the physics does not run on its own in any schedule. It should only run "by hand") - running a "simulation_step" system that advances the Time<Physics> by a fixed delta and running (run_schedule) the PhysicsSchedule and my own SimulationSchedule on the world.
This simulation_step system runs only if the App is in SimulationState::Running.
The problem especially is for some reason I have to initialize the App in the SimulationState::Paused state, otherwise the whole program crashes at the start.
Okay, I solved the crashing issue, but is there a way to insert the Time::<Physics> resource paused?
hello, is there a way to have a transforming gravity effect per-entity?
kind of like GravityScale, except it's a Mat3A instead of a f32
i guess there's always the option of removing and replacing the system responsible for adding gravity in 0.19, but i was wondering if this was a planned feature
There's ConstantLinearAcceleration that is basically like a per-entity gravity
"constant" as in applied every frame continuously, you can still mutate it
oh so i can do like 0 gravity for everything by default and use that component for custom gravity instead?
you could do that yes
thanks!
np!
oh awesome that makes sense, thanks!
Maybe try
app.insert_resource({
let mut time = Time::<Physics>::default();
time.pause();
time
})
after adding PhysicsPlugins? If it still crashes, describing the actual crash message/reason would help too.
Oh, yes. That works. Thank you!
I fixed the crashing. I accidentally ran the PhysicsSchedule twice in a weird way I think. But it runs wonderfully now.
yay, https://github.com/dimforge/parry/pull/418 just got merged and parry 0.27.0 just got released that bumps glam, so that solves the dependency mess
i can update my avian branch and open a PR in a bit for 0.19
-# #[cfg(all(feature="2d",feature="3d"))] const _: () = break rust;
ngl but doesnt look like its going to get merged anytime soon, too many blockers š
yeahhh I don't know what the current plans are there, this PR has been (partially) adopted at least three times now and the original issue is over five years old at this point :P
hopefully something happens there sooner rather than later though
side effects of not being a game engine backed by AAA games and rich ass corporate companies ig /s
compile_error!() no?
or we could just make it trigger a spontaneous UB š
say it's ub and then have it rm -rf /*
I'm getting Collisions registered by the Collisions sys param before the colliding entities have actually moved to the point where the collision would be peformed (i.e. their transforms have not registered the new position)
This leads to the objects reacting to the collision before visibly colliding, especially noticeable in really fast objects
How can I work around this?
Easy thing to try first is to enable extrapolation