Identificazione dei "tipi" di entità in un sistema di entità-componente


10

Se un'entità non ha un "tipo" esplicito (ad esempio un giocatore) ed è semplicemente una raccolta di componenti, come posso identificare le entità su cui i miei sistemi dovrebbero e non dovrebbero lavorare? Ad esempio, in una partita a Pong la paletta e la palla si scontrano entrambe con i confini della finestra. Tuttavia, i sistemi di gestione delle collisioni per ciascuno saranno diversi, pertanto un sistema non dovrebbe gestire entità di tipo errato.

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.
  }
}

Sia il giocatore che la palla condividono gli stessi tipi di componenti rilevanti per la gestione delle collisioni, ma le implementazioni del sistema saranno diverse.

Se ho un contenitore di tutte le entità di gioco, come posso identificare specifici tipi di entità senza ereditare Entityo includere una variabile membro come std::string type, nel qual caso un'entità non è più semplicemente una raccolta di componenti?

Risposte:


21

La risposta di Nicol Bolas è diretta, ma si fa da parte e osserva il tuo problema da lontano: non hai davvero bisogno del tipo di entità.

Devi solo preoccuparti se "l'oggetto ha un componente X" o no e il tuo problema è che non sei stato identificato correttamente X. Se due oggetti si comportano in modo diverso, assegnare loro componenti diversi o semplicemente mettere un flag booleano sul componente se lo fa per comportarsi in modo diverso per le diverse configurazioni degli oggetti. Utilizzare il sistema componente per prendere decisioni sul comportamento, non sull'entità "tipo". Questo è il punto centrale dell'utilizzo dei componenti.

Puoi avere completamente un PaddlePhysicscomponente / sistema e un BallPhysicscomponente / sistema separato se si comportano diversamente. Oppure puoi scomporre i componenti in pezzi più granulari in modo tale da avere un Bouncecomponente che solo la palla ha e un StopAtBoundarycomponente che entrambi Balle Paddlehanno se parte del comportamento è abbastanza complicata da giustificare la condivisione del codice. Oppure puoi semplicemente creare un PongPhysicscomponente con un flag booleano Bouncesimpostato trueper Balle falseper Paddle. È anche possibile creare un WallCollisioncomponente di base e quindi derivare quel componente per ottenere un elemento BallWallCollisionche aggiunge il comportamento extra necessario lì.


4
Penso che questa dovrebbe essere la risposta accettata poiché non vi è assolutamente alcun vincolo o problema con l'ECS "vaniglia". L'etichettatura delle entità può essere facilmente realizzata creando componenti dedicati che fungono da marcatori. Potrebbe anche essere solo un finto PlayerTypeComponent che non fa nulla di utile ma serve solo come tag.
Tiguchi,

19

Un sistema è utile solo se è utile. Se un sistema in cui un'entità è "semplicemente una raccolta di componenti" è meno utile di un sistema in cui un'entità è principalmente una "raccolta di componenti", quindi farlo .

Smetti di provare a creare sistemi "puri" e concentrati sulla realizzazione di quelli buoni che fanno ciò di cui hai bisogno. Utilizzare i componenti fino a quando i componenti non sono più utili per te. Quindi usa qualcos'altro.

Hai già trascorso più tempo a pensarci di quanto non meriti.


molto bello +1 "Hai già passato più tempo a pensarci di quanto non meriti"
wes

8
Non penso che questa sia una risposta, l'argomento del perfezionamento di un ECS merita un'attenzione significativa e Garee (quando l'ha pubblicato nel 2013) probabilmente non aveva trascorso abbastanza tempo a pensarci. L'idea che l'argomento non meriti più tempo implica che i sistemi dovrebbero essere semplici o banali e generalmente poco meritevoli del nostro tempo. Preferirei la risposta di Sean Middleditch in quanto tenta effettivamente di rispondere alla domanda invece di respingerla.
Gavin Williams,

Bella risposta. Mi ritrovo a doverlo dire ogni tanto. Concentrati su come andare avanti.
Dominic Bou-Samra,

5

Se si desidera assegnare alle entità un tipo esplicito, il modo più semplice è definire una variabile di tipo nella classe entità. Rispettare il modello CE solo se utile.

Altrimenti il ​​tipo è implicito attraverso gli attributi del componente. Ad esempio, il componente fisico avrebbe un attributo per mobile vs fisso. Il sistema quindi sa quando due cellulari si scontrano (palla e pagaia). Allo stesso modo è possibile avere attributi per la risposta del sistema di collisione. Basta fermare l'oggetto o rifletterlo? Osservare gli attributi dovrebbe darti un'idea di cosa sia l'entità, ma dovrebbe essere irrilevante. I sistemi non dovrebbero avere bisogno di sapere con quale tipo di entità stanno lavorando, dovrebbero ricevere informazioni sufficienti usando i componenti forniti.

Infine, puoi aggiungere un componente aggiuntivo che contiene un tipo, ma, come con l'aggiunta di un tipo all'entità, finirai per scrivere un sacco di codice specifico per tipo, vanificando lo scopo del sistema EC.


0

Un'entità è un insieme di componenti. Non è possibile assegnare etichette pulite a un set casuale. Rinunciare ai vincoli di tipo è il prezzo per la grande flessibilità.

Ovviamente puoi avere classi di entità speciali (tipizzate) che impongono restrizioni ai componenti.

Idealmente i componenti sono indipendenti. Quindi la soluzione al tuo problema sarebbe quella di chiamare la gestione delle collisioni su ciascun sottocomponente, in ordine. Nelle applicazioni reali ci sono interdipendenze e problemi di ordinazione. In tal caso è necessaria una logica "dispatcher" in ogni metodo della classe Entity.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.