Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

"allowSceneActivation" locks up the editor

Discussion in 'Scripting' started by drjamiearron, Mar 10, 2014.

  1. drjamiearron

    drjamiearron

    Joined:
    Jun 8, 2012
    Posts:
    134
    Hi everyone,

    I'm trying to create a loading screen. Everything works ok, but I don't want to load the new scene immediately. For some reason, Unity will freeze if I don't remove the line "async.allowSceneActivation = false;". Does anyone know why this is happening?

    Here is the code:

    Code (csharp):
    1.  
    2. async = Application.LoadLevelAsync(_levelToLoad);
    3. async.allowSceneActivation = false;
    4. yield return async;
    5.  
    I would appreciate any help with this matter :)
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,554
  3. drjamiearron

    drjamiearron

    Joined:
    Jun 8, 2012
    Posts:
    134
    Hey lordofduct,

    Thanks for your response. I had at a look at your forum post and implemented your approach. However, this still results in Unity freezing, forcing me to close the program via task manager.

    I'm not sure why this is happening, but removing the "async.allowSceneActivation = false;" fixes the issue.
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,554
    Can I see what your code is? If it's not reaching the 0.9 like it does on mine, that is a case of it not operating the same on all systems. And means my method doesn't work.

    Have you ran a debug on it to see where it's hanging?

    This is something I was afraid of, and why I hate 'magic values'.




    Note - if you want it to activate on your own terms. For instance say you are just waiting for some animation to complete before you want to allow the load to complete. You can just allow it to stick until that time comes. Basically keep yielding until isDone, then ANOTHER script will flag the thing as true, allowing it through at that time.
     
    Last edited: Mar 11, 2014
  5. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    Last time I tried this was with Unity 3.5. Maybe things have changed since then?

    In my experience, once you start asynchronously loading a level, there's no way to stop it without locking up Unity. I have never gotten allowSceneActivation to work.

    At first I wanted to load the next scene and have it standing by until I was ready to switch. Unfortunately, all I've been able to do is immediately show a loading bar while the new scene is loading.
     
  6. drjamiearron

    drjamiearron

    Joined:
    Jun 8, 2012
    Posts:
    134
    Here is my code, based on your implementation, though modified slightly:

    Code (csharp):
    1.  
    2. IEnumerator load()
    3. {
    4.     async = Application.LoadLevelAsync(_levelToLoad);
    5.  
    6.     async.allowSceneActivation = false;
    7.  
    8.     while (async.progress < 0.9f)
    9.         yield return null;
    10.        
    11.     async.allowSceneActivation = true;
    12.        
    13.     yield return new WaitForEndOfFrame(); //wait to end of this frame so anything this frame wants to spawn is spawned
    14.     yield return null; //wait that one frame
    15.        
    16.     yield return async;
    17. }
    18.  
     
  7. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,554
    Have you ran a debug through it, where does it hang? Does it hang during the while loop, because the progress never reaches 0.9?

    I would test myself, but on my system it does reach 0.9.

    What is your system you ran this on, if you don't mind me asking?
     
  8. drjamiearron

    drjamiearron

    Joined:
    Jun 8, 2012
    Posts:
    134
    This is the strangest thing. It starts the while loop, but carries on. This is despite the progress value still sits at 0. It then moves onto the last line, "yield return async;", and then boom, crash.

    Does this have anything to do with the "yield return null;" statement? Should it be something else, rather than returning null?

    I'm running the editor (v4.3.4, pro) on a high-spec windows machine.
     
  9. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    In my experience, LoadLevelAsync pretty much acts like LoadLevel in the Unity Editor. Ie: It goes from 0% to 100% in a single frame. I always had to build to a mobile device to test.
     
  10. Gibbonator

    Gibbonator

    Joined:
    Jul 27, 2012
    Posts:
    204
    This may be related to the problems you are seeing. I got stuck in an infinite loading loop when I made the mistake of missing the 'f' off the end of the 0.9f value, like this:

    Code (csharp):
    1.  
    2. while (loadOp.progress < 0.9)
    3. {
    4.   yield return null;
    5. }
    6.  
    Which doesn't produce a warning, but actually means:

    Code (csharp):
    1.  
    2. while ((double)loadOp.progress < 0.9)
    3. {
    4.   yield return null;
    5. }
    6.  
    So I tried this...

    Code (csharp):
    1.  
    2. Debug.Log((double)0.9f);
    3.  
    ...and got a value of 0.899999976158142.

    Which got me thinking that maybe Unity/Mono doesn't guarantee that floating point math is consistent across platforms (a bit different to the conversion to double, I know, but could be an issue). This could be a problem if the 90% value of loadOp.progress is produced via some calculation rather than a magic constant.

    Maybe this test will give more reliable results across platforms:

    Code (csharp):
    1.  
    2. while (loadOp.progress < 0.9f  !Mathf.Approximately(loadOp.progress, 0.9f))
    3.  
     
    Last edited: Mar 12, 2014
  11. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,554
    oh I didn't see that they didn't include the f, like I had.

    Though that's not a matter of keeping floating point math consistent, it's just a matter of float conversion from float to double.

    OP, try sticking the 'f' on there so that you're comparing with a float, and not a double.
     
  12. drjamiearron

    drjamiearron

    Joined:
    Jun 8, 2012
    Posts:
    134
    I already have the 'f' in there, if you look at the code again. I modified the the while loop line to match Gibbonator's approach, but it still results in the same thing :(
     
  13. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,554
    so I'm reading your previous post now:

    So it doesn't block at the while loop, yet the progress value is still 0.

    Something is wrong... like really wrong, if that's happening.
     
  14. drjamiearron

    drjamiearron

    Joined:
    Jun 8, 2012
    Posts:
    134
    Yep, I've just messed around with the code further. Closer inspection shows that "async.progress" never updates, it just sits at 0. For the sake of it, I placed a while loop that intentionally stays looping until progress reaches above 0.9. The result is, of course, an infinite loop. When stepping over this in Mono, again, it stays at 0.

    I've given up for the time being, and just removed the "allowSceneActivation = false" line. Everything works when that isn't there. Mind you, the process, when running, is instantaneous. You never see the loading screen on the desktop, though I haven't tried this on my iPad yet. maybe it has something to do with that?
     
    Last edited: Mar 12, 2014
  15. Gibbonator

    Gibbonator

    Joined:
    Jul 27, 2012
    Posts:
    204
    I notice that your 'async' variable isn't in the local scope of the coroutine. Could something else be messing with it? Does making it local fix it?
     
  16. drjamiearron

    drjamiearron

    Joined:
    Jun 8, 2012
    Posts:
    134
    I've double checked. Nothing else is messing with async. I made it local, but I still get the same result.
     
  17. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,554
    So what you're saying is it reaches 0.9, because that's the only way it would finish the loop (but infinite loop if it's higher that 0.9... this means the loop works).

    It goes back to zero though.

    What I'm betting, is that AyncOperation sets the progress back to zero after it's done loading and everything is activated. And I'm betting it's done activating after you do the yield return null (because it SHOULD only take 1 frame to activate).

    try this code:

    Code (csharp):
    1.  
    2. IEnumerator load()
    3. {
    4.     async = Application.LoadLevelAsync(_levelToLoad);
    5.  
    6.     async.allowSceneActivation = false;
    7.  
    8.     while (async.progress < 0.9f)
    9.         yield return null;
    10.  
    11.     async.allowSceneActivation = true;
    12.  
    13.     yield return async;
    14. }
    15.  
    or this:

    Code (csharp):
    1.  
    2. IEnumerator load()
    3. {
    4.     async = Application.LoadLevelAsync(_levelToLoad);
    5.  
    6.     async.allowSceneActivation = false;
    7.  
    8.     while (async.progress < 0.9f)
    9.         yield return null;
    10.  
    11.     async.allowSceneActivation = true;
    12.  
    13.     yield return new WaitForEndOfFrame(); //wait to end of this frame so anything this frame wants to spawn is spawned
    14.  
    15.     yield return null; //wait that one last frame
    16.  
    17.     //async SHOULD be done by here, don't yield it unless it's not done, otherwise we'll wait forever
    18.     if(!async.isDone)
    19.         yield return async;
    20.  
    21. }
    22.  


    Note, in my code I had this part:

    Code (csharp):
    1.  
    2.     yield return new WaitForEndOfFrame(); //wait to end of this frame so anything this frame wants to spawn is spawned
    3.  
    4.     yield return null; //wait that one last frame
    5.  
    only because I didn't want to yield the async object. I wanted to catch every frame up to when it was done so I can tabulate all the gameobjects in the scene just before it activates. That's all that code was for. You don't need that bit really... unless you need it for something like I did.
     
    Last edited: Mar 12, 2014
  18. drjamiearron

    drjamiearron

    Joined:
    Jun 8, 2012
    Posts:
    134
    No, it never reaches 0.9. At least, I've never seen it as anything other than 0. Also, your code sample still doesn't fix it.

    There is one other thing I've noticed. When you initiate the async operation, are you able to hover over it and see all of the values? When I do, all I get is "Object reference not set to an instance of an object." (although I can still read progress if I hover over it) Could that be it?
     
  19. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,554
    it shouldn't be null, that sounds like it's probably your problem.

    Are you using the free version of unity?

    LoadLevelAsync doesn't work in the free version.
     
  20. drjamiearron

    drjamiearron

    Joined:
    Jun 8, 2012
    Posts:
    134
    I'm using the latest version of Pro.

    Just seen the edit in your previous comment. Implemented it, still doesn't work.
     
  21. Gibbonator

    Gibbonator

    Joined:
    Jul 27, 2012
    Posts:
    204
    Probably a long shot since you get an error for this but... have you added the level you're trying to load to your build settings?
     
  22. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,554
    Yeah, that could be it.

    @OP - it's not the code, editing your code at this point isn't going to help. Your call to LoadLevelAsync isn't returning an AsyncOperation, it's null (as you said), that's your problem.
     
  23. drjamiearron

    drjamiearron

    Joined:
    Jun 8, 2012
    Posts:
    134
    I've fixed it! At last! :D

    I was calling "StartCoroutine(load())" in the Awake method, resulting in Unity crashing. I moved it into the Update method (inside a GetMouseButton) and bingo! It calls the method and doesn't crash. Although I still don't understand why removing "allowSceneActivation" fixed it in the first place...

    My only issue now is actually getting the scene to now change after the loading is finished. After the level has completed loading, I set "allowSceneActivation" to 'true', although this doesn't do anything.
     
    RDeluxe likes this.
  24. RDeluxe

    RDeluxe

    Joined:
    Sep 29, 2013
    Posts:
    117
    THIS. Damn, I was having the same problem.
    Did you report this ?

    Edit ; It's in the Awake() documentation actually. Damn ...
     
    Last edited: Feb 26, 2015