Repository navigation
GECS v 7.1.0 - Relationships added to Archetypes
GECS v7.1.0 — Structural Relationship Queries
Relationship queries are now as fast as component queries. No API changes required — your existing with_relationship() calls just got dramatically faster.
What Changed
with_relationship() previously worked as a post-filter: after selecting entities by component, it iterated every matched entity and linearly scanned their relationships array. This was O(N×M×K) where N = entities, M = relationships per entity, K = filters.
In v7.1.0, each (Relation, Target) pair is baked into the archetype signature. Relationship queries now resolve through the same O(1) archetype bucket lookup that component queries use — no per-entity scanning.
Performance (Godot 4.6, from benchmarks)
Exact relationship queries — constant time regardless of entity count:
| Scale | Relationship Query | Component Query (baseline) |
|---|---|---|
| 100 | 0.089 ms | 0.060 ms |
| 1,000 | 0.092 ms | 0.061 ms |
| 10,000 | 0.091 ms | 0.137 ms |
Exact with_relationship([Relationship.new(C_Type.new(), target)]) queries are flat at ~0.09ms whether you have 100 or 10,000 entities. That's within noise of a with_all() component query.
Wildcard relationship queries (Relationship.new(C_Type.new(), null)) scale with the number of distinct archetypes matched, not total entities:
| Scale | Wildcard Query |
|---|---|
| 100 | 0.214 ms |
| 1,000 | 1.941 ms |
| 10,000 | 21.274 ms |
(This benchmark is worst-case: every entity has a unique target, creating one archetype per entity. Real-world usage with shared targets will be much faster.)
What You Need to Do
Nothing. The with_relationship() API is unchanged. Your existing code benefits automatically.
# This is the same API — it's just fast now
var children = world.query.with_relationship([
Relationship.new(C_ChildOf.new(), parent_entity)
]).execute()Property-based relationship queries continue to work as post-filters (runtime values can't be archetype-keyed):
# Still works — property queries remain post-filter
var high_damage = world.query.with_relationship([
Relationship.new({C_Damage: {"amount": {"_gte": 50}}}, target)
]).execute()Other Changes
- Legacy
relationship_entity_indexremoved — the old Dictionary-based index is gone, replaced entirely by the archetype system. Slightly lower memory footprint. - Archetype explosion warning — if you exceed 500 archetypes (possible with many unique relationship targets), a one-time debug warning fires so you can catch unintended combinatorial blowup early.
- Batch relationship transitions —
add_relationships([r1, r2, r3])produces exactly one archetype transition instead of N, keeping bulk operations fast. - Freed-target cleanup — when a target entity is removed from the world, all source relationships pointing to it are automatically cleaned up via the archetype index.
Test Coverage
313 tests passing, zero regressions. 34 new tests added covering structural relationship storage, signature computation, archetype transitions, query integration, and property query preservation.
What's Changed
Full Changelog: v7.0.1...v7.1.0