-
-
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
Multiple worlds/pipelines #328
Multiple worlds/pipelines #328
Conversation
This has been updated to bevy 0.10 |
Also added world_id in event
I've made some updates while updating this branch to not have any conflicts, two of which will change the public API:
|
Thanks again for your ongoing discussion on this topic ! For information, I'm starting to study The exact details of these improvements are still being worked on, and I'd like to familiarize myself with the design implications and understand in practice the changes necessary for supporting multiple worlds, so I'll be exploring on my own branch from master. For multi-world feature, I will probably transition I think this particular Pull Request is unlikely to be merged as-is, but thanks again for the work which will prove handy to compare approaches, and the discussions to find a good path forward ! |
pub collision_events: RwLock<EventWriter<'a, CollisionEvent>>, | ||
pub contact_force_events: RwLock<EventWriter<'a, ContactForceEvent>>, | ||
pub collision_events: &'a mut RwLock<Vec<CollisionEvent>>, | ||
pub contact_force_events: &'a mut RwLock<Vec<ContactForceEvent>>, |
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.
That's a good change in my opinion 👍 , it helps with support for multi world and we don't need a whole EventWriter
there anyway.
colliders | ||
.get(handle) | ||
.map(|co| Entity::from_bits(co.user_data as u64)) | ||
.or_else(|| self.deleted_colliders.get(&handle).copied()) | ||
.expect("Internal error: entity not found for collision event.") |
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 imagine that's a good change to allow users to come back from errors, but if we're returning None
, isn't that a sign we did a system ordering mistake ?
I agree that moving forward with the "componentization" of I will continue to keep this branch updated for now, since I am using it in my own project. Thanks for taking interest in supporting multiple worlds! I'm sure a lot of people (besides me) will appreciate it. |
events.is_some(), | ||
hooks, | ||
time, | ||
sim_to_render_time, |
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'm not sure sharing SimulationToRenderTime
between all worlds will still yield useful results. I think we'd want it to be specific to each world.
example from dimforge#328 Co-authored-by: Anthony Tornetta <[email protected]>
example from dimforge#328 Co-authored-by: Anthony Tornetta <[email protected]>
example from dimforge#328 Co-authored-by: Anthony Tornetta <[email protected]>
@@ -0,0 +1,111 @@ | |||
//! Systems responsible for interfacing our Bevy components with the Rapier physics engine. |
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.
Thanks for putting those in a separate file 👍 The comment seems a bit off but I'll look into the rest of the code for my own multi-world support attempt :)
/// assuming the child is hit by the full velocity of the parent instead of `parent vel - child vel`. | ||
/// | ||
/// This will not change the bevy component's velocity. | ||
pub fn sync_vel( |
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 assume this is to address #383
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 could be stripped out of this PR for sure, it is not at all necessary for the worlds changes.
/// | ||
/// If this fails to happen, weirdness will ensue. | ||
pub fn on_add_entity_with_parent( | ||
q_add_entity_without_parent: Query<(Entity, &Parent), Changed<Parent>>, |
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 imagine we should filter for any handles or existing PhisicsWorld, this query risks iterating through a lot of entities (probably especially UI)
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 absolutely agree, I believe when I made that I was just worried about missing any child hierarchy changes. IE: If this entity's children were in the physics simulation, I would want to change its children to reflect the new world they should be a part of. I don't think this is an especially common usecase, I just didn't want any unexpected functionality to be present.
.before(TransformSystem::TransformPropagate), | ||
.before(TransformSystem::TransformPropagate) | ||
.after(systems::sync_removals), |
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.
interesting change, do you remember the rationale ?
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.
If I remember correctly, I did that to prevent any of the init_* systems from running before sync_removals had finished. I believe I was running into inconsistencies in that regard without this being set, causing stuff to be removed after it had been re-added to the proper world.
Closing in favor of #545 |
This closes #221 by allowing multiple worlds to be used in parallel.
Reasoning
Currently, bevy_rapier restricts its usage to a single world per game, which is limiting in many situations, despite rapier itself having no restriction on the amount of worlds it supports. This PR changes
RapierContext
to instead store a list ofRapierWorlds
which hold whatRapierContext
used to hold. Each world is addressable be a uniqueWorldId
, which can be attached to any entity via thePhysicsWorld
component. The physics world simply stores the world's id.Goal
The goal of this PR was to add support for any number of worlds to bevy_rapier with minimal breaking changes to projects already using this that are content with only one world. The only changes that will be made to such projects are as follows:
DEFAULT_WORLD_ID
provided as the first argument and you will need to call.expect("The default world should always exist")
before using their result.context.(get_world/get_world_mut)(DEFAULT_WORLD_ID).expect("Default world should exist").field_you_wanted
Example
I have provided a 3d example of the multiple worlds in action in
multi_world3.rs
.Each of those platform/block pairs is in its own physics world, where they do not interact with each other.
A GIF of a cube changing its world every 3 seconds and moving between platforms in different worlds found in
change_world3.rs
:PhysicsWorld
This is a component that may be attached to any entity where you want to specify its world. If this component is omitted, the entity will be added to the DEFAULT_WORLD_ID world, which is present in every game. If this component is attached, the entity will be added to the specified world. If the component is modified, the entity should switch the world that it is in to reflect the id it was changed to.
To add or remove a world, just use
RapierContext::add_world
andRapierContext::remove_world
respectively.