Identificar 'tipos' de entidades en un sistema de entidad-componente

10

Si una Entidad no tiene un 'tipo' explícito (por ejemplo, jugador) y es simplemente una colección de componentes, ¿cómo identifico las entidades en las que mis sistemas deberían y no deberían estar trabajando? Por ejemplo, en un juego de Pong, la paleta y la pelota chocan con los límites de la ventana. Sin embargo, los sistemas de manejo de colisiones para cada uno serán diferentes, por lo tanto, un sistema no debe manejar entidades del tipo incorrecto.

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

Tanto el jugador como la pelota comparten los mismos tipos de componentes relevantes para el manejo de colisiones, pero sus implementaciones del sistema serán diferentes.

Si tengo un contenedor de todas las entidades del juego, ¿cómo identifico tipos específicos de entidad sin heredar Entityo incluir una variable miembro como std::string type, en cuyo caso, una entidad ya no es simplemente una colección de componentes?

Garee
fuente

Respuestas:

21

La respuesta de Nicol Bolas es directa, pero se hace a un lado y mira su problema desde la distancia: realmente no necesita el tipo de entidad.

Solo debe preocuparse si "el objeto tiene un componente X" o no y su problema es que no se ha identificado correctamente X. Si dos objetos se comportan de manera diferente, asígneles componentes diferentes o simplemente coloque una bandera booleana en el componente para que se comporte de manera diferente para diferentes configuraciones de objeto. Use el sistema de componentes para tomar decisiones sobre el comportamiento, no la entidad "tipo". Ese es el punto de usar componentes.

Se le permite completamente tener un PaddlePhysicscomponente / sistema y un BallPhysicscomponente / sistema separado si se comportan de manera diferente. O puede dividir los componentes en piezas más granulares de modo que tenga un Bouncecomponente que solo la Bola tenga y un StopAtBoundarycomponente que ambos tengan Bally Paddleque si parte del comportamiento es lo suficientemente complicado como para justificar compartir el código. O simplemente puede hacer un PongPhysicscomponente que tenga un indicador booleano Bouncesestablecido truepara Bally falsepara el Paddle. Incluso podría hacer un WallCollisioncomponente base y luego derivar ese componente para obtener un BallWallCollisionque agregue el comportamiento adicional necesario allí.

Sean Middleditch
fuente
44
Creo que esta debería ser la respuesta aceptada ya que no hay absolutamente ninguna restricción o problema con el ECS "vainilla". Las entidades de etiquetado se pueden lograr fácilmente creando componentes dedicados que sirvan como marcadores. También podría ser solo un PlayerTypeComponent ficticio que no hace nada útil sino que solo sirve como etiqueta.
tiguchi
19

Un sistema solo es útil si es útil. Si un sistema donde una entidad es "simplemente una colección de componentes" es menos útil que un sistema donde una entidad es principalmente una "colección de componentes", entonces haga eso .

Deje de intentar hacer sistemas "puros" y concéntrese en hacer buenos que hagan lo que necesita. Use componentes hasta que los componentes ya no sean útiles para usted. Entonces usa algo más.

Ya has pasado más tiempo pensando en esto de lo que merece.

Nicol Bolas
fuente
muy agradable +1 "Ya has pasado más tiempo pensando en esto de lo que se merece"
wes
8
No creo que esta sea una respuesta en absoluto. El tema de refinar un ECS merece una atención considerable, y Garee (cuando publicó esto en 2013) probablemente no había pasado suficiente tiempo pensando en ello. La noción de que el tema no merece más tiempo implica que los sistemas deben ser simples o triviales y, en general, no merecen nuestro tiempo. Preferiría la respuesta de Sean Middleditch, ya que en realidad intenta responder la pregunta en lugar de descartarla.
Gavin Williams
Gran respuesta. Me encuentro teniendo que decirme esto ocasionalmente. Concéntrese en seguir adelante.
Dominic Bou-Samra
5

Si desea dar a las entidades un tipo explícito, la forma más fácil es definir una variable de tipo en la clase de entidad. Solo mantenga el patrón CE siempre que sea útil.

De lo contrario, el tipo está implícito a través de los atributos del componente. Por ejemplo, el componente de física tendría un atributo para móvil frente a estacionario. El sistema entonces sabe cuándo chocan dos móviles (pelota y paleta). Del mismo modo, puede tener atributos sobre cómo debe responder el sistema de colisión. ¿Solo detiene el objeto o lo refleja? Mirar los atributos debería darle una idea de lo que es la entidad, pero debería ser irrelevante. Los sistemas no deberían necesitar saber con qué tipo de entidad están trabajando, se les debe dar suficiente información utilizando los componentes que se les proporcionan.

Finalmente, puede agregar un componente adicional que contenga un tipo, pero, al igual que al agregar un tipo a la entidad, terminará escribiendo una gran cantidad de código específico de tipo, lo que anulará el propósito del sistema de la CE.

MichaelHouse
fuente
0

Una entidad es un conjunto de componentes. No puede asignar etiquetas ordenadas a un conjunto aleatorio. Renunciar a las restricciones de tipo es el precio de la gran flexibilidad.

Por supuesto, puede tener clases de entidad especiales (tipificadas) que imponen restricciones a los componentes.

Idealmente, los componentes son independientes. Entonces, la solución a su problema sería llamar al manejo de colisiones en cada subcomponente, en orden. En aplicaciones reales hay interdependencias y problemas de pedido. Si ese es el caso, necesita algo de lógica de 'despachador' en cada método de la clase Entidad.

Karl
fuente