Description
Overview
Inspired by flecs, relations are a first-class graph primitive for the ECS: useful for modelling generalized hierarchies, graphs and so on in a safe, fast and ergonomic way by working with the ECS, rather than fighting it.
These have three main categories of benefits:
- Ergonomics: query for entities with specific relation types and iterate over the various relations
- Correctness: enforce critical logic invariants (such as "each child must have a parent" or "each child can only have at most one parent")
- Performance: operate more quickly, especially compared to naive hand-rolled implementations
Challenges
There are several critical challenges that need to be addressed by any design:
- Performance: ECS is designed for random-order linear iteration
- Serialization: entity ids are opaque and ephemeral
- Ergonomics: there's a lot of interesting and important things you may want to do
- Graph structure: how do you ensure that the rules of the graph that you want to represent are enforced upon creation, and stay correct as components and entities are added and removed. Some graphs may be directed, some may be symmetric, some may have edge weights, some may be acyclic, some may be trees, some may be forests...
- Multiple edges from / to the same entity: this is an essential use case, but entities can (currently) only have one of each component type.
Possible paths forward
Essential universal tasks:
- Thoroughly benchmark existing tools and strategies for working with graphs of entities
Optional universal tasks:
- Allow entities to store multiple components with the same type #1527
- Investigate further optimizations for
query.get()
- Allow
Option<Entity>
to use memory layout optimization #3022
Index-driven approaches:
- Create one or more reasonably performant graph-storing indexes
- Implement a complete, ergonomic indexes solution (see Fast Component Lookup-by-Value with Indexes #1205)
Broadly speaking, there are two paths to this design:
- Index-based: Store the graph in a resource, keep that resource up to date. Use that resource to ensure constraints aren't broken, and enable fast look-up.
- Baked-in: Reframe components as relations with no targets. Reshape the ECS to support relations as the first-class primitives.
In both cases, these implementations details would be hidden to the end user.
Ultimately, we want to build an API that broadly follows the one outlined in bevyengine/rfcs#18 if at all possible.
Atomic indexes
- Make the schedule less of a nightmare using Stageless: a complete scheduling overhaul rfcs#45
- Implement atomic groups ala Atomic schedule groups rfcs#46
- Implement a full indexing solution, using the automatically scheduled cleanup systems seen in Fast Component Lookup-by-Value with Indexes #1205.
Permissions and hook indexes
- Create a permissions and hooks framework, which only allows certain components to be accessed with the appropriate components, and can do cleanup work on component removal (see this early design doc)
Non-fragmenting relations
- Revive Entity Relations #1627
- Alter the internals so the indexes no longer fragment archetypes by default
- As a result, remove the ability to quickly filter by target
Related work and issues
This topic was discussed at great length in bevyengine/rfcs#18. The consensus there was that the feature was incredibly useful and desired, but the specific approach taken in #1627 was challenging to implement and review, and had serious non-local performance impacts due to the archetype fragmentation created.
Entity groups (#1592) reflects one possible use case of this feature.
#2572 covers a broad laundry list of complaints and limitations of the current frustrations with Parent-Child hierarchies, especially in the context of UI.
Kinded entities (#1634) are a very useful correctness feature when working with relations extensively, to help verify that you're pointing to the flavor of entity you think you are. They are probably blocked on #1481.
Sub-issues
Metadata
Assignees
Labels
Type
Projects
Status
Background reading
Activity