Reibungsloser Ladebildschirm zwischen den Szenen

14

Ich habe einen Ladebildschirm erstellt, um eine Ladeanimation anzuzeigen, wenn die nächste Szene geladen wird. Ich lade die nächste Szene asynchron mit:

yield return SceneManager.LoadSceneAsync(scene,LoadSceneMode.Additive);

Und auch gesetzt Application.backgroundLoadingPriority = ThreadPriority.Low;, aber das Verhalten ist immer noch das gleiche wie bei einer normalen Level-Last.

Vermisse ich etwas?

Erwartetes Verhalten:

  • Ebene verlassen und ausblenden.
  • Der Ladebildschirm wird angezeigt.
  • Sobald der Ladevorgang abgeschlossen ist, wird der Ladebildschirm ausgeblendet.
  • Nächste Szene einblenden.

Was ist los:

  • Ebene verlassen und ausblenden.
  • Der Ladebildschirm wird eingefroren angezeigt
  • Plötzlich taucht eine neue Szene auf.

Sobald das Laden beginnt, friert das Spiel einfach ein, wie bei einem normalen Laden der Szene.

Ich habe gelesen , dass Sie festgelegt haben allowSceneActivation = false, so dass Sie den Ladebildschirm aus verblassen, und setze es dann zu trueEinheit Finish Laden zu lassen, aber das completelly friert mein Spiel, wie der Asynchron - Betrieb nie fertig geladen.

Löwe
quelle
Ich hatte dieses Problem und habe hier nichts gefunden. Nachdem ich gegoogelt hatte, fand ich heraus, was dieses Problem verursachte. Ich beschloss, es hier zu posten, damit andere die Antwort leicht finden konnten. Bitte lassen Sie mich wissen, ob Sie meine Antwort / Frage verbessern möchten. Vielen Dank!
Leo

Antworten:

18

Wenn Sie eine Szene mit laden, SceneManager.LoadSceneAsync()passieren tatsächlich zwei Dinge:

  • Die Spielobjekte der Szene werden in den Speicher geladen.
  • Dann ist die gesamte Szene aktiviert. Alle Awake () - und Start () - Rückrufe werden für die Objekte in der Szene aufgerufen.

Der zweite Schritt, der die Szene aktiviert, friert tatsächlich die Einheit ein, da die Einheit alle diese Initialisierungsrückrufe in Ihren Skripten in einem einzigen Zyklus ausführt.

Mit der Einstellung SceneManager.LoadSceneAsync().allowSceneActivationto falsewird der asynchrone Vorgang so ausgeführt, dass nur der erste Schritt des Prozesses abgeschlossen wird, und es wird gewartet, bis trueder zweite Teil des Prozesses gestartet wird.

Aber wenn Sie setzen allowSceneActivationauf falseund Ertrag auf dem Rückruf wie diese, werden Sie Ihr Spiel für gut einfrieren:

AsyncOperation AO = SceneManager.LoadSceneAsync(scene,LoadSceneMode.Additive); 
AO.allowSceneActivation = false;
yield return AO;

//Fade the loading screen out here

AO.allowSceneActivation = true;

Warum? Da Sie den Async-Vorgang anweisen, nicht mit dem zweiten Schritt des Szenenladens fortzufahren, wird der Vorgang niemals abgeschlossen.

Wenn Sie wissen möchten, wann der erste Teil der Operation fertig ist, müssen Sie sich darauf verlassen, um mit dem zweiten fortzufahren AsyncOperation.progress. Dieser Wert stoppt 0.9fsofort, wenn er auf die allowSceneActivationFlagge wartet .

Es sollte ungefähr so ​​aussehen:

AsyncOperation AO = SceneManager.LoadSceneAsync(scene,LoadSceneMode.Additive); 
AO.allowSceneActivation = false;
while(AO.progress < 0.9f)
{
    yield return null
}

//Fade the loading screen out here

AO.allowSceneActivation = true;

Wenn Sie möchten, dass die Szenenaktivierung Ihr Spiel nicht einfriert, sollten Sie Ihre Awake- und Start-Rückrufe auf ein Minimum beschränken und Ihre Skripte in einer Coroutine über mehrere Zyklen hinweg initialisieren.

Löwe
quelle
0

Ich hatte genau das gleiche Problem in Unity 5.6 und hatte bereits versucht, die Ertragsaussagen einzufügen. Es war LoadSceneAsync selbst, das den Hauptthread von Unity blockierte und verhinderte, dass die aktuelle Szene den Ladevorgang korrekt darstellte.

Soweit ich das beurteilen kann, scheint es ein Fehler in Unity zu sein. Als meine Szene weniger komplex war, funktionierte mein Code hervorragend und der Übergang verlief reibungslos. Sobald es größer wurde, blockierte Unity den Thread für ungefähr 6 Sekunden, während das Spiel als "nicht reagierend" abspielte, obwohl die Operation angeblich "asynchron" war.

Die Art und Weise, wie ich das Problem löste, bestand darin, meine Beleuchtung zu betrachten. In der Vergangenheit gab es massive Fehler bei der Beleuchtung und dieser Funktion. Also ging ich meine Objekte durch und stellte fest, dass ich ein Objekt im Rampenlicht hatte (obwohl es deaktiviert war ...)

Ich habe das Rampenlicht gelöscht und Hurra! Szene wird asynchron geladen! Keine Verriegelung!

Herr des Stapels
quelle
Vor der Bearbeitung bot dieser Beitrag keine Lösung für das Problem. Es ist in Ordnung, dass Sie eine Fehlerbehebung hinzugefügt haben. Wenn Sie jedoch in Zukunft "Ich habe dieses Problem auch" sagen möchten, sollten Sie für diesen Zweck keine Antworten verwenden. Wenn Sie ein wenig Wiederholung verdienen, können Sie vorhandene Beiträge kommentieren oder Fragen mit einem Kopfgeld belohnen, um neue Antworten zu erhalten.
DMGregory