mynamekse/godot-gecs

gecs-relationships

Use when connecting entities or adding link-attached data in GECS — Entity-Entity pairs, Entity-Component data links, Entity-Archetype relationships, wildcard queries, stacked removals (buffs/debuffs), and the Rels factory pattern

Quelltext ansehen

Verwendung

  1. Installationsbefehl kopieren und das Quellpaket vor der Installation in der eigenen Agentenumgebung prüfen.
  2. Benötigte Werkzeuge, Zugangsdaten und Hosts im Original prüfen.
  3. Eingabe und gewünschtes Ergebnis beschreiben und die Ausgabe mit den Quellen abgleichen.
npx skills add https://github.com/mynamekse/godot-gecs --skill gecs-relationships

Vor dem Start

  • Die Installation umfasst weder Modellabo noch API-Kontingent oder Dateizugriffsrechte.
  • Sterne und Installationen zeigen Aktivität, keine unabhängige Qualitäts- oder Sicherheitsprüfung.
Originales Skill-Dokument

Aus dem Quell-Repository gerendert; Überschriften, Beispiele, Code, Tabellen, Links und Bilder bleiben erhalten.

GECS Relationships in Godot 4.3+

Express links between entities as first-class pairs in GECS v9. A Relationship connects a Source Entity to a Target through a Relation Component. Relationships support arbitrary metadata, stacked instances (e.g. poison stacks), wildcard queries, and graduated cleansing.

Addon: GECS · version v9 · Godot 4.3+ · MIT Related skills: gecs-core for primitives, gecs-queries for relationship queries, gecs-observers for .on_relationship_added().

1. Anatomy of a Relationship

A relationship consists of 3 elements:

  1. Source: The entity that owns the relationship.
  2. Relation: A Component instance defining the relationship type (e.g., R_ChildOf, R_Attacking).
  3. Target: One of three target types:
  • Entity: Linking two entities (e.g., attacker -> target).
  • Component Instance: Storing link-attached data directly on the relationship (e.g., unit -> C_Burning.new(10.0)).
  • Archetype / Class Type: Categorical tagging (e.g., unit -> Food).
mermaid
flowchart LR
    E1["Source Entity (e.g., Player)"] -- "Relationship (R_Attacks)" --> E2["Target Entity (e.g., Boss)"]
    E1 -- "Relationship (R_StatusEffect)" --> C["Target Component (C_Poison.new(5s))"]
    E1 -- "Relationship (R_Likes)" --> A["Target Archetype (Food)"]

2. The Three Relationship Types

1. Entity → Entity Link

gdscript
# e_alice is attacking e_bob
e_alice.add_relationship(Relationship.new(R_Attacks.new(), e_bob))

2. Entity → Component Instance (Link Data)

Attach custom data directly to the connection without modifying the entity's direct archetype:

gdscript
# Apply 50 fire damage over 5 seconds directly to target
entity.add_relationship(Relationship.new(R_Damaged.new(), C_FireDamage.new(50.0, 5.0)))

3. Entity → Archetype

Tag relationships with high-level classifications:

gdscript
e_unit.add_relationship(Relationship.new(R_Likes.new(), Food))

3. Querying Relationships & Wildcards

Exact Match Queries

gdscript
# Match entities attacking e_boss
var attackers = ECS.world.query \
	.with_relationship([Relationship.new(R_Attacks.new(), e_boss)]) \
	.execute()

Wildcard Queries (ECS.wildcard)

gdscript
# 1. Any entity attacking ANY target (wildcard target)
var in_combat = ECS.world.query \
	.with_relationship([Relationship.new(R_Attacks.new(), ECS.wildcard)]) \
	.execute()

# 2. Any relationship targeting e_boss (wildcard relation)
var targeted = ECS.world.query \
	.with_relationship([Relationship.new(ECS.wildcard, e_boss)]) \
	.execute()

# 3. Omitting target defaults to wildcard:
var has_buff = ECS.world.query \
	.with_relationship([Relationship.new(R_Buff.new())]) \
	.execute()
Performance Rule: Wildcard queries scan multiple archetypes (O(N)). Always combine wildcards with a component filter like .with_all([C_Alive]) in performance-critical code!

4. Limited-Count Removal (Buffs, Debuffs & Stacks)

The remove_relationship() method accepts an optional limit argument:

  • limit = -1 (Default): Remove all matching relationships.
  • limit = N (N > 0): Remove up to N matching instances.
  • limit = 0: Removes none (used for validation).

Example: Poison Stacks & Antidote

gdscript
# Apply 4 poison stacks
for i in 4:
	entity.add_relationship(Relationship.new(R_Poison.new(), null))

# Minor antidote cleanses 2 stacks
entity.remove_relationship(Relationship.new(R_Poison.new(), null), 2)

# Verify remaining stacks: entity still has 2 poison stacks

Batch Cleansing

gdscript
# Remove up to 2 stacks across multiple negative effects
entity.remove_relationships([
	Relationship.new(R_Poison.new(), null),
	Relationship.new(R_Bleed.new(), null)
], 2)

5. The Rels Factory Pattern (Recommended)

To avoid allocating new relation objects repeatedly, create a static Rels helper class. See `examples/rels.gd`:

gdscript
class_name Rels

static var attacks: Relationship = Relationship.new(R_Attacks.new(), null)
static var child_of: Relationship = Relationship.new(R_ChildOf.new(), null)

static func attacks_target(target: Entity) -> Relationship:
	return Relationship.new(R_Attacks.new(), target)

static func child_of_entity(parent: Entity) -> Relationship:
	return Relationship.new(R_ChildOf.new(), parent)

Usage in gameplay code:

gdscript
if entity.has_relationship(Rels.attacks):
	pass

entity.remove_relationship(Rels.attacks, 1)

6. Naming Conventions

TypeClass NameFile Name
Relation ComponentR_ChildOf, R_Attacksr_child_of.gd, r_attacks.gd
Static RelationshipsRels.attacks_target(e)rels.gd
aus demselben Repository

Weitere Skills

Alle Skills