I tried to switch my scene loading to use the asynch method so that I can actually have a small loading icon animate on the player’s screen instead of just being stuck on a black screen. (I have screen wipes that finish on a black screen.)
But yet when I call the asynch load function my game still stays frozen on a black screen while the new scene loads. I have a script running which is supposed to animate an icon that fades in in the corner. Each update it is supposed to increase the alpha. But nothing ever appears until loading has finished.
To test that everything was working properly I added a bunch of bunk data into one of my levels to make sure it had a noticeable load time. I threw in an extra five music tracks. It now takes about two seconds or so to load, but the whole time I’m staring at a black screen.
void StartNextLevel() {
if (Application.CanStreamedLevelBeLoaded(loadThisLevel))
{
StartCoroutine(LoadYourAsyncScene(loadThisLevel));
}
else
{
Debug.LogError("Attempted to load non-existing scene: " + loadThisLevel);
StartCoroutine(LoadYourAsyncScene(1)); // This must always be the Chris Houlihan room.
}
}
IEnumerator LoadYourAsyncScene(string Level)
{
// The Application loads the Scene in the background as the current Scene runs.
// This is particularly good for creating loading screens.
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(Level);
// Wait until the asynchronous scene fully loads
while (!asyncLoad.isDone)
{
HUD.bLoadingLevel = true;
yield return null;
}
}
Sounds usually bad idea, they are just registered, the metadata will be loaded but by default they are streamed if I’m not mistaken.
But, the important thing is, it is working for me. here is my test code:
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Test : MonoBehaviour
{
private int i = 0;
void Update()
{
if (i == 10)
StartCoroutine(LoadLevel());
if (i < 50)
Debug.Log(i++);
}
private IEnumerator LoadLevel() {
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(1);
var t = 0;
// Wait until the asynchronous scene fully loads
while (!asyncLoad.isDone)
{
Debug.Log($"Loading... {t}");
t++;
yield return null;
}
}
}
As you can see, update is counting, at 10 it starts loading and continue counting, while the loading is counting and finally the new scene is loaded. Here is the output:
[…]
Second scene:
using UnityEngine;
public class TestAsync : MonoBehaviour
{
void Start()
{
Debug.Log("Second is loaded");
}
}
I added some debug log calls to my update function. It took five seconds to load the scene, and update was only ever called twice while the scene was loading.
That was on the level I dumped in some extra audio files to increase the load time. My other levels take less than a second to load, and some get just one update in that time, other two.
void Update () {
if (bLoadingLevel)
{
UpdateFrameCounter++;
}
else if (UpdateFrameCounter > 0)
{
Debug.LogWarning("Updates during loading sequence was " + UpdateFrameCounter);
UpdateFrameCounter = 0;
}
(I made it LogWarning to make it easier to find.)
I also tried adding a debug log to the “while !asynchLoad.isDone” and it actually gets called three times. Not surprising, really. The first one gets called at the start of the loading process and none of the others appear until right at the very end.
I tried adding a bunch of extra textures into the scene and sometimes I might get it to take up to four update calls to load everything, but it is otherwise the same pattern. There are no loading calls until the end of the loading sequence. These textures also didn’t increase the load time; it still wasn’t more than five seconds from the first “loading” log until the second.
I could understand if this was hanging while I loaded a particularly large file, but there are actually five such files, and if I can never get a single update over a five second span while each of these load, then there seems to be something wrong with the function.
Can you first simplify this whole process just to that what I sent you above? And then if it is working you can expand to your own solution.
Also can you share the entire script with us to see what’s wrong? As I proved above the functionality is working.
BTW, just for the record: I imported every prefab into the loaded scene from the “PBR Creatures (Pack)”.
I tried it on a regular level and I got to “12” and “loading 2” before it finished loading with no discernible gap in the load time.
And I already deleted all the extra audio tracks from the other level I was testing, so I had to add them back in to give it a heavy load. But here it is when I load that:
Again, a five second gap in time with no updates, and then loading finishes with only counting two frames before the load finishes.
At this point I’m guessing it just doesn’t like those music files I dropped in, but I don’t have enough large textures on hand to try it with different assets.
I’m also on the fence about even using asynch loading; it doesn’t look likely that I’m ever going to have enough data in any one scene to justify a loading icon. But down the road, maybe? Some day when I start adding the final-quality cutscenes and music, instead of the placeholder stuff I have now. Of course, at that point loading audio files is exactly the type of data I’d be bringing in, so…
And also, asych loading is causing some of my event scripts to break, and I see no reason why. They have finished everything they are supposed to do before the load commands get called, because they actually just trigger a screen wipe, and the scene loads after the wipe finishes. And somehow the change to use asynch load causes these to not execute properly. One doesn’t even trigger the screen wipe. Makes no sense at all; I change one line from “scenemanager.loadscene” to “Startcoroutine(loadasynchscene)” and the code that gets called BEFORE that line stops working.