Conversation
|
In light of #12660, I would vote against adding more panicking shorthands like |
cBournhonesque
left a comment
There was a problem hiding this comment.
Would this also allow for
let (mut a, mut b) = world.entity_mut(SOME_ENTITY).components_mut::<(&mut A, &mut B)>();
?
Maybe we can add a unit test for that case as well
Co-authored-by: Periwink <charlesbour@gmail.com>
Co-authored-by: Periwink <charlesbour@gmail.com>
I think discouraging unwrap/panicking variants entirely (as in, not providing impls) would have pretty nasty ergonomics implications for people, especially with the current Option vs Result compatibility problem for |
I agree somewhat with this. It's frustrating when something like |
|
Left some replies in #12660 |
| ); | ||
| assert_eq!(None, world.entity(e2).get_components::<(&X, &Y)>()); | ||
| assert_eq!(None, world.entity(e3).get_components::<(&X, &Y)>()); | ||
| } |
There was a problem hiding this comment.
can you add a test to make sure it returns none or panics if you do world.entity_mut(e).get_components_mut::<&mut X, &mut X>()?
There was a problem hiding this comment.
also should have one for (&mut X, &X)
There was a problem hiding this comment.
Haha I'm so glad you asked this question. The Access part of the Query infrastructure was what enforced this elsewhere, so this was allowed. We can't merge this as-is, and fixing it will almost certainly incur a significant perf cost.
There was a problem hiding this comment.
Wouldn't creating an empty access and calling update_component_access(state, &mut access) on it work?
There was a problem hiding this comment.
It would. It would just be dissatisfying from a perf perspective because Access allocates.
There was a problem hiding this comment.
FYI I have a PR that removes the allocation from an empty Access: https://github.com/bevyengine/bevy/pull/14026/files which might unblock this?
Or maybe not.. calling update_component_access will itself allocate by updating the bitsets
There was a problem hiding this comment.
Could the allocation not just be removed in the meantime by using a smallvec that has 8 items or something?
| } | ||
|
|
||
| /// Returns read-only components for the current entity that match the query `Q`. | ||
| pub fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'w>> { |
There was a problem hiding this comment.
Should add some docs to explain why it might return None. Ditto for the other methods that return an option.
james7132
left a comment
There was a problem hiding this comment.
I find this kind of funny. Thinking about this historically, this feels like we've inverted the relationship between Query::get_component and EntityMut/EntityRef with this change.
I think discouraging unwrap/panicking variants entirely (as in, not providing impls) would have pretty nasty ergonomics implications for people, especially with the current Option vs Result compatibility problem for ?. I would be very uncomfortable removing those apis right now.
I agree that we probably shouldn't remove them until try-blocks or some equivalent are stabilized.
| .get(location.archetype_id) | ||
| .debug_checked_unwrap() | ||
| }; | ||
| if Q::matches_component_set(&state, &|id| archetype.contains(id)) { |
There was a problem hiding this comment.
Could use bool::then instead of the if/else here.
|
Since this uses
"components" sorta makes sense for Option/Has... Is Entity a component though? What if QueryData gets implemented with more Component-adjacent stuff in the future? I'm guessing the next steps item 2 would be renaming these to the |
Haha yeah thats an interesting comparison. Although I think this is significantly more defensible / necessary than
Yup!
Yup that is something discussed in the Next Steps section above. Haven't thought of a better interim name. And |
|
Welp this PR is sadly stalled until we sort out this problem: Not sure there will be a solution that doesn't involve doing access checks on each call. |
|
I think the best we can hope for is "allocation free check every entry against every other entry" (similar to |
alice-i-cecile
left a comment
There was a problem hiding this comment.
I'm in favor of this existing! I agree with the request for more thorough docs (shock). Nonblocking, but I also think we should be returning Result, not Option here (as with most of our ECS APIs). QueryEntityError looks like the closest fit, but would need to be tweaked to better fit the actual problems encountered (and API used).
Obviously the UB is a blocker here on this getting merged. Given the discovered complexity, I'm removing this from the 0.14 milestone <3 I still want this, and if it makes it it makes it, but it's not correct to try and wait for this to be resolved.
|
I think we should be able to reuse the access mechanisms from queries to validate soundness here. Would need to sit down with the code to figure out exactly how. I much prefer that over creating another mechanism though, especially since I'd like to be able to add untyped variants to this in the future. |
|
Would it be possible to merge a version of this PR with just the immutable |
|
I agree the an immutable form would be useful still. Feel free to spin off a PR that does that please. |
|
Closing in favor of #15089; further attempts to implement the mutable form will be easier in a separate PR. |
# Objective Smaller scoped version of #13375 without the `_mut` variants which currently have unsoundness issues. ## Solution Same as #13375, but without the `_mut` variants. ## Testing - The same test from #13375 is reused. --- ## Migration Guide - Renamed `FilteredEntityRef::components` to `FilteredEntityRef::accessed_components` and `FilteredEntityMut::components` to `FilteredEntityMut::accessed_components`. --------- Co-authored-by: Carter Anderson <mcanders1@gmail.com> Co-authored-by: Periwink <charlesbour@gmail.com>
# Objective Provide an unsafe way to get mutable access to multiple components from an EntityMut. This is the API proposed in #13375, but marked `unsafe` as it does not check for conflicting access. ## Solution Add `unsafe fn get_components_mut_unchecked(&mut self) -> Option<Q::Item>` and `unsafe fn into_components_mut_unchecked(self) -> Option<Q::Item>` to `EntityMut` and `EntityWorldMut`.
|
Ultimately fixed by #21780. |
Objective
Implements #13127
EntityRef/EntityMutusage is currently unnecessarily verbose and borrow-checker-constrained. It is currently impossible to useEntityMutto get mutable references to more than one component at the same time:This makes
EntityMutsignificantly less useful than it could be. Querying necessary components on demand is a pattern many prefer to use over traditional top-level queries.Solution
Implement new
get_componentsandcomponentsmethods forEntityRefandEntityMut(and mutable variants forEntityMut) to provide multi-component access:This is implemented using our existing Query implementation to provide multi-component access. It checks access without actually computing QueryState / access using the very convenient
Q::matches_component_set.Next Steps
FilteredEntityRefandFilteredEntityMutvariants, as checking that access is actually more challenging (and with the current methods, likely prohibitively expensive because I think we need to computeAccess<ComponentId>)componentstogetandget_componentstotry_getrenaming / unification I proposed in AddEntityMut::componentsandEntityRefandEntityWorldMutequivalent #13127 as I suspect that will be more controversial, and it also touches a lot of code.Changelog
Added
EntityRef::components,EntityRef::get_components,EntityMut::components,EntityMut::get_components,EntityMut::components_mut, andEntityMut::get_components_mut.Changed
FilteredEntityRef::componentstoFilteredEntityRef::accessed_componentsandFilteredEntityMut::componentstoFilteredEntityMut::accessed_componentsto avoid future name clashesMigration Guide
FilteredEntityRef::componentstoFilteredEntityRef::accessed_componentsandFilteredEntityMut::componentstoFilteredEntityMut::accessed_components