Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

12.11.2015, 00:02

Game/Engine Basis-Aufbau

Hallo,

ich hoffe das ist der richtige Bereich für die folgende Diskussion.
Nach diversen OpenGL Demos (Windows - C++ | Android - Java | Browser - JavaScript) möchte ich nun ein paar Sachen zum Aufbau klären.

In so gut wie jedem Tutorial hat man folgenden Aufbau:

Quellcode

1
2
3
4
5
6
7
8
9
10
RenderWindow window;
GameScene scene;

while(window.isOpen())
{   
scene.update(); 
window.update();
}

window.destroy();


Man erstellt ein Fenster und einen OpenGL-Context, anschließend hat man seine "Main-Game-Loop" und aktualisiert alle Komponenten.
Dabei hat z.b. GameScene Child-Elemente in Form eines GameObjects, welches wiederum weitere Children haben kann.

Bei diesem Aufbau erkennt man sofort wie abhängig die Objekte voneinander sind und dass man Operationen wiederholt.
Sagen wir ich habe eine Klasse die z.b. die Kollisionserkennung der GameObjects vornimmt und eine Klasse die die GameObjects rendert.

Meine Kollision-Klasse holt sich GameObject #1 und anschließend GameObject #2, danach macht die Render-Klasse das Gleiche.
In meinen Augen recht ineffektiv und problematisch bei sehr vielen Objekten(Partikel-System) oder beim Multithreading.


Ich habe mir überlegt dass ich für jede Kernaufgabe ein eigens unabhängiges "System" habe, welches nur seine einfache Arbeit erledigt.


Als Beispiel habe ich einen RenderManager der für sich alleine durch eine Liste läuft und die Objekte zeichnet.
Die Klasse hat keine Ahnung über irgendwas, sie zeichnet nur die Objekte in der Liste.

Ich habe mehrerer solcher Manager die unabhängig voneinander laufen und voneinander auch nichts wissen.
Meine Scene-Klasse enthält die Logik und befüttert die jeweiligen Manager.

Als Beispiel: Ich habe eine Spielfigur die gezeichnet werden soll, dessen Kollision abgefragt werden soll und die brennt.
Die GameScene würde dann ein RenderObject, ein PhysicsObject und ein ParticelObject an die jeweiligen Manager schicken.

Die Frage die sich jetzt stellt lautet: Wie kommunizieren die Manager, wenn sie nur ihre eigene kleine Welt kennen ?
Ich dachte da an ein Observer-System wie aus der Java-Welt.

Ich habe einen EventManager der Listener registrieren kann und Events an diese abfeuern kann.
Beispiel:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
EventManager eventManager;
LogManager logManager(eventManager);
WindowManager windowManager(eventManager);
PhysicsManager physicsManager(eventManager);
RenderManager renderManager(eventManager);
ParticleManager particleManager(eventManager);
AudioManager audioManager(eventManager);
SceneManager sceneManager(eventManager);

eventManager.fire(SceneEvent(SceneEvent.NEW_SCENE, "GameScene"));

while(windowManager.isOpen())
{   
eventManager.update();  
physicsManager.update();    
renderManager.update(); 
particleManager.update();
}


Der Übersicht halber habe ich auch hier eine "Main-Game-Loop", jedoch laufen die Manager unabhängig voneinander und wissen auch nicht welche "Scene" gerade aktiv ist.

Haltet ihr das für einen brauchbaren Aufbau, auch in Hinsicht auf den Observer ?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

12.11.2015, 06:38

Bei diesem Aufbau erkennt man sofort wie abhängig die Objekte voneinander sind und dass man Operationen wiederholt.
(...)
Meine Kollision-Klasse holt sich GameObject #1 und anschließend GameObject #2, danach macht die Render-Klasse das Gleiche.
In meinen Augen recht ineffektiv und problematisch bei sehr vielen Objekten(Partikel-System) oder beim Multithreading.
Ich habe mir überlegt dass ich für jede Kernaufgabe ein eigens unabhängiges "System" habe, welches nur seine einfache Arbeit erledigt.
Klingt für mich so, als ob sich die beiden Teile widersprechen, bzw. der zweite schon deutlich macht, dass das Problem des ersten gar nicht gelöst wurde. Jedes System durchläuft alle seine verwalteten Objekte nacheinander. Da das jedes macht, ist doch auch hier die Wiederholung drin. Aus meiner Sicht sogar viel mehr, weil jedes System alle durchgehen muss. Beim klassischen OO-Design durchlaufe ich einmal alle.

Insgesamt ist das Problem bei solchen Events, dass Du plötzlich tausende davon hast. Je mehr Systeme Du hast, desto mehr solcher Events werden geworfen. Wir hatten hier im Forum letztens erst den Fall, dass jemand genau dieses Problem hatte, als er wie Du den Component-System-Ansatz verfolgt hat. Er hat am Ende durch seine tausend Events nicht mehr durchgesehen und sich gewünscht er hätte es anders gemacht. Das Problem dabei ist außerdem, dass solche Cross-Referenzen und Cross-Calls das Prinzip und den großen Vorteil des Data-Oriented-Designs hier eigentlich komplett vernichten. Die Idee hinter solchen Component-Systemen ist einerseits natürlich die lose Kopplung, andererseits aber auch die optimierte Leistung durch Cache-Lokalität. Das dichte Event-Netz zerstört beides. Du bekommst eine scheinbar lose Kopplung, bei der effektiv aber doch wieder jeder von jedem abhängt (gerade verschiedene Datentypen, die hin und her gereicht werden müssen, machen schon deutlich, dass oft jeder jeden kennt). Durch die hohe Event-Verknüpfung wird die Cache-Lokalität ebenfalls zerstört.

Lose Kopplung lässt sich auch mit einem klassischen Ansatz prima erreichen. Probleme mit Partikeln sind davon total unabhängig. Genauso Multithreading. Mit dem Component-Ansatz in Kombination mit Events, kann Multithreading genauso einfach oder unmöglich sein wie bei einem klassischen Ansatz.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

3

12.11.2015, 14:00

Die Frage die sich jetzt stellt lautet: Wie kommunizieren die Manager, wenn sie nur ihre eigene kleine Welt kennen ?
Ich dachte da an ein Observer-System wie aus der Java-Welt.

Gegenfrage: Wieso genau müssen diese Manager miteinander kommunizieren? War die Idee nicht gerade im Absatz davor noch, dass die Manager voneinander unabhängig sind und nichts vom Rest der Welt wissen müssen?

Ich habe einen EventManager der Listener registrieren kann und Events an diese abfeuern kann.
Beispiel: [...]

Davon würde ich schwer abraten. Eventsysteme sind meiner Erfahrung nach extrem problematisch, weil sie extrem schnell zu einem völlig undurchschaubaren und unbeherrschbaren Kontrollfluss führen (und sie sind dabei auch noch furchtbar ineffizient). Ich habe schon massive Schwierigkeiten in wesentlich weniger komplizierten Systemen, als dem, was du da zu basteln gedenkst, erlebt...

Werbeanzeige