Ladebildschirm mit "Async Load Assets" - Node?

  • Hallo Leute,


    ich habe mal wieder eine sehr spezielle Frage, die mich aber schon länger beschäftigt. Nämlich der Ladebildschirm.

    Öffnet man ein neues Level einfach nur mit der "Open Level"- Node, bleibt das Spiel hängen (und/oder Bildschirm wird schwarz), so lange, bis das Level geladen ist und startet. Damit lässt sich kein Ladebildschirm realisieren (Denke ich).


    Man findet zu diesem Thema erstaunlich wenig Tutorials. Habe aber dann die Node "Async Load Assets" gefunden. Mit dieser Node habe ich es tatsächlich geschafft einen funktionierenden Ladebildschirm zu erzeugen. Denn damit lade ich die Assets asynchron im Hintergrund, während das Spiel nicht hängt.

    Btw.: Ich gebe in dieser Node den Kompletten Level an.


    Soweit so gut, aber mir drängen da Fragen auf:

    Wenn die Assets im Hintergrund laden, liegen diese doch im RAM des Computers. In meiner Vorstellung müllt man sich nach einiger Spielzeit doch den Rechner, bzw. den RAM zu. Deswegen gibt es ja anscheinend die "Garbage Collection" - Node, um alle Assets, die keine Referenzen besitzen, aus dem RAM zu entfernen. Diese Node wende ich auch an, aber ich habe das Gefühl, dass diese nicht richtig funktioniert.
    Wieso? Wenn ich mein Projekt starte und das Level laden lasse, dann dauert der Ladevorgang ca. 10 Sekunden. Nach dem Laden gehe ich ins Hauptmenü zurück und wende die "Garbage Collection" - Node an. Jetzt müssten doch die Assets im Level wieder aus dem RAM draußen sein, da diese Assets keine Referenzen mehr besitzen sollten. Starte ich den Level jetzt aber wieder, braucht der Ladevorgang weniger als eine Sekunde! Das heißt, dass die Assets im RAM noch liegen müssen. Starte ich mein Projekt neu, lädt es wieder wie normal ca. 10 Sekunden.


    Deswegen meine Frage. Übersehe ich etwas? mache ich was falsch? Oder habe ich ein grundlegendes Verständisproblem?



    Anscheinend lässt sich auch ein Ladebildschirm mit der "Load Stream Level" -Node realisieren. Dort kann man den RAM wieder leeren mit der "Unload Stream Level"- Node. Allerdings müsste ich bei mir ALLE Levels als Sublevels in EINEN Level integrieren oder? Falls ja, wäre das viel zu viel aufwand (über 40 Levels).


    Ich hoffe ihr könnt mir ein wenig Licht ins dunkle bringen :)


    Viele Grüße und einen schönen Tag euch

  • Da kann ich jetzt nur mit meinem Halbwissen glänzen.

    Es gibt in der Programmierung mehrere Arten des "Garbige Collectors", was ich jetzt mal in Anführungszeichen setze, weil es so nicht ganz stimmt, also vom Namen her.

    Das häufigste, was du beim Programmieren hast, bzw. auch sehr speziell bei C++ ist der Destructor einer Klasse. Es gibt einmal den Constructor, der hat den Namen der Klasse, zum Beispiel KLASSENNAME, und dann den Destructor, dargestellt als ~KLASSENNAME. Im Destructor stehen dann halt entsprechende Befehle, um eine Klasse abzuschließen.

    Bei Garbage Collectors komme ich zum Halbwissen, weil ich es nur so kenne, ob es auch anders funktioniert, musst du noch mal googeln. Carbage Collectors funktionieren eher automatisch bei Bedarf. Sprich, wenn der Speicher benötigt wird, dann wird er an dieser Stelle freigegeben. Wobei ich da jetzt auch nicht weiß, ob nur im RAM, oder ob hier auch der Cache gemeint ist. Also nur, weil etwas aus dem RAM entfernt wurde, muss es ja noch lange nicht aus dem Cache entfernt sein, was dann auch wieder zu schnellen Ladezeiten führt.

    Aber, wenn du da mehr wissen willst, dann schlage ich dir Bücher zu C++ vor. Da gibt es in der Regel immer mindestens ein Kapitel zur Speicherverwaltung.

    • Offizieller Beitrag

    Ich geb auch mal meine Gedanken dazu:

    Mit Openlevel lädst du ja ein ganzes Level. In diesem Level kannst du theoretisch enorm viele Assets plaziert haben weshalb die Ladezeit lange geht oder das Laden sogar abstürzt.

    Ich frag mich was passiert wenn man es übertreibt und in das Level verdammt viel Stuff reinpackt und dann versucht das ganze Level auf einmal zu laden.

    Vielleicht ist dass dein Problem ? Du versuchst zu viel auf einmal zu laden ?


    Open Level tut ein Level Laden und anzeigen. Vielleicht solltest du dir mal das Levelstreaming anschauen.

    Beim Levelstreaming, kannst du ein persistent Level laden. Das ist quasi das Weltall ohne Inhalt.

    In dieses Level lädst du dann zb das Menü. Während das Menü angezeigt wird, lädst du im Hintergrund bereits Level1. Sobald der Spieler auf Start klickt, wird das Level1 gestartet. (Sofern es fertig geladen ist)


    So kannst du bei einem Spiel mit 100 Level theoretisch alle Levels im Mainlevel anzeigen. Du lädst sie im Hintergrund in den Speicher, zeigst sie mit einem Bums an und schmeißt nicht gebrauchte Level wieder raus.


    1.Level Laden

    2.Level Anzeigen

    3.Level aus dem Speicher löschen


    Ich glaube Garbage Collectors funktioniert automatisch. Die Assets werden nach spätestens 60 Sekunden geprüft und fliegen aus dem Speicher. Wenn dein Speicher ausgeht, können sie auch früher geprüft und entfernt werden.


    Ich sehe den Flaschenhals beim Laden bzw Einblenden deines Levels. (Nicht bei der Optimierung durch die UE) Ich glaube bevor das Level geladen ist, geht da etwas schief.


    1. Dein Level ist zu groß bzw du versuchst zu viel auf einmal du laden und anzuzeigen.

    2.Du hast irgend ein Fehler in deinem Script. Ich frage was zb passieren würde wenn man das "Level laden" in eine Schleifen bauen würde. So nach dem Motto: Lade Level und wenn du fertig bist lade es nochmal. Dann würde dein Level in einer Schleife unendlich oft neu geladen werden. Hier gibt bestimmt noch andere Möglichkeiten sich solche Stolpersteine zu bauen.


    Woran es genau liegt ist mit den Informationen schwer zu sagen.

  • Der Ladebildschirm freezed, weil er auf dem Game Thread läuft und dieser für das Laden blockiert.

    Damit das nicht passiert, kann das Level auf einem extra Thread geladen werden.


    Genau das macht die Async Load Asset Node. Sie erstellt ein Thread, lädt das Asset und zerstört diesen auch wieder.


    Die Garbage collecting Node musst du nicht mal aufrufen, der läuft regelmässig 30-60 Sekunden oder sogar noch öfter. Du kannst in den Projektsettings auch einiges dazu konfigurieren. Ausserdem ist die Node geqeued, es passiert also nicht sofort. Ausserdem kann es sein, dass der Thread noch Referenzen auf das Level hält und deswegen ist garbage Collection noch nicht möglich. Der wird das aber schon noch cleanen. Deswegen ist das Laden auch noch so schnell.


    Ich habe es nie so gemacht, scheint mir aber eine elegante Lösung. Ich würde den Memory Usage mit den Profilingtools genau anschauen. Sollte aber eig. Kein Problem sein.


    Gruss

  • Erstmal vielen lieben dank für eure Hilfestellungen :)


    Auch danke an dich Phoenix-100. Du hast echt Licht ins du dunkle gebracht bei mir. Dann werde ich den Lösungsansatz mit der Async Load Asset Node weiter verdolfen.


    Interessant finde ich auch, dass diese Node anscheinend das geladene zeugs wieder automatisch entfernt. Meine Sorge war, dass bei falscher Nutzung davon der Cache irgendwann voll laufen könnte und das Spiel sozusagen unbrauchbar macht.


    Den Memory Usage mit Profilingtools werde ich mir mal ansehen. Überhaupt noch keine Erfahrung damit. Aber vielen Dank für den hilfreichen Tipp.



    Sleepy Einen so gravierenden Fehler kann ich definitiv bei mir ausschließen. Ich kann dir aus meiner Erfahrung sagen, dass es bei sehr sehr sehr großen levels nur den Anschein hat es wäre abgestürzt. Ich habe Arbeitsbesingt mal einen Level öffnen müssen mit ca. 2 Millionen assets. Ja es hing, aber im Hintergrund lädt sich das weiterhin dumm und dämlich, bis tatsächlich dieses Level geladen ist :) Wäre bei solch großen levels eine Lösung, diese aufzuteilen in mehrere kleine?

    Levelstreaming hatte ich auch schon als Idee für meinen Ladebildschirm nur muss man da alle levels in einen Level als sublevels packen richtig?

    • Offizieller Beitrag

    Wäre bei solch großen levels eine Lösung, diese aufzuteilen in mehrere kleine?

    Levelstreaming hatte ich auch schon als Idee für meinen Ladebildschirm nur muss man da alle levels in einen Level als sublevels packen richtig?

    Wenn man von Level redet denken die meisten ein Level1 dann Level2 usw.

    So funktioniert das Levelstreaming nicht.


    1.Du könntest zb alle Bäume in ein Sublevel packen.

    2.Du könntest alle Häuser in ein Sublevel packen

    3.Du könntest alle Felsen in ein Sublevel packen


    In das Mainlevel würdest du dann alle Sublevels laden so dass dort alles Sublevels zusammen kommen.


    oder


    Du lädst Levelteile. zb den Norden einer Stadt wenn man in die gegen den Südens kommt, wird der Süden des Levels in das Mainlevel geladen. Der Spieler bekommt hiervon der in der Regel nichts mit. So kannst du Sublevels wie Chunks nachladen.

  • In das Mainlevel würdest du dann alle Sublevels laden so dass dort alles Sublevels zusammen kommen.

    Das Problem was ich dann doch wieder habe ist, dass das Mainlevel dann doch Ewigkeiten brauch im z.B. im Editor geladen zu werden, da alle Sublevels auch direkt angezeigt werden. Wie würde ich denn dieses Problem umgehen?


    Du lädst Levelteile. zb den Norden einer Stadt wenn man in die gegen den Südens kommt, wird der Süden des Levels in das Mainlevel geladen. Der Spieler bekommt hiervon der in der Regel nichts mit. So kannst du Sublevels wie Chunks nachladen.

    Interessant, danke für den Hinweis

    • Offizieller Beitrag

    Wie würde ich denn dieses Problem umgehen?

    Umgehen geht nicht ^^ Du musst ja das Level laden das kann man nicht umgehen aber du kannst das Problem verstecken.


    1.Du kannst das ganze Level vorladen. Das ist ja in vielen Spielen so, wo man Anfang warten muss bis alles geladen ist und das Spiel dann startet. Du musst für dich entscheiden welche Ladezeit okay für dich ist.

    Keiner wartet 5 min bis das Spiel losgeht.


    2. In vielen Spielen wie zb Starfield wird die Ladezeit durch Videosequenzen kaschiert. Du landest auf einem Planeten, das Video wird eingeblendet wo zeigt wie dein Schiff landet. (Das ist ein Verstecktes Laden und Landen ^^) Wenn die Landezeit nicht ausreicht, kommt vermutlich ein Blackscreen mit nem Mausicon dass sich dreht und du müsstest warten bis alles geladen ist. (Verstecktes Laden)


    3.Ich kenne dein Spiel nicht aber eine Medhode ist es du startest das Spiel und startest direkt im Menü. Das Menü ist bereits ein Sublevel. Während du dich im Menü befindest, werden im Hintergrund bereits alle Sublevels geladen. Klickst du im Menü auf Spiel starten, wird im Grunde das Menü ausgeblendet und aus dem Speicher geworfen und alle Sublevels werden eingeblendet. Die dann hoffentlich schon geladen sind. Ansonsten siehe Punkt 1. (Verstecken)


    4.Wenn du viele Sublevels hast (Die menge ist nicht das Problem) dann solltest du dir überlegen die Sublevel zu verkleinern.

    (Achtung Wortspiel) Statt eine ganze Stadt zu laden, lieber nur ein Stadtteil. Damit ist die Ladezeit schneller.

    Die Restlichen Stadtteile lädst du dann in weiteren Sublevels und nachdem du gespawnt bist.

    Über triggerboxen könntest du bestimmen wann welches Sublevel geladen werden soll oder aus dem Speicher fliegen soll.

    Das Laden, aus dem Speicherwerfen, und das anzeigen würde dann im Hintergrund passieren.


    Das Camera Occlusion Culling sollte dir auch die Karten spielen. Das COC blendet aus was nicht vom Player gesehen wird.

    Heißt: Blendest du ein Sublevel ein, dass außerhalb des Sichtfeldes des players liegt, ist das Sublevel trotzdem nicht da (Ist Unsichtbar)


    Vorrausetzung dafür ist natürlich deine Stadt ist nicht ein riesiges Mesh. Dann würde das COC nicht funktionieren. Da du die Stadt ja immer komplett siehst und niemals gar nicht sehen würdest. Ich hoffe du verstehst wie ich das meine.


    ich glaube es wichtig, dass du die Technik und Logik verstehst. Dann kannst du selber beurteilen wie du alles einstellen musst.


    Eine Idee noch:

    LODs spielen dabei vielleicht auch eine Rolle. zb sollte die ganze Stadt beim Einblenden nicht in der hohen LOD angezeigt werden.


    Daher: Wenn eine Szene geladen und angezeigt wird, sollte Sie nicht in Highpoly gespawnt werden. Sondern lieber in der Niedrigsten LOD Stufe und die sich nach dem Laden auf die Distanz einstellt.

    Du könntest hier beim Level Start einen kurzen Blackscreen einbauen oder einen blure um den LOD Switch zu verstecken.

    Auch hier hoffe ich du verstehst wie ich meine sonst frag nach.