Skip to content

Conversation

@cBournhonesque
Copy link
Contributor

@cBournhonesque cBournhonesque commented Oct 23, 2025

Objective

We want to be able to run queries that span multiple entities, for example:
Get the Name of entities with Spaceship, that are DocketTo entities with Planet
(which is roughly Query<(&Name, DockedTo<(), With<Planet>>), With<SpaceShip>)>

It is already possible to do this by using multiple queries in a system, but the search can be more efficient is a single query is aware of all the constraints between the multiple sources.

Here we use 'source' to designate an entity for which we are trying to fit a constraint.
In bevy, all the current queries are single-source: we are iterating through entities that fit the constraint Query<D, F>.

For multi-source queries, you iterate through tuples of entities that fit the constraint.
For example Query<(&Name, DockedTo<(), With<Planet>>), With<SpaceShip>)>, iterates through all pairs (E1, E2) where
E1 satisfies Query<(&Name, With<SpaceShip>), E2 satisfies Query<(), With<Planet>> and E1/E2 are linked with DockedTo(E1, E2).

Solution

This PR currently adds everything in a separate file that doesn't interact with the rest of the codebase because:

  • the current QueryState/QueryIterationCursor makes some assumptions that only work for single-source queries
  • the PR is WIP, and I am still unsure if we want to

It adds:

  • a QueryPlan which contains an untyped way of representing the multi-source query, as well as a QueryPlanBuilder.
    The query is built like so:
builder
   .add_source<D, F>()   // source 0
   .add_relationship<R>(0, 1)    // relationship from source 0 to 1
   .add_source<D2, F2>()     // source 1
   .add_relationship<R2>(1, 2)   // relationship from source 1 to 2
   .add_source<D2, F2>()     // source 2
  • A function QueryPlan::query_iter() which returns an iterator that returns the tuple of entities (one entity per source) that matches the query. The item we return is actually a tuple of UnsafeEntityCell; we could convert it to a tuple of FilteredEntityRef/Mut (if the query has dynamic components) or a tuple of (D1, D2, D3) (one typed-data per source).

Soft limitations (these are not real blockers, they were just not implemented in this prototype)

  • only supports Relationships, not RelationshipTarget
  • doesn't support sparse sets
  • performance depends a lot on the correct ordering of the query terms in the query plan, and there is no compilation/optimization step

Bigger limitations

  • uses the FilteredAccess to check if the query matches the archetype, so doesn't support non-archetypal filters and some QueryData. To fix this we could either add these concepts in the dynamic query plan ?

Todo

  • only tested with a single case, I am sure that the current logic is incorrect.
    -> I don't update the VariableState correctly on backtracking!!
    -> I don't update the written correctly on backtracking!!

  • one long-term goal could be to switch ALL existing queries to use this approach, in which case the QueryState and QueryIterationCursor would be modified? All existing queries would become a one-source QueryPlan. The difficult part would be check how we can encode all existing QueryData/QueryFilter implementations in the QueryPlan.

@cBournhonesque cBournhonesque added the A-ECS Entities, components, systems, and events label Oct 23, 2025
Added support for relationships in both directions.
Added more complicated backtracking logic and tests.
Added support for relationships in both directions.
Added more complicated backtracking logic and tests.
@alice-i-cecile alice-i-cecile added C-Feature A new feature, making something new possible X-Controversial There is active debate or serious implications around merging this PR M-Release-Note Work that should be called out in the blog due to impact S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Oct 27, 2025
@github-actions
Copy link
Contributor

It looks like your PR has been selected for a highlight in the next release blog post, but you didn't provide a release note.

Please review the instructions for writing release notes, then expand or revise the content in the release notes directory to showcase your changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-ECS Entities, components, systems, and events C-Feature A new feature, making something new possible M-Release-Note Work that should be called out in the blog due to impact S-Needs-Review Needs reviewer attention (from anyone!) to move forward X-Controversial There is active debate or serious implications around merging this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants