Since Unity 5.5 SceneManager.UnloadScene is marked obsolete and UnloadSceneAsync should be used instead.
I noticed, however, that when using this, more or less randomly my coroutines throw errors for any component, monobehaviour or gameobject they may be referencing.
Obviously objects are being deleted in a more or less random fashion, while all coroutines happily continue running and then complain when objects (even their own transform at times!) go missing.
I don’t think many people are actually unloading scenes. But nonetheless, did anyone encounter this? Is there an easier way than to add checks to all coroutines after every yield statement if all references are still valid (or we’re not in a loading process)?
Here’s what my loading looks like:
// Wait until loading screen is completely visible
while (!loadingScreen.Ready) yield return null;
// Unload active scenes
foreach (var scene in scenesToUnload)
{
SceneManager.UnloadSceneAsync(scene.name);
}
GC.Collect();
// Finish loading animation
yield return null;
yield return null;
// Load new scenes
yield return StartCoroutine(LoadScenesAsync(scenesToLoad));
// etc.
Sounds like it could work, but how do you deal with references to objects in scene A when it’s being unloaded? You’d still need the extra checks in coroutines… also, the temporary scene is also unloaded async, so it could again happen in the middle of a coroutine, right?
Or maybe I didn’t understand it correctly.
I am thinking now, though, that maybe setting timescale to 0 could prevent any coroutines from running during the loading process and thus removing the issue that various objects are unloaded in random order…
Alternatively, a custom coroutine system could be built (or bought, whatever) that allows execution of coroutines to be paused. I think I still have an advanced coroutine system lying around somewhere that added some whistles and bells like that.
You dont need temporary scene. Unity already have it. It called DontDestroyOnLoad
It prevent all object from being destroyed when loading new scene or destroying old scene.
And my practice would be like this. No coroutines needed.
Scene 1: Main menu. Open scene up.
Move stuff to DontDestroyOnLoad:
Main Camera + lighting if needed
My Player Character (if you have one)
My Loading Canvas (overlay, only show loading word)
Open Scene 2(Level 1):
Tell my loading canvas show Black screen with loading text.
Call loading scene addictive. Add a new scene on top menu (or you could call LoadSceneMode.Single).
UnloadAsync my menu scene.
When done, tell my Loading canvas to go back to alpha 0 and show the game (Disable the main camera in DontDestroyOnLoad if you have another camera in scene).
And so on, but what happen if I open my Menu Scene again? I will have to 2 camera, 2 main character yes?
But I my Singleton script destroy all overlap GameObject that have same script SceneLoader attach as component. Therefore you will always have 1 exist camera and 1 character when reopen menu scene.
Thanks for the explanation. It seems to me that we are trying to solve different problems.
My problem is that I have a scene with lots of objects using coroutines that reference other objects. I don’t want any of these objects to remain in the scene.
Let’s say object A refers to object B and has a coroutine where the reference is used.
When I just unload the scene, both objects see destroyed before object A’s coroutine gets to run again.
When I unload the scene async, this can happen: object B gets destroyed. Next frame, object A runs its coroutine, but B is already missing, so there is an exception.
And this can happen randomly, to any object with reference to another in this scene that uses a coroutine. And to prevent it, I’d have to check the references after every yield in every coroutine.
I would just have 1 MonoBehaviour control all coroutine that ever created. So I can stop it all at the same time.
Check null exception for every new coroutine sound like really cumbersome.
Otherwise, I would add 2 scene addictive on top another then wait for all Data transfer(or Gameobject transfer) finish then Unload not needed scene.
Thanks, im also wondering why it doesnt crash when run in the editor, or built as a stand alone windows app, but the exact same code crashes in WebGL tho.