Jump to content
Unity Insider Forum
Bastiuscha

Lange Ladezeit trotz Resources.Load

Recommended Posts

Hallo Leute,

ich arbeite zur Zeit an einem Mobilegame und mich erschreckt die Ladezeit, bei langsamen Geräten. Nach der Introscene, wird die Gamescene geladen. Aus der Besteht das ganze Spiel und es muss wären dessen nicht mehr nachladen. Diese Scene ist im Prinzip fast leer und es werden immer einzelne Raumsegmente, per Resources.Load nachgeladen. Das habe ich so gewählt, weil ich dachte, dass es dann gerade nicht, vorgeladen werden muss. Ich glaube aber, dass das wohl doch der Fall sein wird. Das ist auch schon meine Frage...ist das so?

Nur mal in Zahlen: Auf meinem PC (i7, ssd), läd die Scene in 2-3 sek. Auf meinem IPhone 6 läd sie 6sek. Aber auf nem Samsung Galaxy A5 (ziemlich schwaches Smartphone) läd es locker 50 Sekunden! :o Für eine eigentlich fast leere Scene, ganz schön lange. Ich merke auch, je mehr Prefabs ich erstelle, desto länger dauerts. Also beantworte ich mir eigentlich die Frage damit schon selber. Hat Jemand Erfahrung damit? Was könnte ich unternehmen? Ich möchte das Spiel ungern in mehrere Scenen unterteilen. Muss doch gehen irgendwie....

 

Share this post


Link to post
Share on other sites

Erfahrung habe ich damit auch nicht, du solltest erst einmal herausfinden, wie lange eine leere Szene läd. Wenn eine leere Szene schon 50 Sekunden läd, dann ist es völlig egal in wie viele Szenen du dein Game aufteilst. Dann macht Unity eine Art Aufbereitung mit den Assets des Spiels bevor sie geladen werden oder es Initialisiert die Gameengine und das dauert so lange. Das Laden der einzelnen Szenen kommt dann noch einmal obendrauf.

Share this post


Link to post
Share on other sites

Wie gesagt, je mehr Prefabs ich erstelle, desto länger läd es. Demnach läd eine "wirklich" leere Scene in 1-3Sek. auf dem schwachen Gerät.

Share this post


Link to post
Share on other sites

Hallo zusammen, mein erster Post hier, obwohl ich schon länger registriert bin ;)

Das kann durchaus an der Anzahl Assets im Resources-Ordner liegen. Denn alle Ressourcen werden beim Kompilieren in eine einzige Datei geschrieben. Diese Datei enthält auch einen Index. Der Index dient dazu die Resources-Pfade aufzulösen, so dass Unity weiss, wo sich das Objekt in der Datei befindet. Das Problem ist jedoch, dass der Index mit zunehmender Anzahl an Assets nicht linear wächst, sondern immer grösser wird. Dies betrifft leider auch die Ladezeiten des Index. Die Assets selber werden beim Start nicht geladen, der Index jedoch schon.

Ich weiss jetzt nicht wie viele Assets du im Resources-Ordner hast, aber Unity meint zumindest dass es bei 10'000 Assets schon mal ein paar Sekunden dauern könne bei älteren Mobilgeräten.

Generell rät Unity in den meisten Fällen davon ab, das Resources-System überhaupt noch zu verwenden ("Best Practices for the Resources System: Dont' use it."). Neuerdings würde man das wohl eher über AssetBundles lösen, die z.B. von einem Webserver oder direkt vom Dateisystem nachgeladen werden können. Allerdings kenne ich mich damit auch noch nicht so gut aus.

Quelle: https://unity3d.com/de/learn/tutorials/topics/best-practices/resources-folder

PS: Wenn ich das im Artikel richtig verstanden habe, wäre eine Möglichkeit ein Script zu erstellen, welches eine Liste/Array von Prefabs referenziert. Dann erstellst du ein Empty-Objekt mit diesem Script drauf, machst davon ein Prefab und fügst nur dieses Prefab in den Resources-Ordner ein, während alle anderen Prefabs ausserhalb vom Resources-Ordner sind. Dann kann man mit Resources.Load() dieses Script-Objekt mit allen referenzierten Prefabs laden. Weil die Prefabs davon referenziert werden, werden automatisch auch die Prefabs mitgeladen. Da der Resources-Ordner dann sehr klein ist, sollte dies das Laden der - fast leeren - Szene kaum beeinträchtigen.

Share this post


Link to post
Share on other sites
Am 3/27/2018 um 10:49 schrieb Bastiuscha:

Wie gesagt, je mehr Prefabs ich erstelle, desto länger läd es. Demnach läd eine "wirklich" leere Scene in 1-3Sek. auf dem schwachen Gerät.

Ich erinnere mich daran mal gelesen zu haben, dass gerade viel und vor allem große Prefabs Ladezeiten ziemlich erhöhren können. 

Share this post


Link to post
Share on other sites

Ahaaaa! Sehr aufschlussreich... also habe ich genau das falsche gemacht. Hatte anfangs die Prefabs einfach ohne Resources.Load instanziiert und dann umgestellt, um genau das zu vermeiden...das ging wohl in die Hose. Dann werde ich mich wohl mal mit Asset Bundles beschäftigen müssen. Hoffentlich wird das nicht zu großer Aufriss... bin schon ziemlich weit im Spiel.

Share this post


Link to post
Share on other sites

So...nun habe ich mich da reingefressen und zwei Tage lang damit beschäftigt, um das Assetbundle Thema (war nicht leicht) hinzubekommen.  Und was habe ich erreicht? Nichts! xD läd immernoch genau so langsam. Es sind übrigens auch nur so ca. 300 Prefabs. Hätte ich mal erwähnen können. Und aus Verzweiflung habe ich jetzt mal viele Sachen durchgetestet und rausgefunden.

Also erstmal hatte ich einen Denkfehler...der Resources Ordner, SOLLTE ja schon bei der ersten Scene ausgelesen werden. Oder bzw. das Indexfile. Weil das ja in der Ordnerstruktur statt findet und nicht in der Scene selber (oder nicht?). Meine "Ladehemmung" kommt aber erst in der zweiten Scene, der Hauptscene. Die Erste ist quasi nur das Logo. Wenn ich von der Hauptscene zur Charakterauswahlscene und wieder zurück gehe, habe ich wieder eine lange Ladezeit. Also muss es ja wohl doch an der Scene liegen.

Nach langem Rumgespiele, konnte ich es jetzt ein wenig eingrenzen und nun würd ich wieder gerne eure Meinung dazu wissen. Meine Hauptscene besteht wirklich nur aus einem Canvas, ner Camera und grob, nur einen Gameobject, den "Gamemanager". Dieser ist aber mit zwei dicken Scripten behangen, dem Hauptspielscript und nem Gui Script. Wenn ich den lösche und das Spiel testweise auf nem langsamen Smartphone starte, habe ich eine sehr kurze Ladezeit. Also muss es dieses Gameobject sein. Das Ding hat gut 150 public Variablenfelder. Ist das nicht gut, für die Ladezeit? Der Profiler sagt mir ja leider nicht, was während des Ladens, so lange dauert. Zumal es am PC auch nur 3Sek. läd. Aber irgendwas in der Richtung muss es sein, da es mit fortlaufender Entwicklung immer länger wurde.

 

 

Share this post


Link to post
Share on other sites

Hm, schade.. Ich denke Asset Bundles machen vor allem Sinn, wenn man sie asynchron laden kann, während man vorher noch etwas anderes anzeigt.

Alle in einer Scene verlinkten Prefabs werden beim Laden der Scene halt auch geladen. Heisst, wenn die 150 public Felder auf Prefabs verweisen, werden die alle geladen. Da könnte man nur die wichtigsten direkt verlinken und die restlichen eben erst wenn sie wirklich benötigt werden laden oder schon von Anfang an laden, jedoch asynchron.

Share this post


Link to post
Share on other sites

Es kann gut sein, daß wenn diese Variablen auf Asset / Prefabs oder Texturen verweisen, daß Unity diese "Variablen" initialisieren muss. Beispielsweise kann ich mir gut vorstellen, daß wenn eine Variable auf eine Textur verweist, daß Unity Speicherplatz für diese Textur bei Erstellen der Instanz von "Gamemanager" allokieren muss. Wenn diese Instanz nun sehr sehr viele solche Variablen hat, dann kann das Erzeugen der Instanz von Gamemanager (passiert beim Laden der Szene) schon einige Zeit dauern. Wenn das die Ursache sein sollte, dann könnte man Variablen die Referenzen auf Assets haben ggf. erst erzeugen wenn man sie braucht.
https://docs.unity3d.com/ScriptReference/AssetDatabase.LoadAssetAtPath.html

Ansonsten was treibt dann dieser Gamemanager ?

Share this post


Link to post
Share on other sites

Eigentlich verweisen die zu 70% nur auf Gui Elemente, nur ca 15 Prefabs und der Rest sogar nur Zahlenwerte und Stringfelder. Eigentlich nix Wildes.... kann ja mal durch Probieren versuchen rauzufinden, ob da etwas raus zu holen ist, wenn ich das Zeuch direkt im Code ranhole. 

Was treibt dieser Gamemanager:

Das ist ein kleines Handygame, was nur eine einzige Scene hat. Das GO namens GameManager, hat die Hauptaufgabe, das Spiel zu steuern. Es beinhaltet im Wesentlichen das "GameManager" Script und ein "Gui" Script. Welches* von Beiden das Problem ist, weiß ich NOCH nicht. Werd ich noch probieren. Das Gui Script, ist ganz einfach das komplette Menu und alles was in der Scene an Gui zu sehen ist. Das GameManager Script, steuert im Prinzip das Spiel. Dort werden sämtliche Prefabs des Spieles geladen. Mein Spiel ist auch komplett Prefab basierend. Klingt aber schlimmer als es ist...die App ist nur 83mb gross. :) 

 

Diese 15 Prefabs sind auch Leichtgewichte. Das sind nur Audiosources mit nem Audiofile und nen MiniScript drin.

 

Share this post


Link to post
Share on other sites

Resources und AssetBundles bringen dir nichts, wenn du direkte Referenzen aus der Scene auf deine Prefabs hast. Dann werden deine Daten trotzdem beim Scene Load geladen und du hast evtl sogar einen größeren Build, weil deine Assets mehrfach gepackaged werden.

Genrell sind AssetBundles dem Resources-System vorzuziehen, da sie viel flexibler (dementsprechend natürlich auch etwas komplexer) sind.

Wenn du die Ladezeit deiner Scene (und nur der Scene) gering halten möchtest, solltest du keine Asset Referenzen über Scripte haben und alles über AssetBundle.Load(Async) regeln. Dazu sei aber gesagt, dass man dadurch nicht "schneller" lädt, sondern eigentlich sogar (etwas) langsamer. Wenn deine Assets direkt aus der Scene referenziert werden, speichert Unity sie beim Build so ab, dass alle Assets auf einmal linear von der Disk geladen werden können. Dafür wird halt alles in SceneManager.LoadSceneAsync gemacht und man hat keine Kontrolle darüber. Bei Resources/AssetBundles dauert SceneManager.LoadSceneAsync, aber die Resources/AssetBundle.Load Aufrufe können nicht mehr linear von der Disk lesen.

Im Endeffekt kommt es ganz auf die Situation an und was man möchte.

Share this post


Link to post
Share on other sites

Sehe ich auch so wie @Silveryard
Sollte es wirklich an den Referenzen in der Szene liegen (alles sieht danach aus), dann würde ich eine leere Szene als "Willkommensbildschirm" erstellen (ggf. mit Lade-UI) und dann die Startszene über LoadSceneAsync im Hintergrund laden und Anzeigen, wenn die Szene fertig geladen ist. Man kann mittlerweile eine Szene im Hintergrund laden und sie sogar "suspenden", d.h. man kann selbst festladen, ob sie nach dem asynchronen Ladevorgang angezeigt werden soll oder nicht.
Ob ich nun AssetBundles oder komplette Szenen im Hintergrund lade bleibt dabei Geschmackssache, ich würde AssetBundles aber eher für App-Erweiterungen (erweiterter Content) verwenden und nicht für die Kernanwendung.

Share this post


Link to post
Share on other sites

Finde es aber irgendwie schon ganz schön schwach, dass ich von dem "Bisschen" schon so extrem lahme Ladezeiten bekomme. Es ist nur schwer zu meckern, wenns aufm PC 3Sek. sind.;D SO viel Referenzen sind es ja nun auch nicht. Habe leider noch nicht wieder geschaut, was genau, der Übeltäter ist. Geht Mittwoch wieder los und dann werd ich sehen. An meinen Resources.Load System liegts jedenfalls nicht. Das hatte ich ja zwischenzeitlich komplett aus. Also auch keine Referenzen auf die Datein. Ich forsche nach und sage Euch dann, wer da genau auf der Bremse steht. 

 

Share this post


Link to post
Share on other sites

Leute! Update...... und jetzt wirds natürlich peinlich. Wie jedes mal, wenn ich etwas nicht hin bekomme.

Ich hatte mein Spiel vor 2 Jahren begonnen und es ist natürlich von der Appgröße her, stetig gewachsen. Irgendwann hab ich gemerkt, dass die Ladezeit langsam zu groß wurde. Da mein Spiel (wie gesagt), nur eine Scene besitzt. Darauf hin, hatte ich das Resources.Load System eingebaut. Das kannte ich vorher nicht und musste das System natürlich erstmal lernen. Hat mir nicht geschadet....sag ich mal. Danach war es deutlich schneller. Jetzt habe ich über Monate daran gebastelt und viele Sachen eingebaut und geändert. Irgendwann stellte ich fest, dass die Ladezeit auf meinem Ipad Air 2 schon ein paar Sekunden gedauert hat. Hat mich zwar gewundert, dass eine fast leere Scene so lange läd. ABER erst als ich das Spiel auf einen Galaxy S3 getestet habe (Ladezeit 50Sek.) war ich natürlich baff. Damit kam ich dann zu Euch. Das Resultat war, dass ich mich eine ganze Woche in das Thema Asset Bundle eingearbeitet hatte. Sogar schon umgesetzt und im Projekt erfolgreich getestet hatte. Das war für mich, ehrlich gesagt, ein Brocken...aber ich hatte es geschafft. Allerdings mit zero Erfolg! Daran lag es wohl nicht..... dann hatte ich mich mit dem Async Laden beschäftigt, um das Problem zu umschiffen...ja sogar schon Teilweise eingebaut. Aber an meinen GameManager, mit den 100 public Varriablen, hatte ich mich am Ende geweigert, was zu ändern. "Das kann einfach nicht das Problem sein", war ich mir sicher. 

So....und gestern hab ich das Problem gefunden. Und ich sage Euch....dumm..... Ich habe ein 19 Musiktitel Album im Spiel...und habe es in den Speicher geladen! Das waren 150mb (ungepackt) Musik. Das reicht, um alte Handy's eine Minute arbeiten zu lassen. Oh Man!!! Wie dumm. Aber bin trotzdem froh. Jetzt habe ich alles so gelassen wie es ist. Nur mit dem Resources.Load System. Und meine ganze Programmierung auch gelassen wie sie ist..... Auf dem alten Galaxy S3 eine Ladezeit von 1Sek!  :D:D:D 

 

Share this post


Link to post
Share on other sites

Ja das ist natürlich ein Dingen.
Gerade die Musik muss man eigentlich gar nicht direkt einladen. Du kannst ja bei den Importeinstellungen unter Load Type einfach auf Streaming stellen. 

Share this post


Link to post
Share on other sites

Das ist mir absolut bewusst und Ramspeicher frisst es auch noch sinnlos. Ich frag mich aber nur, welcher Depp das so eingestellt hatte? :D

Share this post


Link to post
Share on other sites

Sorry...musste hier an der Stelle was löschen, hatte zu nem völlig falschen Thema gepostet. Anscheinend keinen außer mir aufgefallen. :)

Share this post


Link to post
Share on other sites

Und jetzt weiß ich auch weshalb. Es hat sich allein umgestellt, als ich von iOS zu Android gewechselt habe. Ist nämlich heute wieder passiert

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×