Externes Laden von Sprites und Memory Leak

  • Allgemein

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Externes Laden von Sprites und Memory Leak

    Hallo mal wieder!

    Ich habe schon vor einiger Zeit entdeckt, dass jedes Mal wenn ich in meinem Spiel im Map Editor eine Map lade, der benutzte Arbeitsspeicher wächst und wächst ...
    und dachte, das würde einfach daran liegen, dass ich nur sprite_add() ohne vorheriges Löschen von alten Sprites verwende.
    Für die Modding-Möglichkeiten die mein Spiel bieten soll ist es essentiell, dass die Ressourcen extern geladen werden.

    Nun habe ich die letzten paar Tage herumprobiert, habe sprite_replace, sprite_add mit vorigem sprite_delete ausführen lassen,
    habe mein Spriteladesystem komplett überdacht, nur um dann drauf zu kommen, dass sich nichts geändert hat ... rein GAR nichts!
    Heute habe ich mich umgesehen und gegooglet, und bin dann auf das hier gestoßen:

    vom Yoyogames Tech Blog
    Loading sprites and backgrounds from an external source can be done in GameMaker:Studio, as can creating new assets using functions like sprite_duplicate(). However each new asset that you create in this way will also create a new texture page, meaning that (for example) adding 10 new sprites will create 10 new texture pages! And each time you draw these sprites it is a new texture swap and a break in the batch to the graphics card.
    As you can imagine, this is not very efficient, and so (unlike previous versions of GameMaker) it should be avoided, with all the graphic assets being added to the game bundle from the IDE. Note that you can use these functions for adding/creating small numbers of things and they won't adversely affect performance, but adding many, many images in this way should always be avoided as it will have an impact.


    Das ist in meinen Augen irgendwie eine Frechheit.
    Als würde sich Yoyogames bewusst sein, dass sie da einen dicken Memory-Leak eingebaut haben und ihn einfach nicht entfernen wollen, da Studio "eh nur für kleine Spiele gedacht ist".
    Ich habe bisher keinen Weg gefunden, erstellte Texture Pages ingame wieder zu löschen und habe auch mit der Funktion draw_texture_flush() herumexperimentiert, jedoch ohne Erfolg.
    Und als ich das Laden der externen Sprites einmal ausgestellt hatte, war ich überrascht zu sehen, dass der Arbeitsspeicher sich zwar nicht mehr so schnell füllt wie vorher, aber immer noch langsam voller wird
    (ca. 200 mb pro Ladevorgang des Spritepakets, ca. 50 mb ohne), d.h. dass der Memory-Leak auch da ist wenn man nur Sprites verwendet, die sich brav nach Yoyogames-Vorgabe im Ressourcenbaum befinden ...

    Meine Frage jetzt, da ich gesehen habe, dass das Thema schonmal aufgekommen ist, gibt es irgendeinen Umweg? Irgendeine DLL die man, zumindest für Windows verwenden kann? Oder sind größere Projekte mit Map-Editor jetzt nicht mehr dafür gedacht mit dem GM gemacht zu werden und es gibt keinen Ausweg? Irgendwie ein wenig frustrierend, wenn der Gamemaker solche Schranken setzt ...
  • Die Umstellung in Studio an sich macht schon Sinn, da das Zusammenfassen von Texturen in Texture Pages einen guten Geschwindigkeitsvorteil mit sich bringt, da Texturen von der selben Page in einem Batch an die Grafikkarte geschickt werden können. Nur das Verteilen der Texturen auf diese Pages sollte man natürlich vorher machen und nicht zur Laufzeit. Das macht dein Mod-Problem natürlich schwieriger, da du jetzt selbst eine Texturepage bauen musst, was direkt so nicht unterstützt wird. Wie im verlinkten Thread vorgeschlagen müsste sich sowas aber über Surfaces lösen lassen. Eine Surface ist eine Textur, die du zur Laufzeit einmal füllen kannst und danach immer wieder zeichnen kannst. Du kannst dir eine geschickte Möglichkeit einfallen lassen, die Surface mit verschiedenen Grafiken zu füllen und dann später mit draw_surface_part(...) Teile dieser Surface zeichnen. Kann sein, dass du dafür immer noch sprite_add benötigst, um die Textur einmal in die Surface reinzuzeichnen, danach kannst du das Sprite aber wieder löschen. Ich würde nicht sprite_create_from_surface(...) und sprite_add_from_surface(...) verwenden, da das dann wieder eine Kopie des Inhalts der Surface erstellt und damit ist der Vorteil natürlich wieder dahin...
    Einige meiner Spiele:
  • Erstmal danke für die schnelle Antwort.

    Wenn ich Surfaces für das Spriteset verwende habe ich nur leider das Problem, dass die Surface noch irgendwie in das Spiel hineingeladen werden muss.
    Mit Modding-Möglichkeit meine ich nämlich das externe Bearbeiten von Texturen in Photoshop, Paint ... o.ä.
    Wenn man dann ingame zwischen verschiedenen Umgebungsmods wechselt, häuft sich dann alles im Arbeitsspeicher an.
    Was ich bräuchte wäre eine Funktion mit der ich während der Laufzeit Sprites zu Texturepages zuweisen kann.

    Ich werde mir mal was überlegen bez. Surfaces. Wenn man zumindest Surfaces aus dem Speicher löschen kann, dann ist das schon mal was.
    Obwohl ich wohl irgendwann auf Probleme stoßen werde, da viele Objekteigenschaften (Kollisionserkennung z.B.) fehlen werden, oder
    sich nur schwer umsetzen lassen, und Transparenzprobleme auftreten werden, aber naja ... mal sehen.

    Mich ärgert es, dass man Texturepages nicht einzeln ansprechen und löschen kann, und dass sich alles einfach anhäuft.
    Ich hätte mir mehr erwartet von Yoyogames.

    EDIT:
    Zumindest für Windows ist das Problem nun gelöst, dank einer DLL! :)
    *Freudenschrei*! Die hätte ich natürlich früher auch entdecken können ...

    EDIT 2:
    Ich habe die DLL nun einem Härtetest unterzogen, dabei hat sich herausgestellt, dass in den Prozessen (Task-Manager)
    der Wert immer zurückspringt zu ca. 20 MB, aber im Reiter "Leistung" sieht man weiterhin, dass sich der Arbeitsspeicher füllt.
    Wenn ich das Laden der Sprites einige Male hintereinander ausführe, dann wird der Speicher voll
    und es kommt nachwievor der Fatal Error "Out of Memory".
    Möglicherweise hilft die DLL ein bisschen, aber was da bei den Prozessen steht ist ein Trugbild ...
    Ich frage mich, wo der ganze Müll hinkommt, wenn er nicht bei den Prozessen ersichtlich ist.
    Hat da jemand eine Erklärung?

    EDIT 3: (ein Tag später)
    Habe nun mein Spiel optimiert und lade die externen Sprites wirklich nur dann ins Spiel hinein wenn es notwendig ist.
    Außerdem hat es einen positiven Effekt wenn man die cleanmem.dll sequentiell ausführt (derzeit alle 120 Steps),
    auch wenn mal viel auf einmal passiert, nach einer Weile normalisiert sich die Arbeitsspeicherauslastung wieder.
    Also es funktioniert nun wie gewünscht. Der einzige Nachteil mit der DLL ist nur, dass sie Windows-Only ist,
    aber es wird sich schon ein Weg finden.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von RLP () aus folgendem Grund: funktioniert nun mit Anpassungen