Dois-je partager des données entre le moteur graphique et physique dans le jeu?

9

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:

  1. Beaucoup de données redondantes (comme deux positions pour les données physiques et graphiques)
  2. 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:

  1. 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)
  2. Cast de données dans la fonction assingModel3D
  3. 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?

PolGraphic
la source
Exactement ma question aussi.
danijar

Réponses:

9

De nos jours, plus de moteurs de jeux adoptent une conception de composants (par exemple Unity, Unreal). Dans ce type de conception, a GameObjectest composé d'une liste de composants. Dans votre situation, il peut y avoir un MeshComponentet un PhysicalComponent, 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, PhysicalComponentsort la transformation du monde vers cette variable. Pendant le rendu, le MeshComponentlit cette variable.

La logique derrière cette conception est de découpler entre les composants. Ni l'un MeshComponentni l' autre ne se PhysicalComponentconnaissent. 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.

Milo Yip
la source
Cela ne répond pas du tout à la question, avoir 2 composants ne dit pas s'ils partagent ou non les données de maillage.
Maik Semder du
2
En fait, il offre un meilleur design, ce qui est tout à fait légitime.
jcora
7

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.

Maik Semder
la source
0

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.

ManicQin
la source
0

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.

Naros
la source