Viele aktive Objekte ohne Performance Probleme

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

  • Viele aktive Objekte ohne Performance Probleme

    Hallo Community,

    "Viele aktive Objekte ohne performance Probleme" ist etwas was ich nie wirklich beim Game Maker hinbekommen habe.
    Ich habe ein paar ansetze, kann aber meist nur geringe unterschiede wahrnehmen, oder ich gehe sofort davon aus, dass das nichts wird.
    (Hierbei geht es hauptsächlich um die Platform: Android & iOS)

    Mein Problem etwas genauer:
    Ich habe ein kleines Feuer mit Hilfe von Objekten (fast wie Particeln) erstellt.


    Das Problem ist halt, dass das sehr viel Leistung nimmt und dadurch z.B. auf einem Smartphone schon fast unspielbar wird.
    Nun habe ich schon erwähnt, dass ich ein paar Ansätze habe, aber nicht die Möglichkeit hatte alles zu testen, weil ich grundsätzlich nicht wirklich verstehe wie Draw calls "gehandelt" werden, oder was im Endeffekt weniger Leistung nimmt.

    3 Ansätze um dieses Problem zu lösen:
    1) Man hat ein Array in dem Koordinaten zu mehreren dieser Kugeln gespeichert werden. Im Step event wird dann jedes Array verändert, also die Position, so wie sich ein einzelnes dieser Objekte bewegen würde.
    Im Draw event werden dann alle Arrays durchlaufen und gezeichnet.
    2) Man macht die Objekte invisible und zeichnet alles auf ein Surface. Die Objekte haben immer noch ein Step event und das Surface updated sich in jedem Step. (ich glaube das bringt überhaupt nichts :D)
    3) Man erstellt ein Riesen Sprite-Strip mit einer Animation die dem Bild oben ähnelt und lässt das einfach 1 mal zeichnen und das läuft dann durch. Problem hierbei: 60 Bilder die Sekunde währen etwas groß für solch eine Animation, spricht: nicht flüssig.

    Habt ihr eine bessere Lösung? Falls ich etwas nicht genau erklärt habe, einfach nach Fragen :)

    Danke im voraus!
  • ich hatte aktuell das selbe problem wenn eine frucht zermatscht wird spawnt darunter ein matschfleck, spielt man aber 2 Minuten sind so viele Flecken vorhandne das es auf HTML 5 Pain in the ass wird deshalb rate ich dir in den flammen objekten selbst folgendes zu tun:

    lass im Step eine variable hochgehen ist die variable dann (bei roomspeed 60) größer als 800 zerstöre das objekt, das ist ja sowieso egal weil drüber schon paar neue sind, dadurch sind die alten objekte tot und das verbessert die Ressourcen, zudem solltest du wenn die flammen aus dem schirm sind die condition outside boundry nutzen um sie ebenfalls zu zerstören weil diese im BG ja weiter machen
  • Also die Objekte werden immer kleiner und sie werden zerstört sobald man sie nicht mehr sehen kann, also bei image_xscale = 0 und image_yscale = 0.
    Außerhalb des Raumes werden sie auch zerstört.

    Ich hab noch mal nachgeschaut, im durchschnitt sind 280 solcher Objekte aktiv. Kein Problem für einen PC oder Laptop, aber für Smartphones leider schon.
  • Lade dir doch mal meine Arbeit runter:

    Regeneffekt mit gridbasierten Kollisionen - konstante 60 FPS bei tausenden Tropfen!

    Das funktioniert wie dein Lösungsansatz 1, ist aber flexibler da ich eine ds_list verwende. Damit solltest du deine Flammen flüssig lodern lassen können.
  • Nico001 schrieb:

    Also die Objekte werden immer kleiner und sie werden zerstört sobald man sie nicht mehr sehen kann, also bei image_xscale = 0 und image_yscale = 0.
    Außerhalb des Raumes werden sie auch zerstört.

    Ich hab noch mal nachgeschaut, im durchschnitt sind 280 solcher Objekte aktiv. Kein Problem für einen PC oder Laptop, aber für Smartphones leider schon.


    dann zähl die instanzen und reduziere sie mit einem externen control event oder nutze den Ansatz von Morpheus dessen Avatar digizeugs kotzt xd
  • ​Lade dir doch mal meine Arbeit runter:Regeneffekt mit gridbasierten Kollisionen - konstante 60 FPS bei tausenden Tropfen!Das funktioniert wie dein Lösungsansatz 1, ist aber flexibler da ich eine ds_list verwende. Damit solltest du deine Flammen flüssig lodern lassen können.


    Danke, ist irgendwie total an mich vorbei gegangen :D

    Ja, ich hätte das wahrscheinlich am ende auch mit einer Liste gemacht, ist etwas simpler.
    Ich hatte ein paar bedenken bei diesem Ansatz, denn ist das nicht das was der GM eigentlich im Hintergrund machen sollte? Eine Liste mit Objekten die erstellt werden, die dann Koordinaten, sprites etc enthalten und er updatet
    das einfach nur? Deswegen ging ich davon aus das es keinen großen unterschied machen sollte
  • Ich denke mal dass Gm bei einem Objekt mehr Hintergrund Aufgaben erledigt und deshalb etwas mehr zieht.
    Ein Bug ist mehr als nur ein Bug, es ist ein... Käfer!
    Egal, wie gut du eine Mauer baust, sie fällt um.... der klügere gibt nach :D

    Willst du mit mir auf Discord Chatten/Quatschen?
    Meine Husi's Tutorial Reihe
  • So ich hab jetzt mal einen test gemacht und eine ds_list erstellt die folgende Werte beinhaltet:
    - 280*4 Einträge, für 280 einzelne Kugeln die jeweils 4 Eigenschaften haben:
    - X
    - Y
    - Scale
    - Direction

    Am Anfang werden 280 Kugeln in eine Liste geschrieben, also 280*4 (1120) Werte werden eingetragen.
    Diese Werte werden in einem Draw Event ausgelesen und gedrawed:

    GML-Quellcode

    1. for (i = 0; i < ds_list_size(global.fireList)/4-1; i++) {
    2. var fireX = ds_list_find_value(global.fireList,i*4);
    3. var fireY = ds_list_find_value(global.fireList,i*4+1);
    4. var fireScale = ds_list_find_value(global.fireList,i*4+2);
    5. var fireDir = ds_list_find_value(global.fireList,i*4+3);
    6. if (fireScale-0.03 < 0) {
    7. ds_list_replace(global.fireList,i*4,random(room_width));
    8. ds_list_replace(global.fireList,i*4+1,room_height+30);
    9. ds_list_replace(global.fireList,i*4+2,1);
    10. ds_list_replace(global.fireList,i*4+3,90);
    11. }
    12. else {
    13. ds_list_replace(global.fireList,i*4,fireX+lengthdir_x(3,fireDir));
    14. ds_list_replace(global.fireList,i*4+1,fireY+lengthdir_y(3,fireDir));
    15. ds_list_replace(global.fireList,i*4+2,fireScale-0.03);
    16. ds_list_replace(global.fireList,i*4+3,fireDir+random(20)-random(20));
    17. }
    18. if fireScale > 0 and 1 > fireScale{
    19. draw_sprite_ext(spr_bubble,0,fireX,fireY,fireScale,fireScale,fireDir,merge_colour(c_red,c_yellow,max(fireScale,0)),1);
    20. }
    21. }
    Alles anzeigen


    Mein Ergebnis:
    Ohne Kugeln: ca. 900 FPS
    Mit Kugeln als Objekt: ca. 580 FPS
    Mit Kugeln in einer Liste: ca. 530 FPS

    Bedeutet: Die Liste ist was die Performance angeht schlechter als einzelne Objekte.
    Nach dem ich das festgestellt habe, habe ich mal einen Blick in das Regeneffekt Beispiel von Morpheus geworfen und gesehen das
    ds_list befehle ehr weniger verwendet wurden, sondern dass das meiste mit einem grid gemacht wurde.

    Jetzt ist die Frage: sind ds_list befehle evtl. schlecht für die Performance? Theoretisch wird in jedem Step 8*280 mal so ein Befehl ausgeführt.
  • mehrfach getestet? das mit der Liste kann n dummer Zufall sein!

    ansonsten mache ich per variable ein festes limit rein und wird das überschritten wird das alte zeugs gelöscht, damit bin ich bisher am besten gefahren
  • ansonsten mache ich per variable ein festes limit rein und wird das überschritten wird das alte zeugs gelöscht, damit bin ich bisher am besten gefahren

    Bei mir gibt es mittlerweile auch ein Limit von 280 Kugeln. Sieht nicht soo gut aus aber auch nicht schlecht also gerade so im Mittelfeld für solch eine Animation.

    mehrfach getestet? das mit der Liste kann n dummer Zufall sein!

    Also ich habe es mehrfach getestet, auch mit verschiedenen Limits.

    Evtl. ist mein Code auch totaler Müll und Resourcen verschwenderig wie sonst was, dass weiß ich halt eben nicht :D
  • Der Grid in meinem Regeneffekt dient nur für die Collisionsabfrage. Das Problem bei dir ist, dass es dann doch zuviele ds_list Einträge sind. Das Problem hatte ich Anfangs bei meinem Regeneffekt auch, dann kam ich aber auf die Idee, die ID eines Regentropfens, quasi die Instanz, in einer ds_list abzuspeichern aber die Attribute eines jeden Regentropfens widerum doch in einem Array. Schau dir mein Example mal genauer an!
    DIe ds_list wäre in deinem Fall dann nur ein Viertel so groß.
  • Ich habe die Liste komplett entfernt, denn bei mir werden die Kugeln nicht zerstört, sie werden zurückgesetzt auf deren Startattribute, also gibt es konstant 280 Kugeln.
    Die Variable global.fireInstances ist daher permanent auf 280.

    So sieht das Ganze jetzt aus: 4 Arrays für jedes Attribut.

    GML-Quellcode

    1. for (i = 0; i < global.fireInstances; i++) {
    2. if (global.fireScale[i]-0.03 < 0) {
    3. global.fireX[i] = random(room_width);
    4. global.fireY[i] = room_height+30;
    5. global.fireScale[i] = 1;
    6. global.fireDir[i] = 90;
    7. }
    8. else {
    9. global.fireX[i] += lengthdir_x(3,global.fireDir[i]);
    10. global.fireY[i] += lengthdir_y(3,global.fireDir[i]);
    11. global.fireScale[i] -= 0.03;
    12. global.fireDir[i] += random(20)-random(20);
    13. }
    14. if global.fireScale[i] > 0 && 1 > global.fireScale[i] {
    15. draw_sprite_ext(spr_bubble,0,global.fireX[i],global.fireY[i],global.fireScale[i],global.fireScale[i],global.fireDir[i],merge_colour(c_red,c_yellow,max(global.fireScale[i],0)),1);
    16. }
    17. }
    Alles anzeigen

    Es hat sich in der Performance nichts getan, hab ich mir aber schon gedacht. Ich denke das Hauptproblem ist nicht wie
    ich die Variablen bzw. Attribute anspreche, sondern das ich eine For-Schleife verwende. Ich habe damals immer öfter gehört das der GM eine schlechtere Performance hat
    sobald man Schleifen verwendet. Ob das Stimmt weiß ich jetzt nicht.

    Also das Ergebnis von eben bleibt: Wenn ich die Kugeln als Objekte erstelle hat man rund 50 FPS mehr.
  • Soll das aufn Smartphone flüssig laufen?

    edit: Achso oben sagst du ja dass es hauptsächlich um Android und so geht. Vielleicht könnte dir ein Shader mit GLSLES helfen. Das du vieleicht nur 8 verschiedene Flammenpartikel drawst und mit einem Shader vervielfachst. Weißt wie ich mein oder denk ich schon wieder zu kompliziert? Warum eigentlich keine Partikel?
  • Ja genau, es sollte hauptsächlich auf einem Smartphone laufen. Es klappt auch bei den neueren Modellen, aber bei älteren nicht und der zweite Grund währe noch den Energieverbrauch zu verbessern.An Shader habe ich noch gar nicht gedacht. Das könnte ich mal versuchen, bezweifle aber das es bei älteren Smartphones ordentlich Funktionieren wird, denn schon ein Shader zum bluren hat dasSmartphone zum kochen gebracht.

    Warum eigentlich keine Partikel?

    Meinst du das inbuild Particle System? Das liefert nicht das Ergebnis was ich erreichen will.

    Ich versuche noch momentan andere Sachen zu verbessern, zum Beispiel habe ich vorher eine Application Surface verwendet, aber da ich kein post processing mache werde ich direkt auf den
    screen buffer drawn. Mal sehen ob die Objekte vielleicht doch nicht so viel Leistung ziehen wie ich dachte.
  • Noch eine andere Idee, die aber etwas provisiorisch ist.
    Wie wäre es, wenn du mehrere Kugeln zu Mustern zusammenfasst.
    Zum Beispiel kannst du dann 14 verschiedene Muster a 10 Kugeln kreieren und aktualisierst dann nur die Muster, welche dann wiederum die Werte der Kugeln nach dem vorgebene Muster festlegen. Natürlich geht dann eine gewisse Zufälligkeit verloren, aber vielleicht hilfts.
  • Gute Idee! Werde ich auf jeden fall mal Morgen versuchen!

    Ich habe allerdings das Hauptproblem der Performance bei Smartphones gefunden, zumindest was Android angeht (noch nicht mit iOS getestet).
    Und zwar ist das Hauptproblem die Auflösung... klingt erst mal komisch wenn ich jetzt sagen die ursprüngliche Auflösung von 1024x768 war zu Hoch, ist aber anscheinend so.
    Erst mal hab ich gelesen, das ältere Android Geräte (so ca. 3 Jahre alt) ein Problem mit Surfaces und Auflösungen haben. Am besten sollte die Auflösung maximal 800x480 sein, alles
    darüber wird die performance immens beeinträchtigen. Bei meinem alten Samsung Galaxy S3 Mini was schreckliche specs hat, hatte ich 10 fps mit 1024x768 und 25 fps mit 800x400.
    Dann hab ich einfach mal die 1024x768 halbiert, also 512x384 und tada: 50 fps mit Effekten und alles drum und dran. Permanent 300 Instances aktiv, kein Problem. Das gute bei diesem kleinen Bildschirm ist halt auch, das man keinen Unterschied zu davor erkennt, oder nur sehr minimal.

    Jetzt werde ich einfach bei alten Geräten die Auflösung runter regeln und evtl. noch eine Option dafür einbauen. Schon krass wie viel die Auflösung ausmacht.