Trainz und die Performance

  • Bei einer Software wie Trainz, die von gewissenhafter Erweiterung lebt, ist es sehr schwierig möglich, die Software als solche für Probleme verantwortlich zu machen. Das bedeutet nicht, dass Trainz fehlerfrei ist. Etwa die GUI verursacht bei mir mit jedem "Update" der angezeigten Geschwindigkeit einen kurzen Stopp, was aufhört, wenn ich die GUI mittels F5 ausschalte.

    Es kommt ganz oft auf eine gewissenhafte Auswahl der Objekte an. Wir mit T:ANE und TRS19 haben schon Glück, dass wir mittels 64Bit im Vergleich zu Früher mehr Resourcen vom PC zur Verfügung gestellt bekommen, was zu mind. ein wenig das ganze kompensieren kann. Schaut man sich dazu mal im Nachbarforum zum Thema Train Simulator um, erkennt man, dass gerade diese Nutzer vom TS durch die relativ schlechte Performance des Simulators umso mehr darauf bedacht sind, effiziente und schonende Inhalte in ihren TS einzubauen. Das geht soweit, dass man sogar Autoren von zum Download angebotenen Inhalten auch mitteilt, wenn Verbesserungen möglich sind. Das haben wir mit Trainz leider noch nie richtig begriffen. Auf der DLS finden sich Objekte wie Parkbänke und Straßenlaternen mit einer Dateigröße von bis zu 100MB. Durch den einfachen Zugang dazu landen solche Objekte schnell auf der Platte, im Editor sieht man den Objekten dann ihre Dateigröße gar nicht an und verbaut es im Eifer des Gefechts auch noch auf der eigenen Strecke. Das aber nur mal als Beispiel, es gibt auch andere Möglichkeiten zur Verbesserung. Ich baue schon ewig Objekte für eine Vielzahl an Simulatoren (habe sogar schon Inhalte für Transport Fever in den Steam-Workshop gestellt).


    Wenn ich ein Objekt baue, dann stelle ich mir folgende Fragen:


    - Sieht man dem Objekt an, wie es sich auf die Performance auswirkt?

    Beantwortet man diese Frage für sich mit nein, ist da etwas schief gelaufen!

    - Inwieweit ergibt es Sinn, gerade in Bezug auf einen Eisenbahnsimulator, das Objekt so zu bauen wie ich es gemacht habe?

    Jeder mag hochdetaillierte Objekte, es sieht gut aus, wenn an einem Haus Fenster und Türen ausgearbeitet sind. Aber man sollte sich trotzdem fragen,

    ob es in einem Eisenbahnsimulator Sinn ergibt ein Wohnhaus so hochdetailliert zu erstellen. Man könnte es einfacher halten und dafür nützliche Funktionen, wie ein vom Wetter abhängiges Aussehen einzubauen (Ein Dach das mit Schnee bedeckt ist, zB).


    - Habe ich gängige Techniken angewandt, um zu mind. ernsthaft zu versuchen, meine Arbeit zu optimieren?

    In der heutigen Welt der 3D Grafik gibt es unzählige Techniken, man kann so gut wie nie versuchen die richtige Balance zwischen guten Texturen und detailliertem Mesh zu finden. Es gibt Optimierungsmöglichkeiten für beide Seiten: LOD-Stufen ermöglichen das Umschalten zwischen Meshes unterschiedlicher Detailstufe. Bibliotheken erlauben mehreren Meshes die gleiche Texturen zu nutzen, was natürlich nur dann Sinn ergibt, wenn es eine Fülle an Objekten gibt, die sich Texturen teilen (zB Vegetation).


    'Scripts sind das Wundermittel'!


    Nicht jedes klitzekleine Objekte muss einen Scriptthread haben, der sekündlich oder gar in der Framezeit (wobei Trainz da nen Riegel vorschiebt) irgendwelche Werte überprüft. Führerstände müssen die Update-Loop (die mit jedem Frame geschossen wird!) auslassen, wenn Sie nicht vom Spieler gesteuert werden.

    Bibliotheken können nicht nur als Scriptsammlung sondern auch als eigenes Script im Spiel Threads zur Verfügung stellen und mittels PostMessage(World, ...) Statusupdates an die Spielwelt senden -> Ein Thread für sämtliche Objekte, statt 100 Objekte mit 100 Threads. Gerade wenn jemand mit Scripting anfängt erscheint oftmals als einfachster Weg ein Thread, der zur Überprüfung läuft, statt auf ein auf Ereignisse basiertes System zu setzen. Das ist logisch, weil ein Ereignisbasiertes System etwas schwieriger zu verstehen ist.

    Also auch hier: Muss das Script so sein, wie ich es gemacht habe? Sollte ich vielleicht jemand anderen nochmal drüber schauen lassen für eine 2. Meinung?


    Sind meine Scripts auf dem aktuellen Stand?

    Die API ändert sich ständig. Kompatibilitäten brauchen Performance und tragen null zur Verbesserung bei. Gerade in TRS19 haben wir nichts vom neuen Streckenformat und nichts von der Streaming-Funktion, wenn die Software auf alte Objekte und Scripts Rücksicht nehmen muss. Zu allem Übel scheint der TRS19 komplett zu versagen, wenn man die Funktion zum Streamen einschaltet, weil nichts mehr geht. Und dann wird der Fehler in der Software gesucht. Aber das ist nicht wahr, denn: Es gibt unter meinen von N3V Games eingebauten und standardmäßig für jede Strecke geladenen Objekten nur eine Ausnahme, wo ein Script einen sog. Legacy-Call (also einfach ausgedrückt einen veralteten Funktionsaufruf, der noch zur Kompatibilität nutzbar ist) ausführt. Und das ist ein veraltetes Senden einer Nachricht.


    Zum Abschluss;
    Unter TS12 waren die sog. Performance Statistiken im Editor und Fahrermodus noch ein Begriff. Hier finden sich auch in TANE und TRS19 Informationen, die wertvoll sein können.


    - Worst Script Library

    Taucht da ein Script auf, dass zu einem Objekt gehört, welchem man relativ wenig Funktion zurechnent, ist hier etwas komisch! Die Zahl dahinter in Klammern gibt die Anzahl der Calls an, die das Script bisher geleistet hat. Achtung: Ein Führerstand bekommt mit jedem Frame zu mind. einen Call auf seine Update-Funktion.


    - Worst Index Count & Worst Buffer Count

    Das sind Werte die sich auf die Kombination der sog. Index- und Vertex-Buffer beziehen. Je kleiner das Objekt bei Worst Index Count (und je größer die Zahl dahinter), desto eher wurde verschwenderisch und uneffizient gebaut. Nicht jedes Polygon muss drei eigene Vertices haben, sondern kann sich diese auch mit anderen Polygonen teilen. Hierzu stellen die Modellierungsprogramme Funktionen zum Verschweißen von Vertices zur Verfügung.

    Worst buffer count zählt die Anzahl der Vertex-Buffer, je größer die Zahl dahinter, desto mehr einzelne Meshes hat das Objekt. Das ist bei zusammengesetzten Objekten, wie Führerständen und solchen des neuen Gleistyps technisch nicht anders lösbar. Auch hier gilt: Je unbedeutender das Objekt, desto schwerwiegender ist eine hohe Angabe an dieser Stelle.


    Quote

    "Hier finden sich Informationen, die wertvoll sein können"

    Man sieht nun, die Angaben bedeuten nicht zwingend etwas schlimmes. Es muss geschaut werden, wie viele Objekte man auf der Map so verbaut hat und dann bewerten, wie der Einfluss der Objekte, die angegeben werden, eigentlich im Vergleich zum Rest angenommen werden sollten. Beispiel: Ich fahre mit einem voll ausgestattetem und ausmodelliertem Fahrzeug mit einer Fülle an Funktionen auf meiner Strecke. Dann würde ich erwarten, dass der Führerstand eventuell in den Statistiken auftaucht. Taucht aber stattdessen Haus XY 1000m Weg von der Strecke dort auf, sollte ich mir jenes Haus nochmal anschauen und seine Position auf meiner Strecke überdenken.

    Also immer schön vergleichen, denn Objekte rauswerfen weil sie dort auftauchen ist dann doch zu brachial :) Es geht hier nämlich um die Bewertung, nicht um das Herausfiltern von schönen Objekten.

Comments 9

  • Quote

    Nicht jedes Polygon muss drei eigene Vertices haben, sondern kann sich diese auch mit anderen Polygonen teilen. Hierzu stellen die Modellierungsprogramme Funktionen zum Verschweißen von Vertices zur Verfügung.

    Das predige ich seit Jahren und alles was bislang von allen Daechern gepfiffen wird :"Kreisch, die Polygone, die Polygone...".

    • Das weiß ich :)


      Ich finde man sollte lieber schauen, ob ein Straßenschild tatsächlich eine 2048er Textur benötigt.
      Eine 512er reicht oftmals, dafür für ein paar Details ein paar Polys mehr am Mesh ist unter'm Strich dann doch besser.

      Like 1
    • Also nach meinen Erfahrungen, die ich teilweise auch durch empirische Versuche erlangt haben, kann man in der Skala von Performance-Killer bis hin zu vertretbar eindeutig eine Reihe erstellen.


      Von schlecht nach macht nicht allzu viel:


      - Anzahl der Materialien (nicht zu verwechseln mit der Anzahl der Maps!)

      - Anzahl der Textur-Maps

      - Groesse der Textur-Maps

      - Anzahl der Vertices


      Von Polygonen schreibe ich bewusst nichts...

    • Was ich auf jeden Fall deiner Liste noch hinzufügen würde, sind Transparenzen.

      Ich habe Tests gemacht, die zeigen, dass 2D Bäume ab T:ANE immer mehr die schlechtere Wahl wurden.

      Scheinbar überwiegt die aufwändigere Beleuchtung mittlerweile die damaligen Vorteile von 2D Bäumen gegenüber ausgearbeiteten Bäumen. Im Nachhinein muss ich sagen, dass es auch logisch erscheint. PostProcessing und die physikalisch näher kommendere Beleuchtung in TRS19 müssen Transparenzen ja auch mit einbeziehen.

      Like 1
    • Das, und außerdem nutzen SpeedTrees einen eigenen und recht performanten Renderer. Speedtrees in der Entfernung werden z.b. nicht jeden Frame gerendert, was aber nur auffällt, wenn man versucht, weit entfernte Bäume im Editor zu verschieben. Die werden erst nach ein paar Sekunden am neuen Platz angezeigt.


      Ich glaube viele dieser Fehler sind auch dem geschuldet, dass viele Tutorials Neulingen ein falsches Verhalten antrainieren, da die meisten Tutorials für 3d-Programme (konkret ist das zumindest bei Blender so) auf einen Rendereinsatz hinarbeiten. Da gilt dann ein je mehr desto besser und es wird zu Wundermitteln wie Bevel o.Ä. geraten die in einer Echtzeitumgebung kompletter Unfug sind. Genauso wird dann auch jedem kleinen Detail ein neues Material zugewiesen, denn anders als die Engine von Trainz welche die Parameter über die Textur pro Pixel steuert, ists beim Rendern oft eine globale Einstellung pro Material.


      Dann sind da so Sachen wie Mesh-Libraries mit Materialsharing und Mesh stitching. Fiel mir jetzt relativ leicht da ich bevor ich Blender angefangen hab zu lernen mit der Entwicklung für Trainz vertraut war und das alles logisch erschien. Aber da das halt doch ein recht Spielspezifischer Ansatz ist, denke ich dass auch viele Anfänger erstmal einen Moment brauchen, bis sie das Libraryprinzip verstanden haben. Ich muss auch mal ganz erlich sagen, dass Skriptlibraries als solches schon ein wenig dämlich umgesetzt sind mit der LibraryCall-Methode. Das macht so gut wie niemand sondern lädt dann lieber eine eigene Klasse mit eigenen Methoden.


      Gerne würde ich Sachen auch Ereignisbasiert umsetzen, statt ständig über einen Thread zu pingen. Es kommt mir aus anderen Sprachen auch wie ein Verbrechen vor, die verbotenen Worte "while(true)" zu schreiben, aber scheint hier gängige Praxis zu sein. Die meisten bauen dann noch nicht mal nen sleep ein...
      Rührt aber leider alles daher, dass das Spiel von sich aus recht wenige Ereignisse ausgibt.


      Ich schau mir das mal an wenn ich wieder was habe, was dazu verleitet, vieles mit einem Thread auszustatten. Wusste gar nicht, dass PostMessage an die World funktioniert, denn PostMessage zum Broadcast wird ja in TRS19 von abgeraten.



      Greets; Mika

      Like 1
    • Moin Mika,


      doch PostMessage(World, ...) funktioniert. Musst den Handler dann aber auch AddHandler(World,...) setzen.

      Seit T:ANE Sp3 ist World ein GameObject, funktioniert aber auch mit Interface.


      Quote

      dämlich umgesetzt sind mit der LibraryCall-Methode

      Das ist nicht wahr. Schonmal was von Methodenaufruf gehört? Du brauchst die LibraryCall nicht, es geht viel eleganter.

      Der dicke Vorteil von Scriptlibraries, du solltest dir das nochmal in Ruhe anschauen.


      Quote

      Rührt aber leider alles daher, dass das Spiel von sich aus recht wenige Ereignisse ausgibt

      Jain, es ist viel hinzugekommen, was nicht in den Scripts steht. Aktiviere mal das Router/Message-Logging im Developer-Reiter des Launchers. Dann siehst du, wie viel eigentlich da hin und her geschickt wird. Und es ist nie verkehrt, wenn man auf Ereignisse im Script reagiert indem man eine Message schickt. Das kann entweder an "World" gehen oder gar an sich selbst, das ist nicht schlimm. Wenn man sich da zu mind. etwas dran hält, dann reichen die eingebauten Messages dicke.


      Als Beispiel für einen deutschen Führerstand:
      Wenn die PZB eine Zwangsbremsung auslöst, einfach ne Message mitschicken, dass ne Zwangsbremsung ausgelöst wird. Dann kann ein anderer der eine Session bastelt mit einer Rule eventuell darauf reagieren, etc.


      Aber mal was anderes: Das ist eine sehr angenehme Diskussion hier! :)

      Like 1