Sollte ich im Spiel Daten zwischen Grafik- und Physik-Engine austauschen?

9

Ich schreibe die Spiel-Engine, die aus wenigen Modulen besteht. Zwei davon sind die Grafik-Engine und die Physik-Engine .

Ich frage mich, ob es eine gute Lösung ist, Daten zwischen ihnen auszutauschen.

Zwei Möglichkeiten (Teilen oder nicht) sehen so aus:

Ohne Daten zu teilen

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

Ich sehe zwei Hauptprobleme:

  1. Viele redundante Daten (wie zwei Positionen für Physik- und Grafikdaten)
  2. Problem beim Aktualisieren von Daten (Ich muss Grafikdaten manuell aktualisieren, wenn sich die Physikdaten ändern)

Mit Daten teilen

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)

Probleme hier:

  1. physicsEngine kann keine neuen Objekte erstellen, sondern nur vorhandene Objekte aus engine3D "bewerten" (irgendwie sieht es für mich anti-unabhängiger aus)
  2. Daten in assingModel3D-Funktion umwandeln
  3. PhysicsEngine und GraphicsEngine müssen vorsichtig sein - sie können keine Daten löschen, wenn sie sie nicht benötigen (weil der zweite sie möglicherweise benötigt). Aber es ist eine seltene Situation. Außerdem können sie nur den Zeiger löschen, nicht das Objekt. Oder wir können davon ausgehen, dass GraphicsEngine Objekte löscht, PhysicsEngine zeigt nur darauf.

Welcher Weg ist besser?

Was wird in Zukunft mehr Probleme verursachen?

Ich mag die zweite Lösung mehr, aber ich frage mich, warum die meisten Grafik- und Physik-Engines die erste bevorzugen (vielleicht, weil sie normalerweise nur Grafiken oder nur Physik-Engines erstellen und jemand anderes sie im Spiel verbindet?).

Haben sie noch mehr versteckte Vor- und Nachteile?

PolGraphic
quelle
Genau meine Frage auch.
Danijar

Antworten:

9

Heutzutage verwenden mehr Spiele-Engines ein Komponentendesign (z. B. Unity, Unreal). Bei dieser Art von Design besteht a GameObjectaus einer Liste von Komponenten. In Ihrer Situation kann es ein MeshComponentund ein geben PhysicalComponent, die beide an ein einzelnes Spielobjekt angehängt sind.

Der Einfachheit halber können Sie der Variablen eine Welttransformationsvariable hinzufügen GameObject. Gibt während der Aktualisierungsphrase PhysicalComponentdie Welttransformation in diese Variable aus. Während des Renderns MeshComponentliest das diese Variable.

Das Grundprinzip dieses Entwurfs besteht darin, zwischen Komponenten zu entkoppeln. Weder MeshComponentnoch PhysicalComponentkennt sich. Sie hängen nur von einer gemeinsamen Schnittstelle ab. Und es kann einfacher sein, das System nach Zusammensetzung zu erweitern, als eine einzelne Vererbungshierarchie zu verwenden.

In einem realistischen Szenario benötigen Sie jedoch möglicherweise eine komplexere Handhabung zwischen der Synchronisation von Physik und Grafik. Beispielsweise muss die Physiksimulation möglicherweise in einem festen Zeitschritt (z. B. 30 Hz) ausgeführt werden, während das Rendern variabel sein muss. Möglicherweise müssen Sie die Ergebnisse aus der Ausgabe der Physik-Engine interpolieren. Einige Physik-Engines (z. B. Bullet) unterstützen dieses Problem jedoch direkt.

Unity lieferte eine gute Referenz ihrer Komponenten , die einen Blick wert war.

Milo Yip
quelle
Dies beantwortet die Frage überhaupt nicht, da 2 Komponenten nichts darüber aussagen, ob sie die Netzdaten gemeinsam nutzen oder nicht.
Maik Semder
2
Tatsächlich bietet es ein besseres Design, was völlig legitim ist.
JCora
7

Engines wählen normalerweise die erste Option (eigenes Physik-Mesh und eigenes Render-Mesh), da sie sowohl in Qualität als auch in Quantität sehr unterschiedliche Daten benötigen.

Qualität, weil sich die Physik-Engine nicht um Texturkoordinaten, normale Gruppen und all diese ausgefallenen Rendering-Dinge kümmert. Jeder von ihnen erwartet, dass die Daten in einem ganz bestimmten Layout auf Ausrichtungsprobleme, Packen, Verschachteln von Daten usw. zurückzuführen sind.

Menge, da das Physiknetz normalerweise viel weniger Dreiecke aufweist, ist es eine vereinfachte Version des hochauflösenden Rendernetzes.

Indem wir beide entkoppeln, stellen wir sicher, dass wir eine Woche tweeten können, einschließlich der Änderung des Datenlayouts für eine bessere Leistung, ohne die andere zu beschädigen. Es ist viel skalierbarer.

Maik Semder
quelle
0

Neben der großartigen Antwort von @Millo Yip möchte ich Sie nur daran erinnern, dass Sie dieselben Daten mit dem Controls-Modul und dem AI-Modul teilen müssen. Wenn ich mich nicht irre, haben die meisten Audiobibliotheken eine Vorstellung von der Position des Sound-Emiters Daher müssen Sie die Daten auch für dieses Modul freigeben.

ManicQin
quelle
0

Wie andere gesagt haben, ist es ziemlich üblich, dass der interne Datenstatus der Physik getrennt vom internen Datenstatus der Rendering-Engine verwaltet wird. Es ist häufig üblich, dass sogar die Transformationsdaten (Position / Orientierung / Skalierung) getrennt von Physik und Renderables gespeichert werden, da möglicherweise ein Spielobjekt existiert, das weder von der Physik auferlegt noch gerendert wird, sondern eine Weltposition für andere Mechaniker erfordert.

Wie die Daten von der Physik zum Rendering gelangen, liegt ganz bei Ihnen.

Sie können dies über einen subsystemübergreifenden Versandprozess mithilfe von Ereignissen / Nachrichten tun. Sie können dies tun, indem Sie eine öffentliche Schnittstelle des Render-Subsystems für das Physik-Subsystem verfügbar machen, sodass die Physik einfach die Position eines bestimmten Renderables festlegen kann. Eine andere Option besteht darin, dass das renderbare Subsystem die Entität während der Aktualisierung nach der Transformation abfragt und die Position der renderbaren Komponente aktualisiert und anschließend gezeichnet wird.

Abhängig von Ihrem Spiel sind einige dieser Mittel natürlich cachefreundlicher und haben eine bessere Leistung als andere. Ich würde mich an dieser Stelle nicht zu sehr auf eine bestimmte Weise einlassen und ein Kommunikationsmuster auswählen und es versuchen. Sie können diesen Teil später leicht überarbeiten, um verschiedene Mittel zur Optimierung zu testen.

Naros
quelle