Skip to content

Allow users to read / write from all components of a given entity using an All WorldQuery types #4278

Description

@alice-i-cecile

What problem does this solve or what need does it fill?

From time to time, users want to fetch all of the components from a given set of entities.

To do so, they must use the EntityRef or EntityMut API, in an exclusive system.

Fundamentally though, there's no reason this must be done in an exclusive system: this does not impact resource data, and we can limit the archetypes affected when combined with query filters.

What solution would you like?

Create a All type that parallels the API of EntityRef.

This would enable users to write e.g. Query<&All, With<Networked>> in an ordinary system, allowing them to read from any component of the given entity.

This will require some interesting new logic around defining which fetches are needed, but should be relatively straightforward.

Alternatives considered

Initially, I thought we could use EntityRef and EntityMut for this by implementing the WorldQuery trait on them directly. However, EntityMut allows users to add components, which cannot be done in parallel due to the potential impacts on archetypes.

Without the ability to reuse the APIs, IMO it makes more sense just to create a new type and use the standard & vs &mut distinction.

Alternatively alternatively, we could instead use one of the more 🧪 ideas to allow for instant component addition / removals in parallel systems and then just use EntityRef and EntityMut, likely by deferring the archetype updates until the next sync point and storing new component data in a scratch space of sorts.

Activity

  1. added
    C-FeatureA new feature, making something new possible
    A-ECSEntities, components, systems, and events
    on Mar 21, 2022
  2. james7132 commented on Mar 21, 2022

    @james7132
    Member

    You can sort of do this with ReflectComponent, though this both requires Reflect impls, still requires an exclusive system, and is mostly for the dynamic case where the types are not known at compile time. However, I'm not sure what kind of use case for AllComponents would work where we know the types at compile time that isn't served by generic systems and the existing query type.

  3. alice-i-cecile commented on Mar 21, 2022

    @alice-i-cecile
    MemberAuthor

    Agreed, this would be dramatically more useful after we have dynamic components.

  4. maniwani commented on Mar 21, 2022

    @maniwani
    Contributor

    This will require some interesting new logic around defining which fetches are needed, but should be relatively straightforward.

    Pretty sure the only thing this query can return is the de-powered version of EntityRef/Mut.

    The type system doesn't allow queries to yield a mix of different component fetch tuples.

  5. mockersf commented on Mar 21, 2022

    @mockersf
    Member

    This would enable users to write e.g. Query<&AllComponents, With<Networked>> in an ordinary system, allowing them to read from any component of the given entity.

    Could you expand on how that would be used?

    fn my_system(
        query: Query<&AllComponents, With<Networked>>
    ) {
        for all_components in query.iter() {
            // how do you use this all_components?
        }
    }

    Without going full dynamic, you'll need to provide the concrete component type, so why not put it in the query anyway?

  6. maniwani commented on Mar 21, 2022

    @maniwani
    Contributor

    Maybe we trade concurrency for ergonomics and provide this as a separate SystemParam that just doesn't block resources.

    fn my_system(
        mut all: AllComponentsMut,
    ) {
        for (mut a, b) in all.query::<(&mut A, &B)>() {
            /* ... */
        }
    }
  7. changed the title [-]Allow users to read / write from all components of a given entity using an AllComponents API[/-] [+]Allow users to read / write from all components of a given entity using an `All` `WorldQuery` type[/+] on Mar 21, 2022
  8. alice-i-cecile commented on Mar 21, 2022

    @alice-i-cecile
    MemberAuthor

    Maybe we trade concurrency for ergonomics and provide this as a separate SystemParam that just doesn't block resources.

    This is better than nothing, but IMO the ability to additionally filter this down based on specific components is an important usability win. In most of the cases I can foresee (networking, saving), you're going to want to restrict this based on the presence or absence of a marker component.

  9. added a commit that references this issue on Jun 22, 2023
    70f91b2
  10. james7132 commented on Jun 22, 2023

    @james7132
    Member

    This still doesn't give mutable access to Entity components yet. We need a version of EntityMut that doesn't give access to structural mutations first.

  11. added this to the 0.12 milestone on Jun 22, 2023
  12. changed the title [-]Allow users to read / write from all components of a given entity using an `All` `WorldQuery` type[/-] [+]Allow users to read / write from all components of a given entity using `EntityRef` and `EntityMut` `WorldQuery` types[/+] on Jun 23, 2023
  13. changed the title [-]Allow users to read / write from all components of a given entity using `EntityRef` and `EntityMut` `WorldQuery` types[/-] [+]Allow users to read / write from all components of a given entity using an `All` `WorldQuery` types[/+] on Jun 23, 2023
  14. added a commit that references this issue on Aug 29, 2023
    bc8bf34
  15. added a commit that references this issue on Jan 9, 2024
    77d0070
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ECSEntities, components, systems, and eventsC-FeatureA new feature, making something new possible

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions