Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Finish addressables loading before scene start

Discussion in 'Addressables' started by Makkus, Apr 7, 2020.

  1. Makkus

    Makkus

    Joined:
    Sep 14, 2015
    Posts:
    20
    I recently started testing the addressables system, but get stuck with a rather trivial problem. In my game I've got a rather 'static' scene which can be equipped with different assets. One of these adaptable assets is carrying the main camera. Unfortunately, addressable loading is async, thus the scene starts without a camera being instantiated. This causes lots of 'missing audio listener' log messages (and other problems).

    Are there any ideas how to (pre) load important addressables via scripting so that they can be instantiated in the scene before it starts updating / rendering. How can I make sure a scene with addressables is 'complete' before it starts updating?
     
    Last edited: Apr 8, 2020
  2. chanon81

    chanon81

    Joined:
    Oct 6, 2015
    Posts:
    168
    Coincidentally, I just wrote a long post describing this problem (or a similar one) and how I do it in my game:
    https://forum.unity.com/threads/non-async-version.627670/#post-5684737

    I would like to also know if there is a simpler way.

    It is just another result of Addressable API being designed without thought for how it will actually be used.
     
  3. phobos2077

    phobos2077

    Joined:
    Feb 10, 2018
    Posts:
    350
    I think you have 2 options:
    1. Use scene management script that lives in a "bootstrap" scene that will know about dependencies for your scene, will load them before the scene is loaded and activated.
    2. Change the code and/or objects in your scene so that it doesn't break if those assets are missing and basically wait until they are loaded before instantiating/initializing.
     
  4. Makkus

    Makkus

    Joined:
    Sep 14, 2015
    Posts:
    20
    phobos2077 suggestions are unfortuately no option in my case.I really need a way to add prefabs to a specific (given) scene. I am really confused by the unfortunate addressables async compulsion - aysc is really a nasty complexity is would expect to be hidden from the developer. Anyhow, I for others with this problem I like to explain an additional approach to the ones suggested in chanon81s post which I have test-implemented today:
    Idea is to separate loading and instantiation of the addressables. Loading (but not instantiation) will be done in a 'bootstrap' scene (aka the scene that is active before). The key is to solve two problems: A) How do I 'transfer' the loaded prefabs to the subsequent scene and B) (at least for my case) how to wait for all asset loading to be completed. Problem A) I solved by simply creating a Singleton class which keeps a Dictionary<string, GameObject>. This Singleton is then *used* inside the Start() method of the subsequent sene for prefab instantiation and configuration. This works because the prefabs have not been instantiated and these operations are synchronous. Problem B) I solved by creating a loading helper class that basically counts the number of Addressables to load (and the number that have completed) and notifies a listener when all Addressables are loaded. This callback is then used to load the subsequent scene.
    In contrast to the SynchAddessable Demo this approach should work with remote assets as well as with local assets. This scene will be started in the 'traditional' way with all prefabs instantly ready.
     
    chanon81 likes this.
  5. TreyK-47

    TreyK-47

    Unity Technologies

    Joined:
    Oct 22, 2019
    Posts:
    1,796
    I'll flag this for the team to have a look. Can you tell me which version of editor and Addressables you're using?
     
  6. phobos2077

    phobos2077

    Joined:
    Feb 10, 2018
    Posts:
    350
    You can use labels to load all assets that you need to be pre-loaded at once without having to write your own bicycle for combining async handles. Just assign the same label to all those assets in the Asset Groups window.
     
    tgrotte and Makkus like this.
  7. Makkus

    Makkus

    Joined:
    Sep 14, 2015
    Posts:
    20
    @phobos2077 perfect, I'll do this - it will make things way cleaner, thanks. .. Oh wait, I just realized, in can't be that trivial. I need different assets according to some pre-conditions. So I always need a way to wait for multiple load operations to complete (either loading multiple lables or individual assets)...
    @ TreyK-47 I'm on Editor 2019.2.21.f1 and Addressables 1.7.5
     
    Last edited: Apr 9, 2020
    chanon81 likes this.
  8. chanon81

    chanon81

    Joined:
    Oct 6, 2015
    Posts:
    168
    Yes, this was my problem too ... which isn't really an uncommon requirement. Sometimes it isn't possible to know beforehand what specific assets will be needed. The result is us Addressable users with this kind of requirement have to implement a system one way or another to fix this problem.

    So yeah, your solution with a scene that loads things for another scene sounds like a way to do it.

    For my solution, each Component can implement IPreStart with any logic needed to determine what needs loading.
     
  9. phobos2077

    phobos2077

    Joined:
    Feb 10, 2018
    Posts:
    350
    There is Addressables.LoadAssets method where you can load a bunch of different keys (asset ids or labels) and have just one AsyncOperationHandle. No need to reinvent the wheel.

    PS: if you really want to combine several AsyncOperationHandles you can use Task.WhenAll and pass handle.Task for each handle.
     
  10. Makkus

    Makkus

    Joined:
    Sep 14, 2015
    Posts:
    20
    Addressables.LoadAssets is a good hint - I will check, if I can replace my code with this. I was somehow irritated by Addresables.InstantateAll() wich I found first, but only takes a single key. LoadAssets() can handle multilpe keys, which is what I need.
    Can you post a brief example of how this would look like? Task is form the async/await pattern, right? Never used this before.
     
  11. phobos2077

    phobos2077

    Joined:
    Feb 10, 2018
    Posts:
    350
    Yes it's async/await. Perfectly normal to use since Unity added UnitySynchronizationContext somewhere around 2017.x I think (executed in the main thread by default, from within the main loop, I think somewhere around LateUpdate, you can look it up).

    Code (CSharp):
    1. var handles = new [] {
    2.    Addressables.LoadAsset("asset1").Task,
    3.    Addressables.LoadAsset("asset2").Task
    4. };
    5. var assets = await Task.WhenAll(handles);
    6.  
    7. foreach (var asset in assets)
    8. {
    9.    // do the magic
    10. }
    More info here.
     
    IggyZuk likes this.
  12. Makkus

    Makkus

    Joined:
    Sep 14, 2015
    Posts:
    20
    :) Thank you!