Reloading scene using addressables

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

private void ReloadLocationl()
{
    LoadLocation(currentlyLoadedScene, false);
}

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!

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.

Reload currently loaded existing scene

You can first use this to unload scenes

and then this to load the scene

This would technically reload the currently loaded scene without an error.

But why you want to do that. Do you want to apply the logic in you own project (just like me) or understand something?

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.

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.

@Amel-Unity , @cirocontinisio could you please take a look?

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)(First frame error check · HarshNarayanJha/open-project-1@02d89ce · GitHub), 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.

Thank you, it’s just I know how to do this traditionally, but not using addressables.

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.

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: Debug System
@cirocontinisio

Thanks.

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:

_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:

AsyncOperationHandle<SceneInstance> unloadingHandle = _currentlyLoadedScene.sceneReference.UnLoadScene();
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():

// We create an empty scene to keep references
AsyncOperationHandle<SceneInstance> emptySceneHandle = _emptyScene.sceneReference.LoadSceneAsync(LoadSceneMode.Additive, true);
yield return new WaitUntil(() => emptySceneHandle.IsDone);

Of course, don’t forget to remove it after your scene is loaded:

bool isLoaded = _emptyScene.sceneReference.OperationHandle.IsValid();
if (isLoaded)
{
    _emptyScene.sceneReference.UnLoadScene();
}

Congratulations, now, with the help of the method below you can reload levels:

private void OnReloadCurrentScene()
{
    if (_currentlyLoadedScene == null)
    {
        return;
    }

    LoadGameplayScene(_currentlyLoadedScene, new LoadSceneOptions(true, true));
}

Thank you!