Reagieren, wenn der SceneManager ein Level nicht lädt

Wenn man in Unity versucht, eine nicht-existente Szene über den SceneManager zu laden, dann erscheint zwar eine Fehler-Meldung im Log-File bzw. der Editor-Konsole, aber es gibt scheinbar keinen direkten weg, um per Code darauf zu reagieren. Das Abfangen von Exceptions, sofern solche überhaupt auftauchen, wirkt in Unity generell etwas unzuverlässig, da das Log-System bereits viel abfängt und verarbeitet. Unklar erscheint mir zudem, wieso die Methode SceneManager.LoadScene nicht einfach einen Rückgabewert liefert, der über den Erfolg der Methode Auskunft gibt. Möglicherweise hängt es damit zusammen, dass Ladevorgänge auch asynchron ablaufen können und daher Fehler unter Umständen nicht sofort ermittelbar sind.

Durch Systemüberwachung Rückschlüsse auf den SceneManager ziehen

Nun ist es zwar so, dass der Level-Ladefehler meistens beim Testen im Editor auffallen dürfte und schlicht durch Inklusion der fehlenden Szenen-Assets zu beheben ist. Dennoch hat mich die Frage beschäftigt, wie man auf den Fehler reagieren kann. Die gefundene Lösung besteht darin, dass man das Log-System während des Ladevorgangs überwacht. Bei jeglichem Protokollierungsvorgang (also Debug.Log...) werden hier eingeschriebene Funktionen benachrichtigt, so dass man kurzum prüfen kann, ob während des Ladens ein Fehler auftrat. Wenn dem so ist, ist in Schlussfolgerung das Fehlschlagen des Ladevorgangs zu vermuten.

Folgender Abschnitt skizziert das Prinzip:

...
bool errors=false;
...
Application.logMessageReceivedThreaded += Application_logMessageReceived;
SceneManager.LoadScene("nonexisting"); 
Application.logMessageReceivedThreaded -= Application_logMessageReceived;
if (errors)
{
   ... scene could not be loaded
}
...

private void Application_logMessageReceived(string condition, string stackTrace, LogType type)
{
   if (type==LogType.Error) errors=true;
}

Schnelle und einfache Lösung mit WatchForError-Klasse

Ich habe dem GameDev-Profi-Toolkit eine Klasse namens WatchForError hinzugefügt, die nach dem oben beschriebenen Prinzip Log-Fehler zählt. Sie lässt sich für fehlerhaftes Szenen-Laden als auch ähnliche Situationen anwenden.

using GameDevProfi.Utils; //https://github.com/renebuehling/GDP-Toolkit
...
WatchForError watch = WatchForError.startNew();
SceneManager.LoadScene("NonExistingLevel"); 
if (watch.stop().errors>0) 
   Debug.Log("Scene could not be loaded.");

Eine Exception werfen, wenn die Szene fehlt

Möglicherweise willst Du bei Auftreten unterschiedlichster Umstände oder Fehler in die selbe Fehlerbehandlung springen. Dann eignet sich ein Try-Catch-Block, der sich mit WatchForError ebenfalls bedienen lässt:

try
{
    WatchForError watch = WatchForError.startNew();
    SceneManager.LoadScene("doesnotexists");
    if (watch.stop().errors>0) throw new Exception("Scene not loadable.");
    //... do things if scene loading was ok ...
}
catch (System.Exception e)
{
    Debug.Log("Scene not loadable! Return to levelmap.");
    //... do something when any error occurred above ...
}

 

Dr. René Bühling

Hi, mein Name ist René und ich möchte Dir dabei helfen, deinen Traum vom eigenen Computerspiel Wirklichkeit werden zu lassen. Mein erstes kommerziell veröffentlichtes Spiel habe ich Mitte der 1990er Jahre als Hobby-Projekt mit einem Basic-Dialekt unter Windows entwickelt. Seither verfolge ich das Thema Spieleentwicklung in Hobby, Studium und Beruf. Ich habe über 20 Jahre Erfahrung in allen Phasen des Entwicklungsprozesses, die ich gerne mit dir teilen möchte.