¿Cómo manejar adecuadamente la colisión en un juego basado en componentes?

11

Tratando de entender cómo manejar adecuadamente la colisión en un juego diseñado alrededor de componentes.

Veo que muchos ejemplos tienen algún tipo de PhysicsComponentque se agrega a la lista de componentes de la entidad, pero la implementación real me confunde.

Para que esto funcione, PhysicsComponentnecesitarían acceso al mundo que lo rodea. Esto no tiene sentido intuitivo para mí. ¿No debería un componente desconocer no solo su contenedor (la entidad), sino el contenedor de su contenedor (el mundo)?

Para mí, parece que el nivel o la escena deben mantener una lista de estas entidades y cada actualización del juego, recorrer las entidades para determinar qué colisión.

Mi pregunta es, en primer lugar, si este es un buen diseño o no, y en segundo lugar, cómo determinar qué entidades pueden colisionar. Supongo que las entidades sólidas podrían implementar una interfaz IRigidBody vacía para que el nivel pueda determinar qué entidades en la lista admiten colisión. ¿Pero esto está rompiendo el diseño del componente?

En cambio, ¿deberían contener un componente RigidBody vacío? En realidad, esto puede ser mejor porque no siempre está vacío y este enfoque es más a prueba de futuro. El único problema con esto es la complejidad. La escena tendría que recorrer no solo todas las entidades, sino también los componentes de cada entidad para determinar si tenía este componente RigidBody.

En tercer lugar, cuando chocan, ambas entidades deberían ser informadas de alguna manera y tampoco estoy seguro de cómo lograr esto.

Digamos que ambas entidades contenían un HealthComponent y cuando colisionaban, sus dos estados de salud disminuían en algún valor arbitrario. 5. ¿Supongo que sería responsabilidad de la escena manejar esto cuando detecta una colisión entre dos entidades?

¿Pero entonces la escena es responsable de demasiado? Pude ver que esto posiblemente se salga de control y se vuelva difícil de manejar cuando la escena sea responsable de muchas cosas a las que las entidades no deberían (?) Tener acceso.

Editar: Pregunta actualizada con más detalles.

Jason Watson
fuente
44
Esta respuesta parece apropiada para vincular a: gamedev.stackexchange.com/questions/13797/…
Andrew Russell
La respuesta vinculada de Andrew, la respuesta de James y la respuesta de Nick Wiggill merecen +1. Piense en los componentes más como datos que como una clase típica con datos y métodos (no es que no tengan métodos, pero no se les debe dar mucha responsabilidad). Mire el sistema de componentes Artemis ( piemaster.net/2011/07/entity-component-artemis ) para ver un ejemplo de un buen marco de componentes.
michael.bartnett

Respuestas:

5

Honestamente, desde el lado del diseño de componentes, mis componentes no se conocen entre sí a menos que tengan que hacerlo (y eso es muy raro). Incluso entonces, generalmente prefiero que los componentes hablen con algún sistema de gestión de dichos componentes en lugar de los componentes directamente. (La interfaz de secuencias de comandos se parece a su objeto a objeto, pero no está en el motor real, jeje).

Con ese fin, me pondría del lado de lo que dijiste primero e iría con los componentes físicos que existen donde sea que los objetos necesiten ser probados para su colisión. Ahora, claramente, estos objetos pueden tener que informar a otros componentes de sí mismos sobre la resolución de colisión, pero, como se mencionó, aquí es donde prefiero el evento en sí solo para salir a los objetos a través de otra interfaz (ya sea a un administrador o a través de un sistema de mensajería de eventos si tienes uno de esos por ejemplo).

Creo que estás en el camino correcto y solo necesitas más de un 'Sí, eso suena bien' Entonces ... Sí, eso suena bien.

¡Espero que esto ayude!

James
fuente
3

Normalmente, los motores de juego usan una biblioteca de terceros para detectar colisiones entre entidades. En ese escenario, uno crea o registra aquellas entidades que tienen el Componente de Física en el mundo de la "física". Y cada vez que detecta una colisión entre dos entidades (A y B), normalmente llamará a una devolución de llamada a la entidad A informando que ha chocado contra la entidad B y lo mismo para la entidad B, informando que ha chocado contra la entidad A.

Para 2D, una conocida biblioteca de física gratuita es Box2D. También vale la pena echar un vistazo a Chipmunk. Para 3D, Bullet es gratis (probablemente el mejor gratis que puedas encontrar). Havok y PhysX son famosos por ser utilizados en muchos juegos triples A.

Byte Tamer
fuente
2

El problema que está teniendo es ver que la detección de colisión (que es la única razón por la que necesitaría una entidad que soporte componentes físicos para hacer referencia a otra) se realiza a un nivel superior, generalmente mediante el bucle del juego directamente o una función / clase auxiliar que hace esto. Mi respuesta a alguien hace unas semanas habla sobre la eliminación de entidades por motivos similares, y teniendo en cuenta que si una colisión causa la destrucción de una de sus entidades, esa misma respuesta, en su contexto dado, será muy relevante para usted , ya que un "poder superior" todavía tendrá que gestionar la limpieza de los cuerpos ... por así decirlo.

Hacer algo de esto solo entre entidades, generalmente no es viable. Casi siempre hay un proxy para tales cosas, en una arquitectura sólida, ya sea a través de la gestión directa como con la detección de colisiones, o despachos de eventos como en, por ejemplo. un sistema de mensajería de jugadores en el que un gerente de mensajería del lado del cliente escucha los mensajes enviados por los jugadores y los envía al servidor para retransmitirlos a todos.

Ingeniero
fuente
2

Estoy enfrentando exactamente el mismo problema que tú en un proyecto ahora. La forma en que decidí abordarlo es tener un "ColliderComponent" que mantiene el cuerpo alejado del motor de física. Los cuerpos se definen externamente (definiciones de formas que se cargan en tiempo de ejecución) y luego se agregan al mundo de la física y a las entidades de juego a las que pertenecen.

Estoy usando Box2D donde puede adjuntar un "oyente de colisión" que será notificado por la colisión. Como agrego un puntero a mi "ColliderComponent" a los datos de usuario del cuerpo, puedo obtener mis dos ColliderComponents que fueron parte de la colisión.

Entonces, lo que sucede cuando ocurre una colisión es lo siguiente: los componentes del colisionador que formaron parte de la colisión enviarán un mensaje a su objeto propietario (la entidad del juego) que a su vez transmitirá ese mensaje a todos sus componentes.

Cada componente puede reaccionar a ese mensaje, por lo que su "componente de salud" podría eliminar 5 puntos de salud, etc.

bummzack
fuente
+1: Estoy usando un enfoque muy similar. ¿Cómo se determina la cantidad de daño que causa dependiendo del tipo de entidades que colisionaron?
Den
@Den envío diferentes mensajes (o datos de mensajes) de acuerdo con la colisión que sucedió. Esto funciona bien para mí, ya que no tengo muchos casos diferentes para manejar.
bummzack
0

Cree un sistema de colisión que conozca el "mundo" de colisión. Luego, en su componente de colisión, dígale al sistema de colisión que proyecte un rayo desde el punto A al B y responda si chocó o no.

Buena suerte. Creo que el sistema de colisión es una de las partes más tediosas del motor del juego.

c2tp
fuente