13
\$\begingroup\$

I created a loading screen to display a loading animation as the next scene is loading. I load the next scene asynchronously with:

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

And also set Application.backgroundLoadingPriority = ThreadPriority.Low;, but the behaviour is still the same as a regular level load.

Am I missing something?

Expected behaviour:

  • Exit level, and fade out.
  • Loading screen appears.
  • Once load is done, fade loading screen out.
  • Fade in next scene.

What is happening:

  • Exit level, and fade out.
  • Loading screen appears, frozen
  • Suddenly new scene fades in.

Once the load starts, the game just frezees, like with a regular Scene load.

I read that you have to set allowSceneActivation = false, so you can fade the loading screen out, and then set it to true to let unity finish loading, but this completelly freezes my game, like the async operation never finishes loading.

\$\endgroup\$
  • \$\begingroup\$ I had this problem and didn't find anything here. After googling I found out what was causing this issue. I decided to post it here so other could find the answer easily. Please let me know if you would add some improvement to my answer/question. Thanks! \$\endgroup\$ – Leo Sep 19 '16 at 15:17
16
\$\begingroup\$

When you load an scene with SceneManager.LoadSceneAsync() there are actually two things happening:

  • The gameObjects of the scene are loaded into memory.
  • Then the whole scene is enabled. All Awake() and Start() callbacks will be called for the objects in the scene.

The second step, enabling the scene, is what actually freezes unity, because unity is running all those initialization callbacks in your scripts in a single cycle.

Indeed setting SceneManager.LoadSceneAsync().allowSceneActivation to false will make the async operation to complete only the first step of the process, and will wait until it's set to true to begin the second part of the process.

But if you set allowSceneActivation to false and yield on the callback like this, you will freeze your game for good:

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

//Fade the loading screen out here

AO.allowSceneActivation = true;

Why? Because you are telling the Async operation to not proceed with the second step of the scene load, so the operation will never be completed.

If you want to know when the first part of the operation is ready, to then proceed with the second one, you have to rely on AsyncOperation.progress. This value will stop at 0.9f once it's waiting for the allowSceneActivation flag.

It should be something like this:

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;

If you want the scene activation to not freeze your game, then you should keep your Awake and Start callbacks to a minimun, and initialize your scripts in a coroutine through several cycles.

\$\endgroup\$
0
\$\begingroup\$

I had the exact same issue in Unity 5.6, and had already tried adding in the yield statements. It was the LoadSceneAsync itself that was blocking the main thread of Unity and preventing the current scene from nicely showing any loading progress.

It would seem to be a bug in Unity as far as I can tell. When my scene was less complex my code worked great, smooth transition. Once it got larger, Unity blocked the thread for about 6 seconds, all the while the game sits as 'not responding' despite the operation supposedly being "async"

The way I solved the issue was to look at my lighting. There have been massive bugs in the past with lighting and this feature. So I went through my objects, and found I had a spotlight on one object (even though it was disabled...)

I deleted the spotlight, and hooray! Scene loads async properly! No locking!

\$\endgroup\$
  • \$\begingroup\$ Prior to the edit, this post didn't actually offer a solution to the problem. It's fine now that you've added a fix, but in future if you want to say "I'm having this issue too" you should not use answers for that purpose. Earning a little rep will let you comment on existing posts, or put a bounty on questions to encourage new answers. \$\endgroup\$ – DMGregory Jul 2 '17 at 14:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.