-
-
Notifications
You must be signed in to change notification settings - Fork 260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rapier context as a Component #545
Conversation
example from dimforge#328 Co-authored-by: Anthony Tornetta <[email protected]>
Co-authored-by: Anthony Tornetta <[email protected]>
I'm reaching a point where I'm confident with the pull request, feedback is most welcome :) |
} | ||
// Verify link is correctly updated for children. | ||
let new_rapier_context = world.spawn(RapierContext::default()).id(); | ||
// FIXME: We need to wait 1 frame when creating a world. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this still a problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I... believe so. I'll try to track down why exactly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd love a test for that specifically ; I'd love to update this test to be able to test exactly a new RapierContext
in the same frame, but I'm not sure on where to insert the user systems exactly for that. Last
seems wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! I'm looking forward to this becoming the standard API!
Could we add an easier way to change the fields of RapierContext during its initialization (for the single default-world approach)? Currently I have to write a system that at startup changes those fields, but that seems a bit clunky. Maybe provide the |
) { | ||
for (entity, new_physics_world) in &q_changed_worlds { | ||
let context = q_context.get(new_physics_world.0); | ||
if new_physics_world.is_added() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This caused errors for me, where the rapier link wasn't propagating down to children. Not sure why this check is here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My initial mental model was that this function is responsible of reacting to rapier context change ; addition is handled within init_rigid_bodies
and similar functions.
You're correct though, the initialization is lacking the children propagation, I'll see what I can do.
I think keeping a similar logic is easier to reason about 🤔, rather than making an big system responsible for both initializing and update to link changes.
pub struct TestMarker; | ||
|
||
#[test] | ||
pub fn hierarchy_link_propagation() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole test could be in another PR to explore ; I think that's an interesting approach to fully master the system ordering. @AnthonyTornetta, this is the direction I'm taking to address your feedbacks on state inconsistencies (mainly hierarchy propagation, not currently tested but I'll probably add it in that way).
It's full of println! ; I quite like those because it helps debugging the tests ; and it's captured anyway. I'm glad to refactor this with specific instructions if need be. @sebcrozet for info.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking great! Thank you @Vrixyz, @AnthonyTornetta and @Aceeri for the work and reviews!
CHANGELOG.md
Outdated
- `ResMut<mut RapierContext>` -> `DefaultRapierContextAccessMut` | ||
- `Res<RapierContext>` -> `DefaultRapierContextAccess` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just a suggestion. Bevy has these Read<>
and Write<>
structs. Perhaps, to make the API look more idiomatic the access structs could be named as follow?
- `ResMut<mut RapierContext>` -> `DefaultRapierContextAccessMut` | |
- `Res<RapierContext>` -> `DefaultRapierContextAccess` | |
- `ResMut<mut RapierContext>` -> `WriteDefaultRapierContext` | |
- `Res<RapierContext>` -> `ReadDefaultRapierContext` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TL;DR: ok :)
I tend to prefer suffixes to prefix, so when you're searching for a term, the alphabetical order comes better grouped.
That said, my initial naming does a bad job at putting Default
first. For this reason, I might prefer a RapierContextDefaultRead
; but that would probably mean renaming DefaultRapierContext
to RapierContextDefault
, which might sound weird.
For the idiomatic way, I wanted to keep close to Res
/ ResMut
, which is very idiomatic. I believe Read
/Write
is used for individual components, which is not exaclty the case here. I'm not sure I've seen it in SystemParam
. But I'm not sure.
In any way, I don't feel too opinionated about that, so I'll just implement your suggestion 😅.
interesting to note differences of system ordering compared to master (from #576) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking fantastic, thanks!
This reverts commit bab3431.
Alternative to support multiple worlds: #328 + lays out the foundation to split
RapierContext
in multiple elements #502, still grouped in an entity.SystemParams
for aDefaultRapierContext
, the migration for most users is painless.Solved blockers
Fixed by #563
These crashes have been observed, analysis within Vrixyz#26.
Collision panics
Details: Rapier plugin is in
PostUpdate
schedule, usingTimestepMode::Interpolated
.log
Different occurence
Strengths
RapierContext
as component avoids maintaining our own indices for worlds, and groups up the dependencies of aRapierContext
in the same entity. I believe it will be most helpful when ECS relations will be a thing.Weaknesses
if let else
.RapierContextEntityLink
on every rapier entitiesRapierContext
-> its acces is simplified withRapierContextAccess
RapierConfiguration
-> as its usage is more advanced, I think it's fine to keep it in queries.RenderToSimulationTime
-> same asRapierConfiguration
RapierContext
entity leads to iteration to all entities for each worlds even though it’s not necessary 🙁 (writeback for example)RapierContext
is not trivial, and we should evaluate regressions.For now all systems share all these things, which I consider low priority to specialize for each
RapierContext
(them being components would be interesting but not trivial):DebugRenderContext
enabled
flag as a component on eachRapierContext
.Testbed
usesDefaultRapierContextAccess
, I think that’s OK.Performance analysis
Overall, This pull request doesn't seem to impact significantly the performance based on selected benchmarks:
Comparison with adapted benchmark with baseline from: #551 :
Cubes "master"
Cubes "This PR"
many_pyramids3 "master"
many_pyramids3 "This PR"
custom_benches "master" 59477d9
custom_benches "This PR" deb0a06