- Home /
Loadlevel.async stops at ~90%?
Hi all, tried to use the loadlevelasync function, as I understand those are useable with the free version of unity 5? If they're not, well, I guess that would explain it...
If they are, well, here is my relevant code:
AsyncOperation loadLevel;
IEnumerator LoadNextLevel(){
loadLevel = Application.LoadLevelAsync(scene);
loadLevel.allowSceneActivation = false;
yield return loadLevel;
Debug.Log("loading complete");
}
void Update(){
if(loadLevel != null){
loadBar.fillAmount = loadLevel.progress;
if(loadLevel.isDone){
beginButton.interactable = true;
}else{
beginButton.interactable = false;
//backButton.interactable = false;
}
}
}
void Start () {
StartCoroutine(LoadNextLevel());
}
I don't get any errors or anything, the loadbar fills to about 90% and then just...stops, and I never see my 'loading complete' debug statement. So...am I doing something wrong or do I have to get the pro version in order for this to work?
I also want to answer to this question since i am working on a game where i have to create a lot of colliders and other stuff on scene in start function. So basically when i call function to load scene my bar gets to 90% same as yours and stops there so i have to wait another 20 - 30 seconds for everything to load but bar not moving up, it is stuck at 90% and screen freeze until level is loaded. Don't know what to do
I also want to answer to this question since i am working on a game where i have to create a lot of colliders and other stuff on scene in start function. So basically when i call function to load scene my bar gets to 90% same as yours and stops there so i have to wait another 20 - 30 seconds for everything to load but bar not moving up, it is stuck at 90% and screen freeze until level is loaded. Don't know what to do
Answer by ThermalFusion · Apr 29, 2015 at 12:17 PM
AsyncOperation.isDone will never be true if AsyncOperation.allowSceneActivation is false. Progress will stop at around 0.9f. You can work around this to do whatever needs to be done before the final load takes place by waiting until progress has reached 0.9f, and end with allowing the scene activation again after you've done what you need to prior to that. Example:
using UnityEngine;
using System.Collections;
public class LoadLevel : MonoBehaviour {
public string level;
private string progress = ""; // Name of scene to load.
private bool isLoading = false;
private bool doneLoading = false;
private bool allowLoading = false;
private void OnGUI() {
GUILayout.BeginVertical("box");
if (!isLoading) {
if (GUILayout.Button ("Begin Load")) {
isLoading = true;
StartCoroutine(LoadRoutine());
}
} else {
if (doneLoading) {
if (GUILayout.Button ("Actually Load")) {
allowLoading = true;
StartCoroutine(LoadRoutine());
}
}
GUILayout.Label(progress);
}
GUILayout.EndVertical();
}
private IEnumerator LoadRoutine() {
AsyncOperation op = Application.LoadLevelAsync(level);
op.allowSceneActivation = false;
while (op.progress < 0.9f) {
// Report progress etc.
progress = "Progress: " + op.progress.ToString();
yield return null;
}
// Show the UI button to actually start loaded level
doneLoading = true;
while(!allowLoading) {
// Wait for allow button to be pushed.
progress = "Progress: " + op.progress.ToString();
yield return null;
}
// Allow the activation of the scene again.
op.allowSceneActivation = true;
}
}
One important thing to note is that anything that happens in Start or Awake on any of the MonoBehaviours in the new scene will not be performed asynchronously. It will only load the things that are in the scene before any code in it is actually run. Another example of an Awake/Start script in the loaded level that takes a long time to process shows that this is the case:
using UnityEngine;
using System.Collections;
public class WorkAtStart : MonoBehaviour {
public int calculations = 10000;
public int iterations = 10000;
public bool inAwake = true;
public bool inStart = true;
void Start () {
if (inStart == true) {
Calculate("Start");
}
}
void Awake() {
if (inAwake == true) {
Calculate("Awake");
}
}
string debugText = "Calculating...";
private void Calculate(string funcName) {
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
Vector3 calc = Vector3.zero;
// Do some random calculations:
for (int i = 0; i < iterations; i++) {
calc = Vector3.zero;
for (int c = 0; c < calculations; c++) {
calc = calc + Random.onUnitSphere;
}
}
stopwatch.Stop();
Debug.Log (stopwatch.Elapsed);
debugText += "\n" + funcName + ": " + stopwatch.Elapsed.ToString();
}
private void OnGUI() {
GUILayout.BeginVertical("box");
GUILayout.Label(debugText);
GUILayout.EndVertical();
}
}
So if you need to do asynchronous things in Start/Awake you will need to fire up some Coroutines or do some threading inside the new scene.
Well, I don't do anything really heavy in start() or awake(), I just wanted a loading bar, and to activate a button to go to the next level when it was done. One the one hand it makes sense that the load operation is never done without actually loading the scene, on the other hand, bit confusing.
Ah well, I'll just show the load bar in a separate loading screen scene ins$$anonymous$$d of during my mission briefing (I wanted to have a load bar while showing a mission briefing, then you could click 'start mission' when it was fully loaded and you had read everything and set some parameters).
I agree it is confusing, isDone should really turn to true even if allowSceneActivation is false, likewise progress should go to 1.
Regarding briefing during the loading, with a button when it's done, that's pretty much what my example does.
Yes, but your example loads to 90%, then allows the button to be pressed after that. I think that's something that could really confuse a player - it's 90% done loading but I can press "Start" now? (Yes, you could just cheat and add 10% to your visible load progress but I don't like doing things like that, it makes code confusing and weird).
Answer by doug__ · Oct 25, 2015 at 05:59 AM
It's worth noting, for anyone else who finds this issue, that you cannot finish the LoadLevelAsync()
operator if you don't yield from a MonoBehaviour
context.
public IEnumerator Open(string sceneId) {
AsyncOperation op = Application.CanStreamedLevelBeLoaded(sceneId) ? Application.LoadLevelAsync(sceneId) : null;
if (op != null) {
op.allowSceneActivation = true; // Do not defer loading
while (!op.isDone) {
yield return new WaitForSeconds(0.1f);
}
}
}
This above function will never complete beyond 0.9 loaded if it is not yielded into a monobehaviour context, like this:
public void LoadScene(MonoBehaviour context, string sceneId) {
context.StartCoroutine(Open(sceneId));
}
This is a bug in Unity; without the MonoBehaviour to track, the AsyncOperation will never complete; waiting for 0.9 does NOT fix this issue and under no circumstances should you ever use the hack:
while (op.progress < 0.9) { ... }
As a workaround; this code above is incorrect; the new level will not have loaded when the function returns; specifically components and objects in the scene will not have spawned.
Answer by JoeStrout · Apr 28, 2015 at 05:45 PM
If you "yield return loadLevel", then that's it for that method; nothing beyond that point will ever get executed. That's why you don't see your debug log. Use "yield return null" if you want to continue execution (asynchronously).
As for the progress, I too see the progress reports stop around 90%, but then isDone becomes true shortly after that. So it doesn't seem like a big deal to me. But note that it may be considerably smoother in a built app than when running within the editor, so be sure to test it there.
Thanks for answer, i am doing it with return null and yeah i get progress working and shown, but in my case i have to instantiate around 10000 game objects so that is intensive process and require time so my load is around 20 sec and i want people to still see loading progress, not to have feel of game freeze. I get instant load to 90% but then i have to wait over 15 seconds for level to load
Even when running as a built app (not within the Unity editor)?
On build app it works normally (part with progress bar up to 90%) but it's the same when stuck at 90%, i still have wait for my colliders to be created on the scene. If it wasn't for those creation of so many objects, then it would be fine i guess when i build app. Collider creation is happening on start function (tried with awake, still the same) and i tried to add indicator for loading but not working when i stuck at 90%, basically screen freeze and all i can do is to wait for it to load
Changing the yield statement to return null does show my debug statement, but my programm still just freezes on 90% loaded. It does not complete shortly after - it doesn't complete (it hadn't completed after 5 $$anonymous$$utes and I figured it wasn't going to happen after that). Running a built app rather than in the editor didn't seem to make a difference.
Answer by Noxury · Aug 01, 2016 at 04:59 PM
For lazy guys adding 11 to the progress value should do it.
Your answer
Follow this Question
Related Questions
Loading Progress using UNET 2 Answers
Reloading scene asynchronously causes stutter as the scene seems to restart a few times in a row. 1 Answer
Build game in Window phone 8 platform. 0 Answers
Scene items are not showing in hierarchy nor in scene window in unity 5 0 Answers
Close unity activity and start another activity - android 0 Answers