Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only.

    Please, do not make any changes to your username or email addresses at id.unity.com during this transition time.

    It's still possible to reply to existing private message conversations during the migration, but any new replies you post will be missing after the main migration is complete. We'll do our best to migrate these messages in a follow-up step.

    On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live.


    Read our full announcement for more information and let us know if you have any questions.

Question Reloading scene using addressables

Discussion in 'Open Projects' started by stroibot, Jul 31, 2021.

  1. stroibot

    stroibot

    Joined:
    Feb 15, 2017
    Posts:
    94
    Hi,

    Scene Management in the game is amazing, but I have a question, lets say that I want to reload scene.
    Logically there's functionality to do this, so let's create method for this
    Code (CSharp):
    1. private void ReloadLocationl()
    2. {
    3.     LoadLocation(currentlyLoadedScene, false);
    4. }
    We simply load currently loaded location - genius!

    In theory it should work, but in practice I get an error:
    Attempting to load AssetReference Scene that has already been loaded

    On line
    sceneToLoad.SceneReference.LoadSceneAsync(LoadSceneMode.Additive, true, 0)


    Ok, yeah, that makes sense, but... How do I reload existing scene then?

    In regular scene it should work, but in addressables it doesn't. Is there a way of doing it?

    Thanks!
     
  2. Harsh-NJ

    Harsh-NJ

    Joined:
    May 1, 2020
    Posts:
    315
    Reload currently loaded existing scene or load an existing scene which is not loaded yet? I can't really understand you point of question. Sorry, but please rephrase.
     
  3. stroibot

    stroibot

    Joined:
    Feb 15, 2017
    Posts:
    94
    Reload currently loaded existing scene
     
  4. Harsh-NJ

    Harsh-NJ

    Joined:
    May 1, 2020
    Posts:
    315
  5. stroibot

    stroibot

    Joined:
    Feb 15, 2017
    Posts:
    94
    LoadLocation
    already does
    UnloadPreviousScene
    first and only then loads scene, that's basically what I do and why I get an error.

    To your questing why - this project is really something, that's basically answer to my prayers about architecture, because previously I was using singletons everywhere, but this project has taught me some great things, like, Audio Manager, Scene Management, Event Channels, Addressables, etc. Big thanks to all of Unity team!
    So, yes, from now on I do same architecture for my projects.
     
    cirocontinisio likes this.
  6. Harsh-NJ

    Harsh-NJ

    Joined:
    May 1, 2020
    Posts:
    315
    Yes that true. And not only thanks to Unity team but to the while community (including you and me) also. We all have worked hard to reach here and develop these amazing systems. I have studied and implemented them in my project also. You are welcome too to contribute to this project.
     
  7. stroibot

    stroibot

    Joined:
    Feb 15, 2017
    Posts:
    94
  8. Harsh-NJ

    Harsh-NJ

    Joined:
    May 1, 2020
    Posts:
    315
    I am sorry @stroibot, without knowing how exactly the error is produced, it is hard to say anything about it. I thought that it was just a warning, but I tried it myself today and it was really giving an error when we try to load a location which is currently loaded. This is something not required in our game (as far as I think), but this can be easily fixed. I will open a PR with the fix.
    Thanks @stroibot

    Also @cirocontinisio, you know that I am unable to pull the updates in git, so if I open a PR with this latest commit (First Frame Error check of yours)(https://github.com/HarshNarayanJha/open-project-1/commit/02d89ce4563083cdaaa842c16aeee8efd97bd293), will that be OK. As I know it is stated in the contribution guidelines that we should pull the latest changes from upstream before opening a PR (I am 123 commits behind).
    So I just wanted to ask if that OK or I should do something else.
    Also, Now I can see a Pull Upstream button on the Github Web UI. It does what it states?
    Thanks.
     
  9. stroibot

    stroibot

    Joined:
    Feb 15, 2017
    Posts:
    94
    Thank you, it's just I know how to do this traditionally, but not using addressables.
     
  10. cirocontinisio

    cirocontinisio

    Joined:
    Jun 20, 2016
    Posts:
    884
    Sorry guys, I have closed both PR and issue. The issue wasn't an issue, we don't have it on the game, and the fix wasn't actually fixing it, it was just silently failing.

    @stroibot I guess the short answer is that if you have a scene already loaded, to get a "fresh" copy either you clean it up, putting it back to the beginning state, or you'd have to unload it and reload it manually.
    Are you sure it's because of Addressables and doesn't work the same in regular scene loading? Talking about additive scene loading, of course just "reloading" a scene in non-additive mode would work.
     
  11. Harsh-NJ

    Harsh-NJ

    Joined:
    May 1, 2020
    Posts:
    315
    It's Ok, I initially tried to really unload and load the scene using Addressables, but at last failed into just silently returning, and really that is not and issue in our game, as we are never reloading currently loaded scene in any scenario.

    And on a side note, please take a look at this: https://forum.unity.com/threads/debug-system.1151783/
    @cirocontinisio

    Thanks.
     
    cirocontinisio likes this.
  12. unity_30D89FB79A72844A3914

    unity_30D89FB79A72844A3914

    Joined:
    Nov 29, 2023
    Posts:
    1
    Hello everyone! You don't believe me but I know how to fix your issue. Because I also faced it.
    But first, let me enjoy the moment: I am your messiah, I am your savior, I am Unity's Jesus. What would you do without me, huh? Huh?

    I finished, thank you, now to the solution:

    Indeed, the error is about the scene already loaded, you cannot load it twice.
    Then we need to unload it and load it again, which is already happening in the UnloadPreviousScene() method:

    Code (CSharp):
    1. _currentlyLoadedScene.sceneReference.UnLoadScene();
    But the Unity community decided to do all these things asynchronically, which is good in general and not good for our case - they call LoadNewScene() without waiting for the unload to complete. This approach is also not good because the _sceneToLoad reference can be lost during such risky transitions between scenes when you cannot be sure in the load ordering.

    Now, let's wait until the unload complete:

    Code (CSharp):
    1. AsyncOperationHandle<SceneInstance> unloadingHandle = _currentlyLoadedScene.sceneReference.UnLoadScene();
    2. yield return new WaitUntil(() => unloadingHandle.IsDone);
    Good, yes? Not yet.

    The problem with lost reference in the _sceneToLoad is now 100% reproducible because, for some reason, Unity cannot keep references to previous scene assets if there is no at least one scene that could "handle"/"keep" it. You will be always noticing that _sceneToLoad is lost until you add a temporary/blank/fake scene before you unload the previous scene. Just create a ScriptableObject scene that will contain an empty scene Addressable inside, add it to the SceneLoader as a SerializableField, set it in the editor and load it before the _currentlyLoadedScene.sceneReference.UnLoadScene():

    Code (CSharp):
    1. // We create an empty scene to keep references
    2. AsyncOperationHandle<SceneInstance> emptySceneHandle = _emptyScene.sceneReference.LoadSceneAsync(LoadSceneMode.Additive, true);
    3. yield return new WaitUntil(() => emptySceneHandle.IsDone);
    Of course, don't forget to remove it after your scene is loaded:

    Code (CSharp):
    1. bool isLoaded = _emptyScene.sceneReference.OperationHandle.IsValid();
    2. if (isLoaded)
    3. {
    4.     _emptyScene.sceneReference.UnLoadScene();
    5. }
    Congratulations, now, with the help of the method below you can reload levels:

    Code (CSharp):
    1. private void OnReloadCurrentScene()
    2. {
    3.     if (_currentlyLoadedScene == null)
    4.     {
    5.         return;
    6.     }
    7.  
    8.     LoadGameplayScene(_currentlyLoadedScene, new LoadSceneOptions(true, true));
    9. }
    Thank you!