Je travaille sur un jeu avec une architecture basée sur des composants. An Entity
possède un ensemble d' Component
instances, chacune ayant un ensemble d' Slot
instances avec lesquelles stocker, envoyer et recevoir des valeurs. Fonctions d'usine telles que Player
produire des entités avec les composants requis et les connexions d'emplacement.
J'essaie de déterminer le meilleur niveau de granularité pour les composants. Par exemple, en ce moment Position
, Velocity
et Acceleration
sont tous des composants séparés, connectés en série. Velocity
et Acceleration
pourrait facilement être réécrit en un Delta
composant uniforme , ou Position
, Velocity
et Acceleration
pourrait être combiné avec des composants tels que Friction
et Gravity
en un Physics
composant monolithique .
Un composant devrait-il avoir la plus petite responsabilité possible (au prix de beaucoup d'interconnectivité) ou les composants associés devraient-ils être combinés en composants monolithiques (au prix de la flexibilité)? Je penche vers le premier, mais je pourrais utiliser un deuxième avis.
la source
Réponses:
Il y a une ligne entre la granularité complète, conduisant à aucun gaspillage de code ou état de type blob (c'est pourquoi les architectures de composants sont privilégiées), et la convivialité.
Évidemment, les choses peuvent avoir un
Position
, mais elles ne sont pas nécessairement dynamiques (alors pourquoi avoirVelocity
etAcceleration
?). Cependant, quelque chose avec unVelocity
va être un objet en mouvement, il est donc logique d'avoir égalementAcceleration
groupé.Allez-vous avoir un cas où v et a vont être nécessaires, mais vous ne voulez pas de simulation physique pour eux? De même, y aura-t-il un point
Gravity
s'il ne s'agit pas d'objets physiques?tl; dr Group ce qui a du sens.
la source
Entity
a unPosition
et quelques composants qui fontPosition
participer la physique, alorsEntity
c'est de facto physique. Je pense que ce que je peux faire, c'est simplement ajouter quelques composants pour le regroupement logique, et garder tous les composants fondamentaux à une seule responsabilité. Ainsi , en ajoutant, par exemple, unMovable
à unEntity
aurait le même effet que l' ajout d' unPosition
,Velocity
etAcceleration
.Pour éviter la microgestion de chaque variable que je suggérerais en commençant lourdement, choisissez des divisions autour de la responsabilité et refactorisez lorsque la situation se présente logiquement. Vous pouvez commencer les premiers dessins sur papier. À un moment donné, ces grosses divisions de responsabilité deviendront les éléments constitutifs de vos entités.
Donc, pour un exemple précipité, vous avez Game. Le jeu se divise en environnement + état. L'environnement se divise en StaticWorld + MovingStuff. L'état se divise en AIControlled + PlayerControlled. L'idée grossière de dommages se divise en TakesDamage + GivesDamage.
Etc.
Un peu comme le conseil commun de "Construire des jeux, pas des moteurs!" pour les nouveaux praticiens, je recommande "Construire des jeux, pas des systèmes de composants élaborés!" car ce n'est qu'avec une expérience personnelle avec un jeu en cours que vous saurez si un système de composants élaboré est nécessaire dans les travaux futurs.
la source
Ma conjecture serait de combiner des composants qui auront beaucoup d'interaction. Dans votre cas, je garderais la position dans un seul composant et garderais la vitesse et l'accélération ensemble dans un composant physique.
Mais cela dépend beaucoup des fonctionnalités de votre jeu (sauf si vous créez un framework sans jeu spécifique en tête).
la source
Je me rends compte que c'est une vieille question mais peut-être que quelqu'un trouvera cette réponse utile.
Je crois que
Systems
cela vous aidera mieux à comprendre comment construire des composants. Les systèmes existent dans des architectures où les composants ne contiennent pas leur propre logique, à part les simples getter / setters et les fonctions d'assistance. Les systèmes fonctionnent sur des entités qui satisfont aux exigences des composants. C'est pourquoi il est préférable de séparer les données des composants autant qu'il est logique que ces données soient traitées sans les autres données.Par exemple, vous pouvez avoir un
MovementSystem
qui met à jour ses entités enPosition
fonction de leurVelocity
. Cela pourrait être pour des entités simples dans le jeu. Mais, pour le joueur et les ennemis, vous voudrez peut-être un mouvement qui aAcceleration
été traitéAcceleratedMovementSystem
. Mais pour les obstacles, vous voudrez peut-êtreFriction
. Le Terrain peut également avoir des frottements, mais il n'aura pas de composante de vitesse. Mais qu'en est-ilGravity
? Ajoutez-le simplement Player, Enemy et Obstacle, et créez-en unGravitySystem
pour le traiter.L'essentiel est que plus découplées votre
Components
sont, plus extensible leEntities
sera lors de l' utilisationSystems
.Edit: rendu la dernière déclaration plus claire.
Edit: Ok, j'ai travaillé sur mon propre système et j'ai réalisé cette réalisation. Un exemple pour diviser la position et la vitesse est que la manipulation de la vitesse fait changer la position avec un MovementSystem. Par conséquent, un «InputMovementSystem» n'a pas besoin d'une position pour que le lecteur se déplace de l'entrée utilisateur, car le MovementSystem récupérera les changements de vitesse à appliquer à la position. Certes, cela fonctionnerait toujours bien pour les assembler, mais c'est un exemple de la raison pour laquelle ils n'ont pas besoin d'être.
J'ai lu récemment un article de blog qui disait quelque chose comme ceci:
la source