Système de composants d'entité - Comment implémenter la transformation d'un objet?


11

En concevant un système entité-composant pour mon moteur, je suis tombé sur un petit problème dans la manière de stocker et de récupérer un type particulier de composant.

Tout d'abord, permettez-moi de clarifier un peu la terminologie que je vais utiliser dans cette question:

  • J'appelle " Component " une structure de données qui stocke les données pertinentes pour un système particulier.
  • J'appelle « système » une agrégation de méthodes et de structures de données qui utilise des composants pour mettre à jour l'état du jeu / l'interface avec l'utilisateur.
  • Une " Entité " est simplement un ID utilisé pour récupérer des composants spécifiques et modifier leurs données dans la logique du jeu.

Chaque système possède un tableau (mappé par ID) de son type de composant (par exemple, Physique-> Composant physique, AI-> AIComponent, Rendu -> RenderingComponent), afin de pouvoir itérer efficacement sur les données.

Cependant, tous les composants n'appartiennent pas spécifiquement à un système. Par exemple, un composant Transform stocke la position, la rotation et l'échelle d'un objet. C'est l'une des parties les plus importantes d'une entité (Unity la rend obligatoire, même), car elle est utilisée par de nombreux systèmes, par exemple la physique, l'IA, le rendu, etc.

C'est à peu près le problème auquel je suis confronté. Étant donné que Transform est utilisé par de nombreux autres systèmes, comment dois-je procéder pour en récupérer un à utiliser pour chaque composant? Une solution possible que je vois est de faire en sorte que chaque composant stocke son propre ID d'entité. Il serait facile de récupérer n'importe quel composant comme celui-ci, mais ce ne serait pas aussi efficace, et cela irait également à l'encontre du concept d'un composant comme un ensemble de données isolé et indépendant, qui n'en connaît aucun autre.

Existe-t-il un moyen approprié de résoudre ce problème? Transformer devrait-il même être un composant?


3
+1 pour "D'abord, permettez-moi de clarifier un peu la terminologie que je vais utiliser dans cette question:"
Vaillancourt

J'aimerais voir ce type de questions plus dans ce site. +1
S. Tarık Çetin

Il suffit de stocker tous les composants en tant que variables globales
Miles Rout

Réponses:


2

Il s'agit d'une question assez large, dont la réponse dépend fortement de votre architecture. Cependant, je vais essayer de vous donner une réponse générale.

Vos systèmes physiques et de rendu nécessiteront certainement la transformation, mais pas le système AI. Par conséquent, il est logique d'encapsuler la transformation dans sa propre classe de composants. Tous ces systèmes intéressés utiliseraient les mêmes données.Par conséquent, il est logique que l'entité ait un pointeur vers l'objet de transformation ou un identifiant pour un objet de transformation stocké ailleurs.

Si vous choisissez cette dernière solution, chaque système intéressé par une transformation devra accéder à l'emplacement de stockage de l'objet de transformation.

Si vous choisissez le premier, tout ce que chaque système doit faire est d'accéder à l'entité elle-même et de demander la transformation.

Dans le premier cas, le problème devient comment accorder l'accès au stockage des transformations à chaque système, sans enfreindre les règles de POO, si vous vous souciez de ces choses.

Le dernier cas n'a pas de tels problèmes, mais nécessite de changer la conception de votre objet entité pour stocker des pointeurs vers des objets plutôt que des identifiants d'objets composants.

Ma préférence personnelle est de concevoir la classe d'entité pour stocker des pointeurs vers des objets composants, car cela simplifie de nombreux problèmes de conception. De cette façon, chaque système qui nécessite une transformation peut la demander à l'entité et l'ignorer s'il ne le fait pas. Cependant, cela entraîne une surcharge de calcul inhérente aux pointeurs, à savoir le coût des échecs de cache.

Jetez un œil à cet aperçu ECS pour plus d'informations à ce sujet.

En fin de compte, c'est à vous de décider ce qui est le plus important pour vous: la facilité de développement ou les performances.

Je voudrais souligner, enfin, que votre question est un excellent exemple des questions de conception auxquelles les partisans d'ECS réfléchissent, et il n'y a pas de solution miracle définitive.


Merci pour vos suggestions. J'ai une question, cependant: pourquoi le système d'IA n'aurait-il pas besoin de la position d'un objet?
CRefice

Vous confondez la position (vecteur de 3 flottants) avec une translation (matrice de transformation construite à partir d'un vecteur de position). Une matrice de transformation est construite à partir de transformations de translation, de rotation et d'échelle. C'est bien plus d'informations qu'un système d'IA n'aurait besoin, bien que vous puissiez certainement en extraire le vecteur de position. Personnellement, je séparerais la position, l'orientation et les tailles dans leur propre composant et les utiliserais pour créer et mettre à jour la transformation.
Ian Young le

@IanYoung Les séparer pourrait faire plus de mal que de bien, potentiellement si vous trouvez que vous avez besoin de position et d'orientation ensemble plus souvent que de position ou d'orientation séparément. Dans ce cas, le placement d'attributs de données de position et d'orientation dans un seul composant peut améliorer les performances du cache.
Naros

1
Ma préférence est de combiner les trois, la position, l'orientation et l'échelle en un seul composant et dans les cas où un sous-système spécifique n'a besoin que d'une position ou d'une orientation, je recommanderais de dupliquer les données et de les synchroniser à des points clairement définis dans la boucle de jeu. .
Naros

@ Naros oui, c'est ce que je voulais dire: deux composants, Transformer et (dans mon cadre) SpatialData, qui contient la position, la vitesse, l'orientation et la vitesse angulaire. La position et l'orientation sont utilisées pour construire et mettre à jour la transformation.
Ian Young
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.