Identifizieren von Entitätstypen in einem Entitätskomponentensystem

10

Wenn eine Entität keinen expliziten 'Typ' hat (z. B. Player) und lediglich eine Sammlung von Komponenten ist, wie identifiziere ich die Entitäten, an denen meine Systeme arbeiten sollen und nicht? Zum Beispiel kollidieren bei einem Pong-Spiel sowohl das Paddel als auch der Ball mit den Fenstergrenzen. Die Kollisionsbehandlungssysteme sind jedoch für jedes System unterschiedlich, daher sollte ein System keine Entitäten des falschen Typs behandeln.

void PlayerCollisionSystem::update(std::vector<Entity *> entities) {
  typedef std::vector<Entity *>::iterator EIter;
  for (EIter i = entities.begin(); i != entities.end(); ++i) {
    Entity *player = *i; // How do I verify that the entity is a player?

    // Get relevant components.
    PositionComponent *position = player->getComponent<PositionComponent>();
    VelocityComponent *velocity = player->getComponent<VelocityComponent>();
    SpriteComponent *sprite = player->getComponent<SpriteComponent>();

    // Detect and handle player collisions using the components.
  }
}

Sowohl der Spieler als auch der Ball haben dieselben relevanten Komponententypen für die Kollisionsbehandlung, ihre Systemimplementierungen sind jedoch unterschiedlich.

Wenn ich einen Container mit allen Spielentitäten habe, wie identifiziere ich bestimmte Entitätstypen, ohne Entityeine Mitgliedsvariable zu erben oder einzuschließen, z. B. std::string typein welchem ​​Fall eine Entität nicht mehr nur eine Sammlung von Komponenten ist?

Garee
quelle

Antworten:

21

Die Antwort von Nicol Bolas ist direkt, aber Sie treten beiseite und betrachten Ihr Problem aus der Ferne: Sie brauchen den Typ der Entität wirklich nicht.

Sie müssen sich nur darum kümmern, ob "das Objekt eine Komponente hat X" oder nicht, und Ihr Problem ist, dass Sie nicht richtig identifiziert haben X. Wenn sich zwei Objekte unterschiedlich verhalten, geben Sie ihnen unterschiedliche Komponenten oder setzen Sie einfach ein boolesches Flag auf die Komponente, damit sie sich für unterschiedliche Objektkonfigurationen unterschiedlich verhält. Verwenden Sie das Komponentensystem, um Entscheidungen über das Verhalten zu treffen, nicht den Entitätstyp. Das ist der springende Punkt bei der Verwendung von Komponenten.

Sie dürfen eine PaddlePhysicsKomponente / ein System und eine separate BallPhysicsKomponente / ein separates System vollständig haben , wenn sie sich unterschiedlich verhalten. Oder Sie können die Komponenten in detailliertere Teile Bouncezerlegen, sodass Sie eine Komponente haben, die nur der Ball hat, und eine StopAtBoundaryKomponente, die beide haben Ballund Paddlewenn ein Teil des Verhaltens kompliziert genug ist, um das Teilen des Codes zu rechtfertigen. Oder Sie können einfach eine PongPhysicsKomponente erstellen Bounces, truefür die ein boolesches Flag für Ballund falsefür gesetzt ist Paddle. Sie können sogar eine Basiskomponente WallCollisionerstellen und diese dann ableiten, um eine zu erhalten BallWallCollision, die das dort erforderliche zusätzliche Verhalten hinzufügt.

Sean Middleditch
quelle
4
Ich denke, dies sollte die akzeptierte Antwort sein, da es absolut keine Einschränkungen oder Probleme mit "Vanille" ECS gibt. Das Kennzeichnen von Entitäten kann einfach durchgeführt werden, indem dedizierte Komponenten erstellt werden, die als Markierungen dienen. Es könnte auch nur eine Dummy-PlayerTypeComponent sein, die nichts Nützliches tut, sondern nur als Tag dient.
Tiguchi
19

Ein System ist nur dann nützlich, wenn es nützlich ist. Wenn ein System, bei dem eine Entität "einfach eine Sammlung von Komponenten" ist, weniger nützlich ist als ein System, bei dem eine Entität hauptsächlich eine "Sammlung von Komponenten" ist, dann tun Sie dies .

Hören Sie auf, "reine" Systeme zu entwickeln, und konzentrieren Sie sich darauf, gute Systeme zu entwickeln, die das tun, was Sie brauchen. Verwenden Sie Komponenten, bis Komponenten für Sie nicht mehr nützlich sind. Dann benutze etwas anderes.

Sie haben bereits mehr Zeit damit verbracht, darüber nachzudenken, als es verdient.

Nicol Bolas
quelle
sehr schön +1 "Sie haben bereits mehr Zeit damit verbracht, darüber nachzudenken, als es verdient"
wes
8
Ich denke nicht, dass dies überhaupt eine Antwort ist. Das Thema der Verfeinerung eines ECS verdient große Aufmerksamkeit, und Garee (als er dies 2013 veröffentlichte) hatte wahrscheinlich nicht genug Zeit damit verbracht, darüber nachzudenken. Die Vorstellung, dass das Thema nicht mehr Zeit verdient, impliziert, dass Systeme einfach oder trivial sein sollten und unsere Zeit im Allgemeinen nicht verdienen. Ich würde die Antwort von Sean Middleditch vorziehen, da sie tatsächlich versucht, die Frage zu beantworten, anstatt sie abzulehnen.
Gavin Williams
Gute Antwort. Ich muss mir das gelegentlich sagen. Konzentrieren Sie sich darauf, vorwärts zu kommen.
Dominic Bou-Samra
5

Wenn Sie Entitäten einen expliziten Typ zuweisen möchten, können Sie am einfachsten eine Typvariable in der Entitätsklasse definieren. Halten Sie sich nur so lange an das EC-Muster, wie es nützlich ist.

Andernfalls wird der Typ durch die Komponentenattribute impliziert. Zum Beispiel hätte die Physikkomponente ein Attribut für mobil oder stationär. Das System weiß dann, wann zwei Handys kollidieren (Ball und Paddel). Ebenso können Sie Attribute festlegen, wie das Kollisionssystem reagieren soll. Stoppen Sie einfach das Objekt oder reflektieren Sie es? Wenn Sie sich die Attribute ansehen, erhalten Sie eine Vorstellung davon, was die Entität ist, aber sie sollte irrelevant sein. Die Systeme sollten nicht wissen müssen, mit welchem ​​Entitätstyp sie arbeiten, sie sollten mithilfe der ihnen bereitgestellten Komponenten genügend Informationen erhalten.

Schließlich können Sie eine zusätzliche Komponente hinzufügen, die einen Typ enthält. Wie beim Hinzufügen eines Typs zur Entität werden Sie jedoch am Ende viel typspezifischen Code schreiben, wodurch der Zweck des EC-Systems zunichte gemacht wird.

MichaelHouse
quelle
0

Eine Entität ist eine Reihe von Komponenten. Sie können einem zufälligen Satz keine ordentlichen Beschriftungen zuweisen. Das Aufgeben von Typbeschränkungen ist der Preis für die große Flexibilität.

Natürlich können Sie spezielle (typisierte) Entitätsklassen haben, die den Komponenten Einschränkungen auferlegen.

Im Idealfall sind die Komponenten unabhängig. Die Lösung für Ihr Problem besteht also darin, die Kollisionsbehandlung für jede Unterkomponente der Reihe nach aufzurufen. In realen Anwendungen gibt es Abhängigkeiten und Ordnungsprobleme. In diesem Fall benötigen Sie in jeder Methode der Entity-Klasse eine Dispatcher-Logik.

Karl
quelle