Jump to content
Unity Insider Forum

Frage zum laden einer Scene


w0rks

Recommended Posts

Hi,

In vielen Spielen ist mir aufgefallen das wenn diese geladen werden und das spiel beginnen lassen, dass diese manchmal nicht komplett Fertig geladen sind und ab & an mall danach Objekte erst in Kürze dargestellt werden & dann einfach aufploppen. 

Das viel mir in manch "Unreal Engine" Spielen auf.

Jetzt meine Frage:

Geht das auch in Unity ? 

Weil Unity ist ja so eingestellt das die Scene erst startet sobald alle Objekte wirklich schon fertig dargestellt werden können.

Geht das ? und . . hat das einen bestimmten Namen ?

 

Würde mich freuen etwas darüber zu erfahren!

w0rks

Link zu diesem Kommentar
Auf anderen Seiten teilen

Interessante Frage, ich kenne da nur folgende Varianten in Unity:
Man läd die aktuelle Szene und kann aber die nachfolgende Szene bereits im Hintergrund vorladen (asynchrones Laden). Ist die nachfolgende Szene im Hintergrund fertig geladen, dann kann die Szene dargestellt werden. Diese Technik funktioniert auch mit "additivem Laden", also man läd Chunks (so nenne ich es mal) eines Level im Hintergrund ständig nach und wenn diese fertig geladen sind, dann werden diese Chunks im aktuellen Level dargestellt (dies kann zum Aufpoppen von Objekten führen in dem Fall, wenn ein Chunk zu lange zum Laden gebraucht hat). Dies kann man zum Beispiel bei einem Endless-World-Runner verwenden (das geht z.B. auch mit Unity-Terrains).

Eine andere Variante ist die Spieldaten zur Laufzeit über AssetBundles nachzuladen. Hier werden dann die Objekte der Szene nachträglich dynamisch erzeugt oder man läd eine komplette Szenen-Datei über ein Assetbundle nach (DLC) und läd diese Szene dann wieder über die obere Methode.

Letzten Endes macht das Laden eines Levels ja nichts anderes als Daten aus dem Asset-Folder in den Speicher zu laden, diese mit "Property-Daten" zu den GOs aus der gespeicherten Szene zu vermischen und dann diese GOs in der Engine zu instanziieren (und darzustellen). All diese Dinge kann man auch per Skripting nachbauen (und könnte theoretisch mit einem leeren Level starten und müsste nie wieder ein anderes Level laden):
Option a) - Laden neuer Assets zur Laufzeit über das Netzwerk auf die lokale Platte (https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequest.html)
Option a) - asynchrones Laden dieser Assets in den Speicher (https://docs.unity3d.com/ScriptReference/AssetBundle.html)
Option b) - Laden von Assets über Resources.Load()
- Das Bestücken dieser Assets mit Instanzdaten (z.b. über Scriptable Objects) oder über selbst geschriebene "Propertyklassen" die in der Szene abgelegt (als Templates) wurden und nur dafür da sind, um neue Instanzen der Szene mit Propertydaten zu versorgen
- das Erzeugen von Instanzen zur Laufzeit über die zuvor geladenen Assets und Properties (https://docs.unity3d.com/ScriptReference/Object.Instantiate.html)

Nachteil dieser Methode ist allerdings, man braucht entweder eine gute Internetverbindung oder man muss seine Game-Assets in ein Verzeichnis mit dem Namen "Resources" packen und umgeht hiermit aber auch das komplette Level-Management von Unity. Daher wird dies meist nur in Kombination mit einem "normalen Build" verwendet. Dabei gibt es gibt quasi ein Base-Game das man herunterladen kann (und welches die Assets mitbringt), aber man kann zusätzlich später andere Teile des Games als DLCs nachladen.

Also als Beispiel zu deiner Frage, wenn das Spiel beispielsweise noch am Nachladen eines Asset-Bundles ist und damit die Engine die Instanzen dieses Assets noch nicht darstellen kann, dann würde man in der Szene diese Objekte noch nicht instanziieren (oder nur Platzhalter anzeigen). Sobald das Asset-Bundle jedoch fertig geladen wurde, können die zugehörigen Objekte der Szene per Code instanziiert werden (und dabei können wieder GOs aus dem Nichts aufpoppen).

Link zu diesem Kommentar
Auf anderen Seiten teilen

Man macht das ja aus zwei Gründen:

  1. Weniger auf einmal zu rendern, wenn's eh zu weit weg ist.
  2. Weniger auf einmal zu laden, wenn man Teile der Welt laden kann, während das Spiel schon läuft.

Für diese beiden Ziele gibt es unterschiedliche Techniken.

Für 1. ist LOD (Level of Detail) sinnvoll.Dafür kann man in Unity z.B. die LODGroup-Komponente benutzen. Da wird der Abstand zur Kamera angeschaut und dann in Abhängigkeit davon das Modell mit Versionen immer niedrigerer Qualität ausgetauscht. Im letzten Level wird das Objekt einfach komplett ausgeblendet.

Für 2. brauchst du Streaming, was aber 1. mitbringen kann. Da hast du eine Welt und lädst dessen Teile nur dann, wenn Spielfigur oder Kamera nah genug dran kommen. Erste Anlaufstelle ist da SceneManagement.SceneManager.LoadSceneAsync (Async, damit das Spiel während der Ladezeit der Szene nicht einfriert), mit SceneManagement.LoadSceneMode.Additive als Parameter, damit vorhandene Szenen nicht wieder entladen werden. SceneManagement.SceneManager.UnloadSceneAsync benutzt du dann, um die Teile absichtlich wieder zu entladen. Streaming ist nicht ganz simpel und muss richtig gemacht werden. Eine langsamere Maschine verhält sich anders als eine schnelle. Vielleicht lädt das nächste Weltsegment schnell genug, wenn das Spiel auf einer SSD liegt, aber von einer HDD wird nicht schnell genug geladen. Ich erinnere mich noch, wie man mit dem Jet in GTA: San Andreas schnell genug fliegen konnte, dass die Welt nicht schnell genug nachgeladen hat. Die Kollision war vom Streaming ausgenommen, sodass man dann gegen unsichtbare Hochhäuser geflogen ist. Vermutlich besser, als damit unter die Welt fliegen zu können. Kann auch sein, dass da Modding im Spiel war, um den Jet so schnell zu machen :)

Das sing jedenfalls die beiden Dinge, die du dir anschauen kannst.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich habe gerade so ein System entwickelt und es "LoadBalancing" genannt. Dabei Lade ich alle Objekte aus einer XML Datei, aber ich Instanziere sie nicht direkt, sondern packe sie in eine Liste als eigene klasse "VirtualGameObject". 

Danach läuft eine Coroutine endlos, die nahe "virtuelle" Objekte Instanziert und weiter entfernte Destroy't und wieder als "VirtualGameObject" in die List packt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 19 Minuten schrieb Thariel:

Ich habe gerade so ein System entwickelt und es "LoadBalancing" genannt. Dabei Lade ich alle Objekte aus einer XML Datei, aber ich Instanziere sie nicht direkt, sondern packe sie in eine Liste als eigene klasse "VirtualGameObject". 

Danach läuft eine Coroutine endlos, die nahe "virtuelle" Objekte Instanziert und weiter entfernte Destroy't und wieder als "VirtualGameObject" in die List packt.

Das hört sich extrem interessant an !

Link zu diesem Kommentar
Auf anderen Seiten teilen

Am besten wie gesagt in dem du das große Level in mehrere kleine Level (Chunks) zerlegst und beim Start des Games nur der Chunk (oder mehrere Chunks) geladen wird, den der Spieler aktuell betreten hat  bzw. sehen kann. Die anderen Chunks (bzw. besser die den Spieler umgebenden Chunks) können derweil im Hintergrund bereits asynchron vorgeladen werden (LoadSceneAsync), aber der Spieler kann mit dem Spiel bereits starten.
Wenn der Spieler sich dann im Spiel bewegt, kann dies dazu führen, dass weitere Chunks nachgeladen werden müssen oder Chunks die jetzt weiter entfernt sind vom Spieler auch wieder aus dem Speicher entfernt werden (UnloadSceneAsync).

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 7 Minuten schrieb w0rks:

Aber an sich lässt sich mit Unity nichts machen ?

Ja, diese Technik wird im allegemeinen unter dem Begriff "Level Streaming"  oder "Scene Streaming" zusammengefasst. Man kann dann noch einmal unterscheiden, ob man ein Unity-Terrain streamen möchte oder nicht, dabei müsste man dann die Unity-Terrain-Chunks mit den Level-Chunks sinnvoll verbinden.

Hier ein Artikel wo es ums Unity-Terrain Streaming geht, aber man findet auch diverse andere Level Streaming Artikel oder auch bereits fertige Assets im Store:
https://gamedevacademy.org/how-to-handle-huge-worlds-in-unity-part-1-deactivating-distant-regions-to-improve-performance/

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...