J'écris le moteur de jeu qui se compose de quelques modules. Deux d'entre eux sont le moteur graphique et le moteur physique .
Je me demande si c'est une bonne solution pour partager des données entre eux?
Deux façons (partage ou non) ressemble à ça:
Sans partager de données
GraphicsModel{
//some common for graphics and physics data like position
//some only graphic data
//like textures and detailed model's verticles that physics doesn't need
};
PhysicsModel{
//some common for graphics and physics data like position
//some only physics data
//usually my physics data contains A LOT more informations than graphics data
}
engine3D->createModel3D(...);
physicsEngine->createModel3D(...);
//connect graphics and physics data
//e.g. update graphics model's position when physics model's position will change
Je vois deux problèmes principaux:
- Beaucoup de données redondantes (comme deux positions pour les données physiques et graphiques)
- Problème de mise à jour des données (je dois mettre à jour manuellement les données graphiques lorsque les données physiques changent)
Avec le partage de données
Model{
//some common for graphics and physics data like position
};
GraphicModel : public Model{
//some only graphics data
//like textures and detailed model's verticles that physics doesn't need
};
PhysicsModel : public Model{
//some only physics data
//usually my physics data contains A LOT more informations than graphics data
}
model = engine3D->createModel3D(...);
physicsEngine->assingModel3D(&model); //will cast to
//PhysicsModel for it's purposes??
//when physics changes anything (like position) in model
//(which it treats like PhysicsModel), the position for graphics data
//will change as well (because it's the same model)
Problèmes ici:
- physicsEngine ne peut pas créer de nouveaux objets, juste "évaluer" ceux existants à partir de engine3D (en quelque sorte, cela semble plus anti-indépendant pour moi)
- Cast de données dans la fonction assingModel3D
- physicsEngine et graphicsEngine doivent être prudents - ils ne peuvent pas supprimer les données lorsqu'ils n'en ont pas besoin (car le second peut en avoir besoin). Mais c'est une situation rare. De plus, ils peuvent simplement supprimer le pointeur, pas l'objet. Ou nous pouvons supposer que graphicsEngine supprimera les objets, physicsEngine ne fait que les pointer vers eux.
Quelle voie est meilleure?
Qui va générer plus de problèmes à l'avenir?
J'aime davantage la deuxième solution, mais je me demande pourquoi la plupart des moteurs graphiques et physiques préfèrent la première (peut-être parce qu'ils ne font normalement que des graphiques ou uniquement un moteur physique et que quelqu'un d'autre les connecte dans le jeu?).
Ont-ils des avantages et des contras plus cachés?
physics
architecture
graphics
PolGraphic
la source
la source
Réponses:
De nos jours, plus de moteurs de jeux adoptent une conception de composants (par exemple Unity, Unreal). Dans ce type de conception, a
GameObject
est composé d'une liste de composants. Dans votre situation, il peut y avoir unMeshComponent
et unPhysicalComponent
, tous deux attachés à un même objet de jeu.Pour plus de simplicité, vous pouvez mettre une variable de transformation du monde dans le
GameObject
. Pendant la phrase de mise à jour,PhysicalComponent
sort la transformation du monde vers cette variable. Pendant le rendu, leMeshComponent
lit cette variable.La logique derrière cette conception est de découpler entre les composants. Ni l'un
MeshComponent
ni l' autre ne sePhysicalComponent
connaissent. Ils dépendent simplement d'une interface commune. Et il peut être plus facile d'étendre le système par composition, que d'utiliser une seule hiérarchie d'héritage.Dans un scénario réaliste, cependant, vous pourriez avoir besoin d'une gestion plus sophistiquée entre la synchronisation physique / graphique. Par exemple, la simulation physique peut devoir être exécutée par pas de temps fixe (par exemple 30 Hz), tandis que le rendu doit être variable. Et vous devrez peut-être interpoler les résultats de la sortie du moteur physique. Certains moteurs de physique (par exemple Bullet) prennent cependant directement en charge ce problème.
Unity a fourni une bonne référence de leurs composants , qui valent le coup d'œil.
la source
Les moteurs choisissent généralement la première option (propre maillage physique et propre maillage de rendu) car ils ont besoin de données très différentes, à la fois en qualité et en quantité.
Qualité parce que le moteur physique ne se soucie pas des coordonnées de texture, des groupes normaux et de tous ces trucs de rendu fantaisie par exemple. Chacun d'eux attend les données dans une disposition très spécifique se rapportant aux problèmes d'alignement, d'emballage, d' entrelacement des données, etc.
Quantité parce que le maillage physique a généralement beaucoup moins de triangles, c'est une version simplifiée du maillage de rendu haute résolution.
En découplant les deux, nous nous assurons que nous pouvons en modifier un, notamment en modifiant la disposition des données pour de meilleures performances, sans corrompre l'autre. C'est beaucoup plus évolutif.
la source
Outre @Millo Yip, excellente réponse, je voudrais juste vous rappeler que vous devrez partager les mêmes données avec le module Controls et le module AI et si je ne me trompe pas, la plupart des bibliothèques audio ont une idée de la position de l'émetteur sonore. vous devrez donc également partager les données avec ce module.
la source
Comme d'autres l'ont dit, il est assez courant que la physique ait un état de données interne géré séparément de l'état de données interne du moteur de rendu. Il est souvent courant de voir même les données de transformation (position / orientation / échelle) stockées séparément de la physique et des rendus car il est possible qu'un objet de jeu existe qui n'est pas imposé par la physique ni rendu mais nécessite une position mondiale pour les autres mécaniques.
La façon dont les données passent de la physique au rendu est à vous de décider.
Vous pouvez le faire via un processus de répartition inter-sous-système utilisant des événements / messages. Vous pouvez le faire en exposant une interface publique du sous-système de rendu au sous-système physique afin que la physique puisse simplement définir la position d'un rendu particulièrement. Une autre option est que le sous-système de rendu interroge l'entité pour la transformation pendant sa mise à jour et procède à la mise à jour de la position du composant de rendu, suivi d'un dessin.
Naturellement, en fonction de votre jeu, certains de ces moyens seront plus compatibles avec le cache et auront de meilleures performances que d'autres. À ce stade, je ne me laisserais pas trop entraîner d'une manière spécifique et je choisirais un modèle de communication et je l'essayerais. Vous pouvez facilement retravailler cette partie ultérieurement pour tester différents moyens d'optimisation.
la source