Wednesday, March 26, 2014

Unity3d Preloading Scenes with allowSceneActivation = false working (Loading scene in background)

Loading Scene in Background without switching the level immediately.


Read below to find a working (and tested)  way of loading scene in background in Unity3d. Also it wont  switch next level immediately.

If you are trying to preload a new scene, you have to use Application.LoadLevelAsync("sceneName"); method. I have managed to use this function with allowSceneActivation=false. When you set allowSceneActivation to false, you will probably sett that Unity Editor hangs. This is why you must use a different approach to achieve preloading.

IF allowSceneActivation locks up  Unity Editor  try this script:

IEnumerator LevelLoaderProcess() {
AsyncOperation status = Application.LoadLevelAsync("gameScreen");
status.allowSceneActivation = false;

// Wait until done and collect progress as we go.

//while( !status.isDone )
//{
loadProgress = status.progress;
if( loadProgress >= 0.9f )
{
Debug.Log("almost done");
// Almost done.
//break;
}
yield return null;
//}

while (!doLoadNextFrame) {
Debug.Log("still waiting");
                       //You can do whatever you want here...  
yield return new WaitForSeconds(1.0f);
}
// Allow new scene to start.
status.allowSceneActivation = true;
//yield return status;
}

You see that 0.9f if condition? Well that is the trick. When you set status.allowSceneActivation to false, unity3d stops loading target scene as soon as it loads  %90 of scenes content. And starts to wait for that 10 percent to load the next scene.  To load that 10% data, Unity3d will be waiting for status.allowSceneActivation = true; command.

Script I share above handles this issue.


Another thing to notice. DO NOT put your StartCoroutine command in AWAKE function. This also makes  unity crash, your editor crashes which makes it unresponsive. This is a Untiy3d bug I believe.  You can put a gui button in your  OnGUI  method to start your coroutines. Like this:

void OnGUI()  {
if (GUI.Button (new Rect (10, 10, 50, 50), "sirinlike")) {
StartCoroutine (LevelLoaderProcess());
}
}





1 comment:

  1. I was also having this problem but this script is a little confusing. Can you please explain it more and show your call to actually do the scene load? Also the commenting out is confusing.

    What I'm trying to do is on Start of my main menu, preload the simple battle scene, so when they press play, it switches immediately.

    I have the preloading, but once they hit play (to which I use application.loadlevel) it hangs.

    ReplyDelete