Dans un moteur Entity-Component-System Engine, comment gérer des groupes d'entités dépendantes?

48

Après avoir passé en revue quelques modèles de conception de jeu, je me suis installé avec Entity-Component-System (ES System) pour mon moteur de jeu. J'ai lu des articles (principalement T = Machine ), passé en revue un code source et je pense en avoir assez pour commencer.

Il y a juste une idée de base avec laquelle je me bats. Comment puis-je traiter avec des groupes d'entités qui dépendent les uns des autres?

Me laisser utiliser un exemple:

Supposons que je fabrique un jeu de tir aérien standard (pensez à Jamestown ) et que je souhaite construire une "entité de boss" avec plusieurs parties distinctes mais liées. La panne pourrait ressembler à quelque chose comme ça:

  • Corps du navire: Mouvement, rendu
  • Canon: position (verrouillé par rapport au corps du navire), poursuite \ tir au héros, prise de dégâts jusqu'à désactivation
  • Noyau: position (verrouillé par rapport au corps du navire), suivi \ tir sur le héros, subit des dommages jusqu'à ce qu'il soit désactivé, désactivation (er ... destruction) de toutes les autres entités du groupe de navires

Mon objectif serait d’identifier (et de manipuler) un élément de jeu distinct sans avoir à réécrire le sous-système à la base à chaque fois que je souhaite construire un nouvel élément agrégat.

Comment implémenter ce type de conception dans ES System?

  1. Est-ce que je mets en place une sorte de relation d'entité parent-enfant (les entités peuvent avoir des enfants)? Cela semble aller à l’encontre de la méthodologie selon laquelle les entités ne sont que des conteneurs vides et donnent davantage d’impression à la POO.
  2. Est-ce que je les implémente en tant qu'entités distinctes, avec une sorte de composant de connexion (BossComponent) et de système associé (BossSubSystem)? Je ne peux pas m'empêcher de penser que cela sera difficile à mettre en œuvre, car la communication des composants semble être un piège à ours.
  3. Est-ce que je les implémente comme une seule entité, avec une collection de composants (ShipComponent, CannonComponents, CoreComponent)? Celui-ci semble changer de direction par rapport à l'intention du système ES (les composants ici ressemblent trop à des entités lourdes), mais je suis au courant de cela, j'ai donc pensé que je l'énoncerais.
  4. Est-ce que je les implémente comme quelque chose d'autre que j'ai mentionné?

Je sais que cela peut être mis en œuvre très facilement dans la programmation orientée objet, mais je choisirai de choisir ES plutôt que la programmation orientée objet. Si je dois rompre avec la théorie ES pure pour mettre en œuvre ce design, je le ferai (ce n’est pas comme si je n’avais jamais eu à compromettre le design pur auparavant), mais je préférerais le faire pour des raisons de performance plutôt que pour commencer par un mauvais design.

Pour obtenir un crédit supplémentaire, songez au même concept, mais chacune des "entités boss" était en fait connectée à une "entité BigBoss" plus grande composée d’un corps principal, d’un noyau principal et de 3 "entités Boss". Cela me permettrait de voir une solution pour au moins 3 dimensions (grand-parent-parent-enfant) ... ce qui devrait être plus que suffisant pour moi.

John Daniels
la source
2
Il s'agit simplement de différents composants de maillage attachés à une entité, d'un maillage de navires et de canons attaché à l'entité de boss, ne vous engourdissez pas davantage. Btw un système de composant d'entité est OOP!
Maik Semder
2
Oui, le pire de ces articles de T-Machine est l'idée erronée que ce n'est en quelque sorte pas orienté objet. La plupart des systèmes de composants pour les entités sont complètement orientés objet, mais ne sont pas basés sur l'héritage.
Kylotan
3
Je pense qu'ils soulignent la nature non-POO parce que "penser à la POO classique" vous causera beaucoup de problèmes. J'ai aidé quelques personnes à utiliser des systèmes d'entités jusqu'à présent, et c'est le principal obstacle. Essayer de mettre du code dans les composants, essayer d’avoir des composants qui se sous-classent, etc., est un gros problème au début, mais c’est agréable de voir la lumière s’allumer lorsque l’idée est enfin pleinement comprise.
PSpeed
@MaikSemder J'ai nettoyé mes commentaires et les ai déplacés pour discuter
MichaelHouse
1
Pour que je comprenne bien @MaikSemder, dans le système ES que vous référencez, une entité peut avoir plusieurs composants du même type et le sous-système responsable de ces composants devrait traiter de ce fait? Ainsi, une entité peut avoir plusieurs composants de rendu et les données et les sous-systèmes de ces composants détermineraient comment les restituer correctement. Cela entraînerait moins d'entités, potentiellement moins de composants, mais une logique de sous-système un peu plus profonde, n'est-ce pas?
John Daniels

Réponses:

42

Si j'étais dans cette situation, je créerais chaque partie du chef en tant qu'entité séparée. Ces "sous-entités" incluraient un type AttachmentPointou un ParentEntitycomposant. Ce composant inclurait une référence à l'entité mère et un décalage par rapport à la position des parents. Lors de la mise à jour de la position, ils vérifient la position parent et appliquent le décalage pour générer leur propre position. En outre, il peut effectuer des vérifications pour s'assurer que l'entité parent existe toujours. De plus, vous pouvez avoir un SubEntitycomposant qui surveille l'existence de sous-entités pour l'entité parent. Cela vous permet de faire des choses comme ne rendre le noyau du boss vulnérable que lorsque les bras dotés de boucliers sont détruits.

J'utilise actuellement un TargetEntitycomposant dans mon jeu, qui est utilisé pour le suivi de la tourelle et lorsque les gobelins vont chercher une ressource. Il peut vérifier la position de l'entité cible et modifier son comportement en conséquence. Les entités qui n'ont pas de position ne sont jamais ajoutées en tant que cible, alors ne vous inquiétez pas. Toutefois, lorsque vous approfondissez vos connaissances, par exemple en vérifiant l'état de santé de l'entité mère ou enfant, le bouclier, les réserves de puissance ou autre, vous devez vous assurer que l'entité parent ou enfant a bien le composant associé.

En faisant de chaque partie sa propre entité, on maintient la flexibilité du cadre entité / composant en vous permettant d'ajouter des composants supplémentaires et différents à chaque partie du boss. Par exemple, une partie du chef pourrait avoir un composant pistolet et un composant de santé, tandis qu'une autre aurait un composant de bouclier et un composant de santé.

J'ai trouvé une autre discussion sur ce sujet ici . Dans lequel les utilisateurs discutent de l'ajout de plusieurs composants du même type à une entité (ce qui me semble une mauvaise idée). Cela semble être une conversation utile, même si je n’ai pas lu toute la discussion.

MichaelHouse
la source
Beaucoup de bonnes informations ici. Vous avez bien expliqué la solution, donnez-moi un exemple et répondez probablement à 1 ou 2 autres questions auxquelles je devrais revenir plus tard. La discussion liée semble également intrigante, en particulier lorsque je commence à mettre en œuvre une mise en œuvre plus difficile. Merci @ Byte56!
John Daniels
Pas de problème John! Bien sûr, il y a beaucoup de façons différentes de mettre en œuvre un système EC. Le système que j'avais en tête pour cette réponse est celui que j'ai décrit dans cette réponse . Bonne chance avec votre jeu!
MichaelHouse
Votre approche est la plus flexible et il est judicieux de l’utiliser dans un moteur de jeu généraliste.
Coyote
7

Sans connaître trop de détails sur vos systèmes existants, la façon dont je modéliserais ceci (et dans une certaine mesure dans mon propre système d'entité) consiste à avoir un composant tel que AttachedTo (parentEntity). Chacun des enfants peut ensuite recevoir le composant AttachedTo (boss).

Le système de rendu (ou quoi que ce soit) saisit ensuite les entités avec les composants: Position, AttachedTo, etc. et forme les hiérarchies appropriées.

PSpeed
la source
Cela semble être la réponse consensuelle. La prochaine fois, je donnerai plus de détails sur l'implémentation pour que les gens puissent mâcher. Merci @PSpeed!
John Daniels
4

Si vous souhaitez qu'une entité ne soit représentée que par un ID, le confinement d'entités peut être effectué via un composant spécial. Vous pouvez l'appeler CompositeComponent. Celui-ci contient une liste d'ID d'entités enfants et d'interfaces permettant d'ajouter / de supprimer des enfants de cette liste.

Il est évident que tous les composants dépendant de la position, etc. devront travailler avec celui-ci pour placer correctement l'entité. La manière de mettre en œuvre cela dépendra un peu de la manière dont vous implémentez le positionnement actuellement.

À propos, il n’existe pas de "théorie ES pure" - la création d’entités à partir de composants est une approche populaire, mais la méthode précise n’est pas encore normalisée.

Kylotan
la source
Oui, je devrais apprendre à ne pas utiliser le mot "pur" dans toutes les discussions sur le design ... rien de tel. Voie ConpositeComponent semble le consensus ici. Merci @Kylotan!
John Daniels