Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Hosting Plugin to load Addressables from Firebase Storage

Discussion in 'Addressables' started by robinryf, Sep 29, 2019.

  1. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    Hello Unity Community,


    I recently played around with Addressables and since my projects tend to base on Google Firebase I thought: Could not be that hard to host my Addressable AssetBundles on Firebase Storage and load them from the client, right ... right? It actually turned out to take more time than expected because I could only find guides which download the AssetBundles directly from the http:// links and not using the Firebase API to retrieve the FirebaseStorage location dynamically.

    I have a working version and just wanted to share it with you and gather feedback or suggestion on how to improve on the code! Please have a look at the ReadMe to get further setup instructions:

    https://gitlab.com/robinbird-studio...ls/blob/master/Storage/Addressables/README.md

    Or you can directly add
    Code (CSharp):
    1. "robinbird.firebasetools": "https://gitlab.com/robinbird-studios/libraries/unity-plugins/firebase-tools.git"
    to your
    Code (CSharp):
    1. <PROJECT_URL>/Packages/manifest.json
    and open Unity.


    Best regards,

    Robin
     
  2. traden

    traden

    Joined:
    Sep 16, 2009
    Posts:
    65
    Seems to work! Thanks Robin.
     
  3. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    Great to hear, if you have any problems please let me know
     
  4. stevenchristian20

    stevenchristian20

    Joined:
    Dec 23, 2019
    Posts:
    25
    Hey,

    I am trying to link up my Firebase Storage for Addressables and I am unable to link the Git with my unity. It gives me an error. can I just download the .zip of the repo and copy the contents to my unity project folder?
     
  5. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    Hi Steven,

    Jep, you can just unpack the whole Git Repo Zip into the Assets directory.

    Out of curiosity and for future people: Could your share the error message you received? Did you try to integrate with the package manager?

    Cheers,

    Robin
     
  6. stevenchristian20

    stevenchristian20

    Joined:
    Dec 23, 2019
    Posts:
    25
    I got it working. I needed to download Git onto my computer. The problem I have now is that I am trying to download the addressables I loaded on Firebase to my device and load the assets into a scene. None of the assets are loading. Do I need to initiate a script to download when the scene is opened? or can I download and load everything when the app opens up to the menu screen before I select the scene.
     
  7. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    Ah I see.

    Normally Addressables downloads things directly on demand when you need them. So you don't have to add a step to download things in advance. There are ways to download everything at start of the app in some initial Download Loading Screen but this is not the scope of this post. This extension "just" allows you to download the assets from Firebase using the normal Addressables API.

    Have you followed the Guide to setup Firebase loading here: https://gitlab.com/robinbird-studio...ls/blob/master/Storage/Addressables/README.md

    There is also an example project which you could compare to your setup: https://gitlab.com/robinbird-studios/hives/firebase-tools-hive

    Hope this helps. If it still does not work for you, maybe you can share an example project and I can have a look.

    Cheers
     
  8. stevenchristian20

    stevenchristian20

    Joined:
    Dec 23, 2019
    Posts:
    25
    Yeah thanks. I was able to get it working after some playing around. I definitely used your demo project as an example!
     
  9. stevenchristian20

    stevenchristian20

    Joined:
    Dec 23, 2019
    Posts:
    25
    So quick Question: I was looking at your example script and the firebase one an I am confused as to why the initialization scripts are different. Could you explain the differences?

    From your Sample:

            // Make sure to continue on MAIN THREAD for addressables initialization
    Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task => {
    var dependencyStatus = task.Result;
    if (dependencyStatus == Firebase.DependencyStatus.Available)
    {
    // Create and hold a reference to your FirebaseApp,
    // where app is a Firebase.FirebaseApp property of your application class.
    // app = Firebase.FirebaseApp.DefaultInstance;

    Debug.Log("FIREBASE INIT FINISHED");
    FirebaseAddressablesManager.IsFirebaseSetupFinished = true;

    // Set a flag here to indicate whether Firebase is ready to use by your app.
    }
    else
    {
    UnityEngine.Debug.LogError(System.String.Format(
    "Could not resolve all Firebase dependencies: {0}", dependencyStatus));
    // Firebase Unity SDK is not safe to use here.
    }
    });


    From Firebase Sample:


     protected virtual void Start()
    {
    persistentDataPath = Application.persistentDataPath;
    FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task => {
    dependencyStatus = task.Result;
    if (dependencyStatus == DependencyStatus.Available)
    {
    InitializeFirebase();
    }
    else
    {
    Debug.LogError(
    "Could not resolve all Firebase dependencies: " + dependencyStatus);
    }
    });
    }
     
  10. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    I don't see a big difference. Both execute the handler on the main thread by "ContinueWithOnMainThread". Both check for "DependencyStatus.Available". In the sample for Firebase Storage Adressables we have to tell the Manager that the Firebase init is now ready by calling:
    FirebaseAddressablesManager.IsFirebaseSetupFinished = true;

    Any specific difference which you want to highlight?
     
  11. stevenchristian20

    stevenchristian20

    Joined:
    Dec 23, 2019
    Posts:
    25
    maybe I am looking into this too much because I often have typos in my logic, but:

    Firebase.FirebaseApp.CheckAndFixDependenciesAsync()

    vs

    FirebaseApp.CheckAndFixDependenciesAsync()

    Not much of a difference in the overall function?
     
  12. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    That is no functional difference. The one just states the explicit namespace and the other one is using a "using Firebase" at the top of the file. Like you could use at the top of the file "using System.Generic.Collections" and then use "List<>" in the code or you could directly use "System.Generic.Collections.List<>" directly.
     
  13. jay_unity490

    jay_unity490

    Joined:
    Oct 5, 2019
    Posts:
    2
    First of all thank you for the plug-in.

    Does this support "Update a Previous Build" ?
    Thanks in advance :)
     
  14. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    I haven't used this functionality in any of my projects so I am not sure if it works, sorry. Actually this plugin just allows you to download Addressables files from a different remote server location. All the internal Addressable handling/loading is left in Unity's hands. So I don't see a reason why it should not work with patch files. But again I can't confirm this. I would be eager to know if it works if you come around testing it. You can also open a GitLab issue and I'll have a look if I can remove any blockers

    Cheers
     
    jay_unity490 likes this.
  15. jay_unity490

    jay_unity490

    Joined:
    Oct 5, 2019
    Posts:
    2
    Working perfectly fine.
    You are really a wizard:cool:
     
  16. takatori_unity

    takatori_unity

    Joined:
    Jan 13, 2019
    Posts:
    2
    Is GetDownloadSizeAsync API working ?
    I tried to call this API, But callback only 0.
     
  17. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    As far as I know the GetDownloadSizeAsync method takes the download size from the AssetCatalog. This plugin uses the normal Addressables catalog. So it should work.

    Please be aware that if your assets are already in the cache on your local system the GetDownloadSizeAsync method will always return 0 because there is nothing to download. Use ClearCache to make sure you actually download and not load from cache.

    I have not tested this myself. I will try to test it in the next few days.
     
  18. takatori_unity

    takatori_unity

    Joined:
    Jan 13, 2019
    Posts:
    2
    I tried to use ClearCache before downloading Addressable Resource from Firebase Storage, But callback only always 0.
    Please try to test GetDwonloadSizeAync API.
     
  19. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    I indeed found an issue with the 'GetDownloadSizeAsync' method. The Addressables codebase assumes that everything remote starts with "http"

    Code (CSharp):
    1. internal static bool IsPathRemote(string path)
    2. {
    3.     return path != null && path.StartsWith("http");
    4. }
    Since the InternalId of the Firebase stuff starts with "gs://", Addressables just assumes that it is local. I am working on a fix. Thanks for pointing it out!
     
  20. jbergs

    jbergs

    Joined:
    Feb 13, 2014
    Posts:
    14
    Do you think this might be the problem of why my Addressable builds do not upload to Firebase Storage, because of the "gs://" address? They seem to build correctly but it just doesn't upload to Firebase. Have you had this problem recently?
     
  21. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    This plugin does not support uploading the built bundles to Firebase Storage. It implements the downloading but not the uploading. So you either manually upload them via the website or you can use the Firebase Admin Sdk to upload them. I use a little work in progress script to upload the files: https://gitlab.com/robinbird-studio...er/Firebase/Admin/UploadDirectoryToStorage.py
    It works but is not pretty. You have to exchange the paths to the local files and the paths to the files on the Firebase Storage bucket. Also you have to have your admin-sdk-key.json from Firebase in the current directory you are executing "python3 UploadDirectoryToStorage.py"

    AFAIK Addressables in general does not upload any content for you.
     
  22. jbergs

    jbergs

    Joined:
    Feb 13, 2014
    Posts:
    14
    Oh, very interesting. Thanks I’ll take a look at your script. I’m also in the midst of figuring out Addressables so that’s not helping me any.

    Thank you for your work on this, it’s been extremely helpful!
     
    robinryf likes this.
  23. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    I finally figured this out. Took longer than expected :D I updated the Plugin on GitLab. Please let me know if this works for you. I added an example on how to get the Download Size and also how to pre-download the files here:
    https://gitlab.com/robinbird-studio...r/Unity/Assets/Scripts/InitFirebaseStorage.cs

    Two things to make this work. You have to add certain hooks into Addressables for this to work.
    Code (CSharp):
    1. Addressables.InternalIdTransformFunc += FirebaseAddressablesCache.IdTransformFunc;
    Also you have to call
    Code (CSharp):
    1. FirebaseAddressablesCache.PreWarmDependencies()
    before calling GetDownloadSize(). Then everything should work out. Check out the example if this is unclear.
     
  24. elfasito

    elfasito

    Joined:
    Jul 4, 2017
    Posts:
    14
    Hello robin, Im new with unity.
    I cant understand this part of you readme:
    Configure Scripts
    Before you load any Addressable Asset you have to add the FirebaseStorage Providers and hooks to the Addressables API:

    Addressables.ResourceManager.ResourceProviders.Add(new FirebaseStorageAssetBundleProvider());
    Addressables.ResourceManager.ResourceProviders.Add(new FirebaseStorageJsonAssetProvider());
    Addressables.ResourceManager.ResourceProviders.Add(new FirebaseStorageHashProvider());

    where I put these lines?. Thanks
     
  25. IJsLauw

    IJsLauw

    Joined:
    May 31, 2015
    Posts:
    8
    Hi Robin, thanks for your plugin. I've implemented everything as good as I could and try to preload two assetGroups/-bundles at the beginning of starting our app. All goes well, everything get's downloaded (as far as I can tell). Except for this error that is fired/spammed in the console:

    It's in FirebaseAddressablesCache => StartUrlFetch

    Code (CSharp):
    1.  
    2. if (task.IsCanceled || task.IsFaulted)
    3. {
    4.     Debug.LogError($"Could not get url for: {firebaseUrl}, {task.Exception}");
    5. }
    6.  
    And this is what it throws:


    Could not get url for: gs://plus-test-xyz.appspot.com/Android/collection_assets_all_5914dac1c3ec76b991bf0e96170bd816.bundle, System.AggregateException: One or more errors occurred. ---> Firebase.Storage.StorageException: The server did not return a valid JSON response. Contact Firebase support if this issue persists.
    --- End of inner exception stack trace ---
    ---> (Inner Exception #0) Firebase.Storage.StorageException: The server did not return a valid JSON response. Contact Firebase support if this issue persists.<---


    This is the code used to download the assetgroups

    Code (CSharp):
    1. List<object> keys = new List<object>()
    2.         {
    3.             "Collection", "Scanner"
    4.         };
    5.         try
    6.         {
    7.             FirebaseAddressablesCache.PreWarmDependencies(keys,
    8.                 () =>
    9.                 {
    10.                     var handler = Addressables.GetDownloadSizeAsync(keys);
    11.  
    12.                     handler.Completed += handle =>
    13.                     {
    14.                         if (handle.Status == AsyncOperationStatus.Failed)
    15.                         {
    16.                             Debug.LogError(
    17.                                 $"Get Download size failed because of error: {handle.OperationException}");
    18.                         }
    19.                         else
    20.                         {
    21.                             Debug.Log($"Got download size of: {handle.Result}");
    22.  
    23.                             asyncOperationHandle =
    24.                                 Addressables.DownloadDependenciesAsync(keys, Addressables.MergeMode.Union);
    25.  
    26.                             downloadStarted = true;
    27.  
    28.                             asyncOperationHandle.Completed +=
    29.                                 operationHandle =>
    30.                                 {
    31.                                     downloadStarted = false;
    32.  
    33.                                     var dependencyList = (List<IAssetBundleResource>) operationHandle.Result;
    34.                                     foreach (IAssetBundleResource resource in dependencyList)
    35.                                     {
    36.                                         AssetBundle assetBundle = resource.GetAssetBundle();
    37.                                         Debug.Log($"Downloaded dependency: {assetBundle}");
    38.                                     }
    39.  
    40.                                     if (operationHandle.Status == AsyncOperationStatus.Succeeded)
    41.                                     {
    42.                                         Addressables.Release(asyncOperationHandle);
    43.                                         GameEventMessage.SendEvent("AssetsLoaded");
    44.                                     }
    45.                                     else
    46.                                     {
    47.                                         Debug.LogError(
    48.                                             $"{this}: error downloading dependencies - status: {operationHandle.Status}: exception: {operationHandle.OperationException?.Message}",
    49.                                             this);
    50.                                     }
    51.                                 };
    52.  
    53.                             asyncOperationHandle.Destroyed += (h) =>
    54.                             {
    55.                                 Debug.Log($"{this}: destroyed downloader: {h.Status}", this);
    56.                             };
    57.                         }
    58.                     };
    59.                 });
    60.         }
    61.         catch (Exception e)
    62.         {
    63.             Debug.LogError($"{this}: error downloading dependencies: {e.Message}", this);
    64.             ShowErrorPopup(e.Message.Split('\n').Last());
    65.         }
    Any idea why firebase would have trouble reaching an url at the start, but is able to download it later?
     
  26. IJsLauw

    IJsLauw

    Joined:
    May 31, 2015
    Posts:
    8
    Checkout his example project and all will be clear: https://gitlab.com/robinbird-studios/hives/firebase-tools-hive

    Specifically the InitFirebaseStorage.cs monobehaviour!
     
    robinryf and elfasito like this.
  27. elfasito

    elfasito

    Joined:
    Jul 4, 2017
    Posts:
    14
    Thanks @IJsLauw
    I think I setted up all.
    but something is not working, I get this error:

    Could not get url for: gs://myproject.appspot.com/manual/Android/60b85ae8c2e7eea24fd73ba788f2bc04_scenes_laminacubo&esfera-addressable.bundle, System.AggregateException: One or more errors occurred. ---> Firebase.Storage.StorageException: Not Found. Could not get object Http Code: 404

    aparently is not getting the bundles but idk why, the url adress looks ok, except for the section in bold, Idk what is.
     
  28. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    Hi
    thank you for your feedback! I hope I can have a look in the next few days.

    @IJsLauw This is peculiar.. especially the mention to contact support. I don’t really know how to tackle this. Have you contacted support? Maybe if you can test it on a new or other firebase project it would be super interesting if it is not project specific

    @elfasito I will have a look. Can you maybe share the code you are using to load? And a screenshot of your Firebase Storage setup in the Firebase Console would help!
     
  29. IJsLauw

    IJsLauw

    Joined:
    May 31, 2015
    Posts:
    8
    @IJsLauw This is peculiar.. especially the mention to contact support. I don’t really know how to tackle this. Have you contacted support? Maybe if you can test it on a new or other firebase project it would be super interesting if it is not project specific.

    I've just contacted them to see what they can find out. The firebase project is brand new. Still I could try to setup another one, I haven't dealt with these yet so I don't know how easily they can break.

    Also I'm passing 2 labels to DownloadDependenciesAsync, and they seam to trigger a lot of StartUrlFetches, one for every file in the two assetGroups, is that the right behaviour and way to go to download the two bundles? I wonder of the downloads would even happen if I didn't have enough files in them. The first x seem to fail and after that they go through.

    The other strange thing is, this happens when I clear the cache or not, so even when the download size is 0. Does that make any sense to you? And after reporting the download size, it does start to receive data (or does fetching from cache also report progress?), albeit always starting from .75

    upload_2020-6-9_23-48-39.png

    upload_2020-6-9_23-53-49.png
     
  30. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    @IJsLauw
    If you have your Asset Groups set as "Pack seperately" then Unity will create a lot of bundles ( one foreach asset in the Addressables Group ) each of these triggers a StartUrlFetch so that seems to be correct.
    If you have the setting "Pack together" then only one StartUrlFetch should be done per Addressable Group. If that is the case that seems to be a bug. It would be nice to see what kind of URLs are fetched. (Like always the same ones, duplicates. Or variations)


    This may be a bit off-topic but Addressables only counts the amount of operations in the AsyncHandle and reports progress on that. So if you want to download two files. One is 1 MB and the other one 100GB big and Addressables finished to download the first file it will be at 50%/0.5 progress! So for your case a lot of little tiny operations finishing very quickly probably bring up the Progress really quick.
    One trick can be to make sure Addressables.InitializeAsync is finished before calling further Addressables calls. Because Addressables will add all these little Initialize tasks to the Progress (loading the catalog, converting keys, etc.) I hope this helps. If not, please make sure it is directly related to this plugin or open/search a thread on the Addressables forum.
     
  31. shkim7902

    shkim7902

    Joined:
    Feb 7, 2020
    Posts:
    1
    You are so smart guy!
    our project uses firebase storage. so really need to firebase addressables remote system.
    im really thanks to your plugin. your code was like a light to me.
    I also learned about Providers in Addressables.

    thank you robin~
     
    robinryf likes this.
  32. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    Hi Mortalyx,

    Interesting case. I have to admit I did not think about offline :/

    I created a branch for the project with offline support: https://gitlab.com/robinbird-studio...s/firebase-tools/-/tree/tech/offline-handling
    Branch Name: "tech/offline-handling"
    It basically saves the mapping from Addressable Locations to Firebase Storage locations in a format of your choice. Just set
    Code (CSharp):
    1. FirebaseAddressablesManager.PersistCache = true;
    If you kill the internet connection and restart the game, everything should be loaded from cache if it was downloaded to cache before.
    Can you please let me know if it works for your setup?

    Cheers, Robin
     
  33. Mortalyx

    Mortalyx

    Joined:
    Mar 20, 2015
    Posts:
    7
    Hi Robin,

    Thank you for your job! I didn't expect you will do so much after my feedback. I've even started creating my own tricky workaround solution with a manual asset bundle creation from the cached binary files o_O

    Currently, my project is in RC stage for public BETA testing. I'll try your solution and will let you know ASAP
     
  34. Mortalyx

    Mortalyx

    Joined:
    Mar 20, 2015
    Posts:
    7
    Soooo.... I have some results.

    My target platforms are iOS+Android and iOS is not able at the moment. So Editor and Android results.
    In Editor everything works fine! The only thing I can mention - the familiar error message. That's ok


    The android build gives me the same list of errors, but with 2 minutes delay after "Loading manifest". Seems like 2 minutes web request timeout.

     
  35. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    hmm, sorry that there are troubles and thank you for trying it out!

    Can you please describe your use case with an expected situation and user flow? I think we have different understandings on what to achieve here.

    Do you have your Manifest in a remote or local location?

    The flow I imagined would be:
    1. User installs app from App Store
    2. Opens App with Internet
    3. App downloads Addressables Manifest and Bundles and stores them in cache
    4. User kills the app
    5. User disconnects internet (tunnel or foreign country)
    6. User starts app without internet
    7. Addressable manifest and bundles are loaded from cache
    Does this flow match your understanding?

    Cheers
    Robin
     
  36. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    The two minutes timeout result from the "GetHash" request. Firebase API tries to retrieve the file and retries upon failure.

    You can set
    FirebaseStorage.DefaultInstance.MaxOperationRetryTime = TimeSpan.FromSeconds(myTime);
    to lower the timeout when Firebase gives up to get a new manifest version and gives Addressables the ok to load from cache. The default setting for this is actually 2 minutes. So precises measurements on your end! :D

    Cheers,
    Robin
     
    Last edited: Aug 1, 2020
  37. Mortalyx

    Mortalyx

    Joined:
    Mar 20, 2015
    Posts:
    7
    That's right. The manifest is in my remote location. But at that moment I didn't have any problem except 2 minutes delay on Android, which is FirebaseStorage issue =) Thanks for your reply!

    I have a new issue for you :D
    Have you ever tried the PreWarmDependencies function on iOS? I tend to feel this is my very specific issue. I git pulled my project to my mac and switched to iOS build platform. It works fine on iOS only if bundles are cached but clear cache causes errors In Editor it always shows this
     
  38. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    Usually I test everything on Android an iOS as much as time allows.

    This is interesting. You have an Asset that does not have an dependency asset. I don't have that in my test setup so thanks for finding it!
    For example Sprites have a dependency on a Texture2D to load from. So Addressables wants to load the Sprite and then first has to load the Texture in a chain.
    Could you have different Assets for iOS vs Android? Or some config files? But with this fix it should not matter and work:

    I fixed the NRE on the
    tech/offline-handling branch
    . Please give it a try if time allows you :)
     
  39. Mortalyx

    Mortalyx

    Joined:
    Mar 20, 2015
    Posts:
    7

    Yea, that works. I have addressables builds for iOS and Android. They should be in different bundles files (as always for bundles) but in general, they are the same. So it's a very strange NRE exception in this case.

    But it doesn't matter for now for me. I made stable builds for both platforms and my Android version is waiting for approving at Google Play while I'm finishing an iOS publishing at Testflight for open beta-testing =)

    Thanks a lot! Next steps are new bundles for paid assets. So I'll let you know if I have any issue with addressables update :D
     
    robinryf likes this.
  40. elfasito

    elfasito

    Joined:
    Jul 4, 2017
    Posts:
    14
    Hi robin, sorry for bother you again.
    I want to load addressable scenes in offline mode too.
    I update my previous project with the new tech/offline-handling branch.
    but not sure how implement it.
    I readed your new readme file, and added the line: FirebaseAddressablesManager.PersistCache = true;
    to my old InitFirebaseStorage.cs (from your example project).
    still not working in offline mode.
    I surely understood something wrong. can you please explain me?

    EDIT: okay, the problem was the "GetHash" request, I will lower the value from 2 minutes.
    Now is working.
     
    Last edited: Aug 18, 2020
  41. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    So it is working now?
    Nice

    yeah, that default setting from Firebase is strange. But mostly Firebase storage is not used for „background“ operations. So it makes sense

    cheers
     
    elfasito likes this.
  42. Paul_H23

    Paul_H23

    Joined:
    Jun 19, 2019
    Posts:
    39
    This is exactly the flow I'm trying to test at the moment, I posted a support request on this forum, https://forum.unity.com/threads/offline-behaviour-not-as-expected.953372/. I've been reading and just noticed this part of the thread. I have updated to the tech/offline-handling branch (at least I think I have, by adding #tech/offline-handling to the entry in the manifest.json as described here, https://docs.unity3d.com/Manual/upm-git.html#revision). However, this flow still doesn't work for me.

    I run the game (through XCode) while connected, and play through enough to ensure that at least some of the key assets are loaded. Then I shut down completely, and restart, again through XCode, although I've tried both ways, while in AirPlane mode, and it fails on the first request for an asset from a remote bundle that I would have expected to have been cached. I'm not getting the hash messages I mentioned in my other post, instead I'm getting InvalidKeyExceptions for the assets that I'm requesting that I would have expected to be in cache. I've set the flag described above.

    Code (CSharp):
    1. FirebaseAddressablesManager.PersistCache = true;
    2.  
    Any idea what might be going wrong, or how I can track down the error? Any and all help very much appreciated.
     
  43. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    Hi ☺️
    Sorry that you are having trouble with the offline cache...

    Do you have some log or error message? Hard to find out what is going on

    have you registers the
    public static Action<AsyncOperationHandle, Exception> ExceptionHandler { get; set; }

    Callback in ResourceManager?


    Cheers
     
  44. Paul_H23

    Paul_H23

    Joined:
    Jun 19, 2019
    Posts:
    39
    I haven't put an exception handler in, didn't know anything about that, I'll look into it and see if I can get more information about the error. The relevant error messages, that show directly after calling the "LoadAssetAsync" function that fails are below, with certain sensitive details redacted, it's quite long, as Apple error logs tend to be, hope that's not breaking any rules...

    2020-08-18 10:37:47.717147+0100 ###########[559:102395] [] nw_connection_get_connected_socket [C15] Client called nw_connection_get_connected_socket on unconnected nw_connection
    2020-08-18 10:37:47.717782+0100 ###########[559:102395] TCP Conn 0x2820ff9c0 Failed : error 0:50 [50]
    2020-08-18 10:37:51.071236+0100 ###########[559:102421] [] nw_connection_get_connected_socket [C16] Client called nw_connection_get_connected_socket on unconnected nw_connection
    2020-08-18 10:37:51.072075+0100 ###########[559:102421] TCP Conn 0x2820e0e40 Failed : error 0:50 [50]
    2020-08-18 10:37:53.729444+0100 ###########[559:102382] TIC TCP Conn Failed [17:0x2820e0e40]: 1:50 Err(50)
    2020-08-18 10:37:53.757787+0100 ###########[559:102382] Task <254E5517-80EB-4E6E-8C4E-10F31CC12E2C>.<4> HTTP load failed (error code: -1009 [1:50])
    2020-08-18 10:37:53.761504+0100 ###########[559:102378] Task <254E5517-80EB-4E6E-8C4E-10F31CC12E2C>.<4> finished with error - code: -1009
    2020-08-18 10:37:53.763392+0100 ###########[559:102378] Task <254E5517-80EB-4E6E-8C4E-10F31CC12E2C>.<4> load failed with error Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo={_kCFStreamErrorCodeKey=50, NSUnderlyingError=0x2819d36c0 {Error Domain=kCFErrorDomainCFNetwork Code=-1009 "(null)" UserInfo={_kCFStreamErrorCodeKey=50, _kCFStreamErrorDomainKey=1}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <254E5517-80EB-4E6E-8C4E-10F31CC12E2C>.<4>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalDataTask <254E5517-80EB-4E6E-8C4E-10F31CC12E2C>.<4>"
    ), NSLocalizedDescription=The Internet connection appears to be offline., NSErrorFailingURLStringKey=https://firebasestorage.googleapis....essables/iOS/catalog_2020.08.13.16.53.34.hash, NSErrorFailingURLKey=https://firebasestorage.googleapis....essables/iOS/catalog_2020.08.13.16.53.34.hash, _kCFStreamErrorDomainKey=1} [-1009]
    Could not load hash: System.AggregateException: One or more errors occurred. ---> Firebase.Storage.StorageException: An unknown error occurred
    --- End of inner exception stack trace ---
    ---> (Inner Exception #0) Firebase.Storage.StorageException: An unknown error occurred<---

    RobinBird.FirebaseTools.Storage.Addressables.FirebaseStorageHashProvider:<LoadManifest>b__2_0(Task`1)
    System.Action`1:Invoke(T)
    Firebase.Extensions.<ContinueWithOnMainThread>c__AnonStorey9:<>m__0()
    System.Func`1:Invoke()
    Firebase.<RunAsync>c__AnonStorey1`1:<>m__0()
    System.Action:Invoke()
    Firebase.ExceptionAggregator:Wrap(Action)
    Firebase.Dispatcher:pollJobs()
    Firebase.Platform.FirebaseHandler:Update()

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Exception encountered in operation Resource<Object>(catalog_2020.08.13.16.53.34.hash): One or more errors occurred.
    UnityEngine.AddressableAssets.AddressablesImpl:LogException(AsyncOperationHandle, Exception)
    System.Action`2:Invoke(T1, T2)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, String, Boolean)
    RobinBird.FirebaseTools.Storage.Addressables.FirebaseStorageHashProvider:<LoadManifest>b__2_0(Task`1)
    System.Action`1:Invoke(T)
    Firebase.Extensions.<ContinueWithOnMainThread>c__AnonStorey9:<>m__0()
    System.Func`1:Invoke()
    Firebase.<RunAsync>c__AnonStorey1`1:<>m__0()
    System.Action:Invoke()
    Firebase.ExceptionAggregator:Wrap(Action)
    Firebase.Dispatcher:pollJobs()
    Firebase.Platform.FirebaseHandler:Update()

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Exception encountered in operation Dependencies: One or more errors occurred.
    UnityEngine.AddressableAssets.AddressablesImpl:LogException(AsyncOperationHandle, Exception)
    System.Action`2:Invoke(T1, T2)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, String, Boolean)
    UnityEngine.ResourceManagement.AsyncOperations.GroupOperation:CompleteIfDependenciesComplete()
    System.Action`1:Invoke(T)
    DelegateList`1:Invoke(T)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
    UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    System.Action`1:Invoke(T)

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Exception encountered in operation Resource<ContentCatalogData>(catalog.json): Attempting to use an invalid operation handle
    UnityEngine.AddressableAssets.AddressablesImpl:LogException(AsyncOperationHandle, Exception)
    System.Action`2:Invoke(T1, T2)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, String, Boolean)
    UnityEngine.ResourceManagement.AsyncOperations.ProviderOperation`1:Execute()
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeExecute()
    System.Action`1:Invoke(T)
    DelegateList`1:Invoke(T)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
    UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    System.Action`1:Invoke(T)

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Exception encountered in operation UnityEngine.ResourceManagement.ResourceManager+CompletedOperation`1[UnityEngine.AddressableAssets.ResourceLocators.IResourceLocator], result='', status='Failed': Failed to load content catalog.
    UnityEngine.AddressableAssets.AddressablesImpl:LogException(AsyncOperationHandle, Exception)
    System.Action`2:Invoke(T1, T2)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, String, Boolean)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeExecute()
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Start(ResourceManager, AsyncOperationHandle, DelegateList`1)
    UnityEngine.ResourceManagement.ResourceManager:StartOperation(AsyncOperationBase`1, AsyncOperationHandle)
    UnityEngine.AddressableAssets.Initialization.InitializationOperation:OnCatalogDataLoaded(AddressablesImpl, AsyncOperationHandle`1, String)
    System.Func`2:Invoke(T)
    UnityEngine.ResourceManagement.ChainOperation`2:Execute()
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeExecute()
    System.Action`1:Invoke(T)
    DelegateList`1:Invoke(T)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
    UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    System.Action`1:Invoke(T)

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Exception encountered in operation Resource<ContentCatalogData>(catalog.json) - Chain<IResourceLocator,ContentCatalogData>: ChainOperation of Type: UnityEngine.AddressableAssets.ResourceLocators.IResourceLocator failed because dependent operation failed
    Failed to load content catalog.
    UnityEngine.AddressableAssets.AddressablesImpl:LogException(AsyncOperationHandle, Exception)
    System.Action`2:Invoke(T1, T2)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, String, Boolean)
    System.Action`1:Invoke(T)
    DelegateList`1:Invoke(T)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
    UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    System.Action`1:Invoke(T)

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Addressables - initialization failed.
    UnityEngine.AddressableAssets.Initialization.<>c__DisplayClass14_0:<LoadContentCatalogInternal>b__0(AsyncOperationHandle`1)
    System.Action`1:Invoke(T)
    DelegateList`1:Invoke(T)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
    UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    System.Action`1:Invoke(T)

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Exception encountered in operation UnityEngine.AddressableAssets.Initialization.InitializationOperation, result='', status='Failed': ChainOperation of Type: UnityEngine.AddressableAssets.ResourceLocators.IResourceLocator failed because dependent operation failed
    Failed to load content catalog.
    UnityEngine.AddressableAssets.AddressablesImpl:LogException(AsyncOperationHandle, Exception)
    System.Action`2:Invoke(T1, T2)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, String, Boolean)
    UnityEngine.AddressableAssets.Initialization.<>c__DisplayClass14_0:<LoadContentCatalogInternal>b__0(AsyncOperationHandle`1)
    System.Action`1:Invoke(T)
    DelegateList`1:Invoke(T)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
    UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    System.Action`1:Invoke(T)

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Exception encountered in operation UnityEngine.ResourceManagement.ResourceManager+CompletedOperation`1[UnityEngine.Texture2D], result='', status='Failed': Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown., Key=Backgrounds/##########, Type=UnityEngine.Texture2D
    UnityEngine.AddressableAssets.AddressablesImpl:LogException(AsyncOperationHandle, Exception)
    System.Action`2:Invoke(T1, T2)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, String, Boolean)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeExecute()
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Start(ResourceManager, AsyncOperationHandle, DelegateList`1)
    UnityEngine.ResourceManagement.ResourceManager:StartOperation(AsyncOperationBase`1, AsyncOperationHandle)
    UnityEngine.AddressableAssets.AddressablesImpl:LoadAssetAsync(Object)
    System.Func`2:Invoke(T)
    UnityEngine.ResourceManagement.ChainOperationTypelessDepedency`1:Execute()
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeExecute()
    System.Action`1:Invoke(T)
    DelegateList`1:Invoke(T)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
    UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    System.Action`1:Invoke(T)

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Exception encountered in operation UnityEngine.ResourceManagement.ResourceManager+CompletedOperation`1[UnityEngine.Texture2D], result='', status='Failed': Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown., Key=Backgrounds/##########, Type=UnityEngine.Texture2D
    UnityEngine.AddressableAssets.AddressablesImpl:LogException(AsyncOperationHandle, Exception)
    System.Action`2:Invoke(T1, T2)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, String, Boolean)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeExecute()
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Start(ResourceManager, AsyncOperationHandle, DelegateList`1)
    UnityEngine.ResourceManagement.ResourceManager:StartOperation(AsyncOperationBase`1, AsyncOperationHandle)
    UnityEngine.AddressableAssets.AddressablesImpl:LoadAssetAsync(Object)
    System.Func`2:Invoke(T)
    UnityEngine.ResourceManagement.ChainOperationTypelessDepedency`1:Execute()
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeExecute()
    System.Action`1:Invoke(T)
    DelegateList`1:Invoke(T)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
    UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    System.Action`1:Invoke(T)

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Exception encountered in operation UnityEngine.ResourceManagement.ResourceManager+CompletedOperation`1[UnityEngine.Texture2D], result='', status='Failed': Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown., Key=Backgrounds/##########, Type=UnityEngine.Texture2D
    UnityEngine.AddressableAssets.AddressablesImpl:LogException(AsyncOperationHandle, Exception)
    System.Action`2:Invoke(T1, T2)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, String, Boolean)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeExecute()
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Start(ResourceManager, AsyncOperationHandle, DelegateList`1)
    UnityEngine.ResourceManagement.ResourceManager:StartOperation(AsyncOperationBase`1, AsyncOperationHandle)
    UnityEngine.AddressableAssets.AddressablesImpl:LoadAssetAsync(Object)
    System.Func`2:Invoke(T)
    UnityEngine.ResourceManagement.ChainOperationTypelessDepedency`1:Execute()
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeExecute()
    System.Action`1:Invoke(T)
    DelegateList`1:Invoke(T)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
    UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    System.Action`1:Invoke(T)

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Exception encountered in operation UnityEngine.AddressableAssets.Initialization.InitializationOperation, result='', status='Failed' - Chain<Texture2D>: ChainOperation of Type: UnityEngine.Texture2D failed because dependent operation failed
    Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown., Key=Backgrounds/##########, Type=UnityEngine.Texture2D
    UnityEngine.AddressableAssets.AddressablesImpl:LogException(AsyncOperationHandle, Exception)
    System.Action`2:Invoke(T1, T2)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, String, Boolean)
    System.Action`1:Invoke(T)
    DelegateList`1:Invoke(T)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
    UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    System.Action`1:Invoke(T)

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Exception encountered in operation UnityEngine.AddressableAssets.Initialization.InitializationOperation, result='', status='Failed' - Chain<Texture2D>: ChainOperation of Type: UnityEngine.Texture2D failed because dependent operation failed
    Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown., Key=Backgrounds/##########, Type=UnityEngine.Texture2D
    UnityEngine.AddressableAssets.AddressablesImpl:LogException(AsyncOperationHandle, Exception)
    System.Action`2:Invoke(T1, T2)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, String, Boolean)
    System.Action`1:Invoke(T)
    DelegateList`1:Invoke(T)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
    UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    System.Action`1:Invoke(T)

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Exception encountered in operation UnityEngine.AddressableAssets.Initialization.InitializationOperation, result='', status='Failed' - Chain<Texture2D>: ChainOperation of Type: UnityEngine.Texture2D failed because dependent operation failed
    Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown., Key=Backgrounds/##########, Type=UnityEngine.Texture2D
    UnityEngine.AddressableAssets.AddressablesImpl:LogException(AsyncOperationHandle, Exception)
    System.Action`2:Invoke(T1, T2)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, String, Boolean)
    System.Action`1:Invoke(T)
    DelegateList`1:Invoke(T)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
    UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    System.Action`1:Invoke(T)

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Route RenderSection background finished Failed System.Exception: ChainOperation of Type: UnityEngine.Texture2D failed because dependent operation failed
    Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown., Key=Backgrounds/##########, Type=UnityEngine.Texture2D
    H23.RockJam.Routes.<>c__DisplayClass34_0:<RenderSection>b__0(AsyncOperationHandle`1)
    System.Action`1:Invoke(T)
    DelegateList`1:Invoke(T)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
    UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    System.Action`1:Invoke(T)

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Route preparation code failed
    H23.RockJam.Routes.<>c__DisplayClass4_0:<PostShow>b__1(Exception)
    System.Action`1:Invoke(T)
    RSG.<>c__DisplayClass45_0:<Catch>b__1(Exception)
    System.Action`1:Invoke(T)
    RSG.Promise:InvokeRejectHandler(Action`1, IRejectable, Exception)
    RSG.Promise:InvokeRejectHandlers(Exception)
    System.Action`1:Invoke(T)
    RSG.Promise:InvokeRejectHandler(Action`1, IRejectable, Exception)
    RSG.Promise:InvokeRejectHandlers(Exception)
    System.Action`1:Invoke(T)
    RSG.<>c__DisplayClass45_0:<Catch>b__1(Exception)
    System.Action`1:Invoke(T)
    RSG.Promise:InvokeRejectHandler(Action`1, IRejectable, Exception)
    RSG.Promise:InvokeRejectHandlers(Exception)
    System.Action`1:Invoke(T)
    RSG.Promise:InvokeRejectHandler(Action`1, IRejectable, Exception)
    RSG.Promise:InvokeRejectHandlers(Exception)
    System.Action`1:Invoke(T)
    RSG.<>c__DisplayClass45_0:<Catch>b__1(Exception)
    System.Action`1:Invoke(T)
    RSG.Promise:InvokeRejectHandler(Action`1, IRejectable, Exception)
    RSG.Promise:InvokeRejectHandlers(Exception)
    System.Action`1:Invoke(T)
    RSG.Promise:InvokeRejectHandler(Action`1, IRejectable, Exception)
    RSG.Promise:InvokeRejectHandlers(Exception)
    System.Action`1:Invoke(T)
    RSG.<>c__DisplayClass45_0:<Catch>b__1(Exception)
    System.Action`1:Invoke(T)
    RSG.Promise:InvokeRejectHandler(Action`1, IRejectable, Exception)
    RSG.Promise:InvokeRejectHandlers(Exception)
    System.Action`1:Invoke(T)
    RSG.Promise`1:InvokeHandler(Action`1, IRejectable, T)
    RSG.Promise`1:InvokeRejectHandlers(Exception)
    System.Action`1:Invoke(T)
    RSG.<>c__DisplayClass45_0:<Catch>b__1(Exception)
    System.Action`1:Invoke(T)
    RSG.Promise:InvokeRejectHandler(Action`1, IRejectable, Exception)
    RSG.Promise:InvokeRejectHandlers(Exception)
    System.Action`1:Invoke(T)
    RSG.Promise`1:InvokeHandler(Action`1, IRejectable, T)
    RSG.Promise`1:InvokeRejectHandlers(Exception)
    System.Action`1:Invoke(T)
    RSG.<>c__DisplayClass45_0:<Catch>b__1(Exception)
    System.Action`1:Invoke(T)
    RSG.Promise:InvokeRejectHandler(Action`1, IRejectable, Exception)
    RSG.Promise:InvokeRejectHandlers(Exception)
    System.Action`1:Invoke(T)
    RSG.Promise`1:InvokeHandler(Action`1, IRejectable, T)
    RSG.Promise`1:InvokeRejectHandlers(Exception)
    H23.RockJam.Routes.<>c__DisplayClass34_0:<RenderSection>b__0(AsyncOperationHandle`1)
    System.Action`1:Invoke(T)
    DelegateList`1:Invoke(T)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
    UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    System.Action`1:Invoke(T)

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Route RenderSection background finished Failed System.Exception: ChainOperation of Type: UnityEngine.Texture2D failed because dependent operation failed
    Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown., Key=Backgrounds/##########, Type=UnityEngine.Texture2D
    H23.RockJam.Routes.<>c__DisplayClass34_0:<RenderSection>b__0(AsyncOperationHandle`1)
    System.Action`1:Invoke(T)
    DelegateList`1:Invoke(T)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
    UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    System.Action`1:Invoke(T)

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    Route RenderSection background finished Failed System.Exception: ChainOperation of Type: UnityEngine.Texture2D failed because dependent operation failed
    Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown., Key=Backgrounds/##########, Type=UnityEngine.Texture2D
    H23.RockJam.Routes.<>c__DisplayClass34_0:<RenderSection>b__0(AsyncOperationHandle`1)
    System.Action`1:Invoke(T)
    DelegateList`1:Invoke(T)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
    UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    System.Action`1:Invoke(T)

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    2020-08-18 10:37:55.084293+0100 ###########[559:102378] [] nw_connection_get_connected_socket [C18] Client called nw_connection_get_connected_socket on unconnected nw_connection
    2020-08-18 10:37:55.089898+0100 ###########[559:102378] TCP Conn 0x2820ff9c0 Failed : error 0:50 [50]
    Returned to previous scene after failure.
    H23.Scenes.<>c__DisplayClass2_0:<DoSceneActivation>b__8()
    System.Action:Invoke()
    RSG.<>c__DisplayClass54_0:<Then>b__0()
    System.Action:Invoke()
    RSG.Promise:InvokeResolveHandler(Action, IRejectable)
    RSG.Promise:InvokeResolveHandlers()
    System.Action`1:Invoke(T)
    UnityEngine.AsyncOperation:InvokeCompletionEvent()

    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    2020-08-18 10:37:58.709392+0100 ###########[559:102379] [] nw_connection_get_connected_socket [C19] Client called nw_connection_get_connected_socket on unconnected nw_connection
    2020-08-18 10:37:58.709885+0100 ###########[559:102379] TCP Conn 0x2820fe580 Failed : error 0:50 [50]
    2020-08-18 10:38:06.382742+0100 ###########[559:102378] [] nw_connection_get_connected_socket [C20] Client called nw_connection_get_connected_socket on unconnected nw_connection
    2020-08-18 10:38:06.384109+0100 ###########[559:102378] TCP Conn 0x2820fe4c0 Failed : error 0:50 [50]
     
  45. robinryf

    robinryf

    Joined:
    May 22, 2014
    Posts:
    43
    Hi :)

    I saw your post, thank you. Currently I am short on time, sorry...

    From what I can see the Addressables cannot find your hash at: https://firebasestorage.googleapis....essables/iOS/catalog_2020.08.13.16.53.34.hash

    Looking at the file name with "2020.08.13.16.53.34" I guess this is the local time of the time of request? I don't think the cache system can handle this. Because this file name has not been cached. Probably when you had internet the offline cache cached something like "2020.08.13.15.30.23" and if you would request that it would work. I use a more "constant" filename for my hashes like: "catalog_v1_1_0.hash" which is bound to the binary version.

    This is just an assumption. I have to get back finding the exact cause in a few days.

    Cheers
     
  46. Paul_H23

    Paul_H23

    Joined:
    Jun 19, 2019
    Posts:
    39
    Hi,

    I've just checked and validated, the file catalog_2020.08.13.16.53.34.hash and .json both exist on Firebase Storage, and work fine when the network is connected, but when I disconnect, it can't load them from Firebase because, well, the network is disconnected. This is the situation where I would have expected it to use a locally cached copy of that file to resolve the assets. I fully expected it to fail to load the hash and json, because that's the test I'm trying to perform.

    Thanks for any help you can offer, much appreciated, I'm completely stalled on this at the moment.

    Cheers
     
  47. Paul_H23

    Paul_H23

    Joined:
    Jun 19, 2019
    Posts:
    39
    Hi,

    Any update on this? I'm still unable to get reliable behaviour under uncertain connection conditions.

    Cheers

    Paul
     
  48. Paul_H23

    Paul_H23

    Joined:
    Jun 19, 2019
    Posts:
    39
    I've looked into the code a bit myself, it looks like this can never work if the phone is offline at the start of play. As far as I can tell, the first thing it does is call through to LoadManifest on FirebaseStorageHashProvider to get the hash and if that fails, the whole AddressableAssets initialisation fails, so nothing will work. I'm trying to understand the code, but it looks to me like the only thing the offline caching supports is holding individual maps from resource identifier to URL. If the hash/catalog cannot be downloaded at the start, it will never use the cached entries, again, as far as I've been able to determine so far.

    Seems to me, the right thing to do is to cache the actual hash and/or catalog when it is first downloaded, and use the locally stored version in the LoadManifest calls on FirebaseStorageHashProvider and FirebaseStorageJsonAssetProvider if there is no internet connection, that's what I'd expect it to do. As it stands, it seems it's only useful if you've already requested an asset from the addressables database, and then you request the same asset later when offline, and then only if you were online at the time the game started.

    Can anyone confirm this?


    Paul
     
  49. abhi3188

    abhi3188

    Joined:
    Dec 13, 2015
    Posts:
    22
    Hey, I had a question. What exactly does this plugin do? Can I not simply add in my bucket url in the remote load path, upload my asset bundle to the firebase bucket and then use addressables api as I normally do?

    What additional advantages does using this plugin provide?
     
  50. Paul_H23

    Paul_H23

    Joined:
    Jun 19, 2019
    Posts:
    39
    I'm no Firebase expert, but my understanding is that the URI to a resource/bucket in Firebase Storage takes the form "gs://<bucket name>/<folder>/<file>", this is clearly not going to be accessible to the web request API in Unity, so it has to be converted to an https URI, via the Firebase Storage API. This plugin does that, uses the Firebase API to convert the gs:// URI to https:// and then passing it onto the Addressables system to download. It also does some other stuff, like caching manifest and hash information, that I'm less clear on.

    Paul
     
    abhi3188 likes this.
unityunity