Comment gérer correctement les collisions dans un jeu basé sur des composants?

11

Essayer d'envelopper ma tête autour des moyens de gérer correctement les collisions dans un jeu conçu autour de composants.

Je vois que de nombreux exemples ont une sorte de PhysicsComponentqui est ajouté à la liste des composants de l'entité, mais la mise en œuvre réelle me déroute.

Pour que cela fonctionne, il PhysicsComponentfaudrait avoir accès au monde qui l'entoure. Cela n'a pas de sens intuitif pour moi. Un composant ne devrait-il pas ignorer non seulement son conteneur (l'entité), mais le conteneur de son conteneur (le monde)?

Pour moi, il semble que le niveau ou la scène devrait maintenir une liste de ces entités et chaque mise à jour du jeu, parcourir les entités pour déterminer celles qui entrent en collision.

Ma question est d'une part, s'il s'agit ou non d'une bonne conception, et d'autre part, comment déterminer quelles entités peuvent entrer en collision. Je suppose que des entités solides pourraient implémenter une interface IRigidBody vide afin que le niveau puisse déterminer quelles entités dans la liste prennent en charge la collision. Mais cela rompt-il la conception des composants?

Au lieu de cela, devraient-ils contenir un composant RigidBody vide? Cela peut en fait être mieux car il n'est pas toujours vide et cette approche est plus pérenne. Le seul problème avec cela est la complexité. La scène devrait parcourir non seulement toutes les entités, mais aussi les composants de chaque entité pour déterminer si elle avait ce composant RigidBody.

Troisièmement, lorsqu'elles entrent en collision, les deux entités doivent être informées d'une manière ou d'une autre et je ne sais pas trop comment y parvenir.

Disons que les deux entités contenaient un HealthComponent et lorsqu'elles entraient en collision, leur santé serait diminuée d'une valeur arbitraire, 5. Je suppose que ce serait la responsabilité de la scène de gérer cela lorsqu'elle détecte une collision entre deux entités?

Mais alors la scène est-elle trop responsable? Je pouvais voir cela devenir incontrôlable et devenir difficile à gérer lorsque la scène est responsable de nombreuses choses auxquelles les entités ne devraient pas (?) Avoir accès.

Modifier: question mise à jour avec plus de détails.

Jason Watson
la source
4
Cette réponse semble appropriée pour un lien vers: gamedev.stackexchange.com/questions/13797/…
Andrew Russell
La réponse liée d'Andrew, la réponse de James et la réponse de Nick Wiggill méritent toutes des +1. Considérez les composants plus comme des données que comme une classe typique avec des données et des méthodes (non pas qu'ils n'auront pas de méthodes, mais ils ne devraient pas avoir beaucoup de responsabilités). Regardez le système de composants Artemis ( piemaster.net/2011/07/entity-component-artemis ) pour un exemple d'un bon cadre de composants.
michael.bartnett

Réponses:

5

Honnêtement, du point de vue de la conception des composants, mes composants ne se connaissent pas, sauf s'ils le doivent (et c'est très rare). Même alors, je préfère généralement que les composants parlent à un système de gestion desdits composants au lieu des composants directement. (L'interface de script ressemble à son objet à objet, mais ce n'est pas dans le moteur réel, hehe).

À cette fin, je serais d'accord avec ce que vous avez dit en premier et j'opterais pour des composants physiques qui existent partout où des objets doivent être testés pour leur collision. Maintenant, clairement, ces objets peuvent avoir à informer d'autres composants d'eux-mêmes lors de la résolution des collisions, mais, comme mentionné, c'est là que je préfère que l'événement lui-même soit simplement envoyé aux objets via une autre interface (soit vers un gestionnaire, soit via un système de messagerie d'événement si vous en avez un par exemple).

Je pense que vous êtes sur la bonne voie et que vous avez juste besoin de plus d'un «Oui, ça sonne bien» Alors .. Oui, cela sonne bien.

J'espère que cela t'aides!

James
la source
3

Normalement, les moteurs de jeux utilisent une bibliothèque tierce pour détecter les collisions entre entités. Dans ce scénario, on crée ou enregistre les entités qui ont le Composant Physique dans le monde "physique". Et chaque fois qu'il détecte une collision entre deux entités (A et B), il appelle normalement un rappel à l'entité A l'informant qu'il est entré en collision avec l'entité B et la même chose pour l'entité B, informant qu'il est entré en collision avec l'entité A.

Pour la 2D, une bibliothèque de physique gratuite bien connue est Box2D. Il vaut également la peine de jeter un œil à Chipmunk. Pour la 3D, Bullet est gratuit (probablement le meilleur gratuit que vous puissiez trouver). Havok et PhysX sont célèbres pour être utilisés dans de nombreux jeux triple A.

Byte Tamer
la source
2

Le problème que vous rencontrez est de voir que la détection de collision (qui est la seule raison pour laquelle vous auriez besoin d'une entité porteuse de composants physiques pour en référencer une autre) se fait à un niveau supérieur, généralement soit par votre boucle de jeu directement, soit par une fonction / classe d'assistance qui fait cela. Ma réponse à quelqu'un il y a quelques semaines parle de suppression d'entité pour des motifs similaires, et en gardant à l'esprit que si une collision entraîne la destruction d'une de vos entités, cette même réponse, dans son contexte donné, va être très pertinente pour vous , puisqu'un "pouvoir supérieur" devra encore gérer le nettoyage des corps ... pour ainsi dire.

Faire tout cela entre les seules entités n'est généralement pas viable. Il y a presque toujours un proxy pour de telles choses, dans une architecture solide, que ce soit via une gestion directe comme avec la détection de collision, ou des répartitions d'événements comme par exemple. un système de messagerie de joueur où un gestionnaire de messagerie côté client écoute les messages envoyés par les joueurs et les envoie au serveur pour être rediffusés à tout le monde.

Ingénieur
la source
2

Je suis confronté exactement au même problème que vous dans un projet maintenant. La façon dont j'ai décidé de l'aborder est d'avoir un "ColliderComponent" qui retient le corps du moteur physique. Les bodys sont définis en externe (définitions de formes qui sont chargées au moment de l'exécution) puis ajoutées au monde physique et aux entités de jeu auxquelles ils appartiennent.

J'utilise Box2D où vous pouvez attacher un "écouteur de collision" qui sera notifié par la collision. Puisque j'ajoute un pointeur à mon "ColliderComponent" aux données utilisateur du corps, je peux obtenir mes deux ColliderComponents qui faisaient partie de la collision.

Ainsi, la chose qui se produit lorsqu'une collision se produit est la suivante: les composants Collider qui faisaient partie de la collision enverront un message à leur propriétaire-objet (l'entité de jeu) qui à son tour diffusera ce message à tous ses composants.

Chaque composant peut alors réagir à ce message, de sorte que votre "composant santé" pourrait supprimer 5 points de santé, etc.

bummzack
la source
+1: J'utilise une approche très similaire. Comment déterminez-vous le montant des dommages à causer en fonction du type d'entités en collision?
Den
@Den J'envoie différents messages (ou données de message) en fonction de la collision qui s'est produite. Cela fonctionne bien pour moi, car je n'ai pas beaucoup de cas différents à gérer.
bummzack
0

Créez un système de collision qui connaît le «monde» des collisions. Ensuite, dans votre composant de collision, dites au système de collision de lancer un rayon du point A vers B et de répondre s'il est entré en collision ou non.

Bonne chance. Je trouve que le système de collision est l'une des parties les plus fastidieuses du moteur de jeu.

c2tp
la source