You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue is to discuss an ergonomics issue that I've faced both in Bones ECS and in Bevy ECS, and to explore whether or not there's a good solution.
The scenario is simple:
I have a custom system parameter named CollisionWorld that contains helper methods and logic around detecting collisions and manipulating the physics world.
As a part of that CollisionWorld parameter, I borrow the Transform components mutably. This allows me to, as a part of collision world methods like translate move entities, and also to get the entities positions, as is necessary for collision detection.
This causes an ergonomics problem when any the user wants to include both a CollisionWorld system param, and a CompMut<Transforms> system param, because that is a conflict: you have two mutable borrows of Transform components.
The current solution in my WIP branch in jumpy is to make the transforms: CompMut<Transform> field of CollisionWorld public. This allows you to access a borrow of the transforms, but it's not a perfect solution, and users are not going to expect that it's impossible to borrow both their own transforms argument, and the CollisionWorld.
Also, considering the situation where the CollisionWorldand another system parameter needs to borrow CompMut<Transform>, there is no good workaround.
This is partially just a limitation of the way borrowing works. The issue is "solved" in Bevy using ParamSets which usually feels un-ergonomic, but again, there's only so much we can do in Rust, where we must make our borrowing intentions clear at compile time. We can't have two mutable references to the Transform components at the same time. The only way around this is to delay the actual borrowing of the components, requiring an extra lock()/borrow() step.
Maybe we make a Defer system parameter, that wraps around other system parameters, deferring the borrow, and requiring an extra borrow() call to do runtime borrow checking later in the function.
In that case you would be allowed to have transforms: Defer<CompMut<Transform>> and collision_world: Defer<CollisionWorld> in your system params, but you would have to .borrow() them before you could use them, and you wouldn't be able to .borrow() them at the same time without a panic at runtime.
Or we make an equivalent to ParamSets in Bones?
Finally, another alternative, is to have CollisionWorld use it's own component to represent the entity positions, and this component must be synchronized somehow with the Transform component. This is also a foot-gun because it's easy to forget to synchronize the values, and that there is in fact a separate CollisionWorld version of the entity position.
This discussion was converted from issue #86 on February 07, 2023 19:23.
Heading
Bold
Italic
Quote
Code
Link
Numbered list
Unordered list
Task list
Attach files
Mention
Reference
Menu
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
This issue is to discuss an ergonomics issue that I've faced both in Bones ECS and in Bevy ECS, and to explore whether or not there's a good solution.
The scenario is simple:
I have a custom system parameter named
CollisionWorldthat contains helper methods and logic around detecting collisions and manipulating the physics world.As a part of that
CollisionWorldparameter, I borrow theTransformcomponents mutably. This allows me to, as a part of collision world methods liketranslatemove entities, and also to get the entities positions, as is necessary for collision detection.This causes an ergonomics problem when any the user wants to include both a
CollisionWorldsystem param, and aCompMut<Transforms>system param, because that is a conflict: you have two mutable borrows ofTransformcomponents.The current solution in my WIP branch in jumpy is to make the
transforms: CompMut<Transform>field ofCollisionWorldpublic. This allows you to access a borrow of thetransforms, but it's not a perfect solution, and users are not going to expect that it's impossible to borrow both their owntransformsargument, and theCollisionWorld.Also, considering the situation where the
CollisionWorldand another system parameter needs to borrowCompMut<Transform>, there is no good workaround.This is partially just a limitation of the way borrowing works. The issue is "solved" in Bevy using
ParamSetswhich usually feels un-ergonomic, but again, there's only so much we can do in Rust, where we must make our borrowing intentions clear at compile time. We can't have two mutable references to theTransformcomponents at the same time. The only way around this is to delay the actual borrowing of the components, requiring an extralock()/borrow()step.Maybe we make a
Defersystem parameter, that wraps around other system parameters, deferring the borrow, and requiring an extraborrow()call to do runtime borrow checking later in the function.In that case you would be allowed to have
transforms: Defer<CompMut<Transform>>andcollision_world: Defer<CollisionWorld>in your system params, but you would have to.borrow()them before you could use them, and you wouldn't be able to.borrow()them at the same time without a panic at runtime.Or we make an equivalent to
ParamSets in Bones?Finally, another alternative, is to have
CollisionWorlduse it's own component to represent the entity positions, and this component must be synchronized somehow with theTransformcomponent. This is also a foot-gun because it's easy to forget to synchronize the values, and that there is in fact a separateCollisionWorldversion of the entity position.Beta Was this translation helpful? Give feedback.
All reactions