Search Unity

Question Get RemoteLoadPath at runtime?

Discussion in 'Addressables' started by Noblauch, Jan 29, 2021.

  1. Noblauch

    Noblauch

    Joined:
    May 23, 2017
    Posts:
    275
    I know I can get the remote location in the editor via:
    AddressableAssetSettings.RemoteCatalogLoadPath.GetValue(AddressableAssetSettings)

    but I can't find a point in the source code how to find this address at runtime. If I follow the public method it seems like this location is only resolved via the resource location of a specific asset.

    I don't have a specific asset to get this path from, I need to get the path from what I've configured in the Addressables Profile settings, that the app shipped with.
     
    Last edited: Jan 29, 2021
  2. Noblauch

    Noblauch

    Joined:
    May 23, 2017
    Posts:
    275
    Hm, there must be a way to get this string right?
    I still haven't been able to find a way to get the remote server location from the system :( Anyone?
     
  3. Noblauch

    Noblauch

    Joined:
    May 23, 2017
    Posts:
    275
    If this is not possible (which is nuts), I will have to add a script that writes the URL into a file at build and then read it at runtime, which would be yet another workaround to get the Addressables package to work..
    So this is my last bump.

    Unity? Anyone?
     
  4. TreyK-47

    TreyK-47

    Unity Technologies

    Joined:
    Oct 22, 2019
    Posts:
    1,820
    I'll bounce this off the team for some guidance!
     
    Noblauch likes this.
  5. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    763
    So, it's not exactly the most straightforward thing to do but it is possible. Basically you need to load the built in ResourceManagerRuntimeData and then check the property CatalogLocations. The [0] index should always be the remote location. Let me clarify, the location will point to a .hash file. What you probably want is the .json catalog location so just replace the .hash with .json to point to the actual catalog.

    Code (CSharp):
    1. string playerSettingsLocation = Addressables.ResolveInternalId(PlayerPrefs.GetString(Addressables.kAddressablesRuntimeDataPath, Addressables.RuntimePath + "/settings.json"));
    2.  
    3.         var text = File.ReadAllText(playerSettingsLocation);
    4.         ResourceManagerRuntimeData rtdRuntime = JsonUtility.FromJson<ResourceManagerRuntimeData>(text);
    5.  
    6.         var remoteCatalogLocation = rtdRuntime.CatalogLocations[0].InternalId.Replace(".hash", ".json");
    7.  
    8.         //var remoteCatalogLocation = rtdRuntime.CatalogLocations.First(loc => loc.InternalId.StartsWith("http://"))
    9.         //    .InternalId.Replace(".hash", ".json");
    I've thrown in the commented out section in case you'd rather find the remote path that way instead of relying on the 0 index.

    One other option is to use the Addressables.TransformInternalIdFunc. You can use this to see paths as Addressables requests assets (catalogs, AssetBundles, etc.). You could look for a remote catalog location to come through this func and then do whatever you need with it. Something akin to this:

    Code (CSharp):
    1. Addressables.InternalIdTransformFunc += location =>
    2.         {
    3.             if (location.InternalId.StartsWith("http://") && location.InternalId.EndsWith(".json"))
    4.             {
    5.                 //Do something with remote catalog location.
    6.             }
    7.  
    8.             return location.InternalId;
    9.         };
    Full disclosure this code is untested so you may need to tweak it for your specific situation. I hope this helps.
     
    won-gyu, bbbottle and Noblauch like this.
  6. Noblauch

    Noblauch

    Joined:
    May 23, 2017
    Posts:
    275
    Okay, today I got the chance to test this approach.
    Unfortunately, the remoteCatalogLocation variable will resolve into:
    {UnityEngine.AddressableAssets.Addressables.RuntimePath}/catalog.json


    I was not able to find a way to convert this variable into a valid address yet.
     
  7. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    763
    Hopefully this is what you're looking for but if you feel that string "{UnityEngine.AddressableAssets.Addressables.RuntimePath}/catalog.json" into
    Addressables.ResolveInternalId
    it should give you what you're looking for. Let me know if it doesn't.
     
  8. Noblauch

    Noblauch

    Joined:
    May 23, 2017
    Posts:
    275
    Thank you, I was able to get something resolved, this is my final code that worked somewhat:
    Code (CSharp):
    1. string runtimeData = PlayerPrefs.GetString(Addressables.kAddressablesRuntimeDataPath, Addressables.RuntimePath + "/settings.json");
    2. string playerSettingsLocation = Addressables.ResolveInternalId(runtimeData);
    3. string playerSettingsFile = File.ReadAllText(playerSettingsLocation);
    4. ResourceManagerRuntimeData rtdRuntime = JsonUtility.FromJson<ResourceManagerRuntimeData>(playerSettingsFile);
    5. string assetLocation = rtdRuntime.CatalogLocations[0].InternalId.Replace(".hash", ".json");
    6. string assetLocationURL = Addressables.ResolveInternalId(assetLocation);
    I didn't realise that I would have to utilize Addressables.ResolveInternalId two times, and using it on "{UnityEngine.AddressableAssets.Addressables.RuntimePath}/catalog.json" seemed like it wouldn't work anyway.

    But: I'm still not getting the remote URL, but "Library/com.unity.addressables/aa/iOS/catalog.json" even though:
    - The correct profile with the real RemoteLoadPath URL is selected
    - Addressables were build again
    - Playmode Script is set to existing build

    But it seems like this issue maybe related to my latest bug issue on the package, didn't test it in a build yet.
     
    Last edited: Apr 19, 2021
  9. Noblauch

    Noblauch

    Joined:
    May 23, 2017
    Posts:
    275
    Well, I reverted my Unity and Addressable versions, to make sure this wasn't the issue. I tried everything, but I can't get the URL.
    To be sure, I simply need this URL:
    RemoteLoadPath.png
    Nothing more, nothing less.

    I tried:
    Addressables.ResolveInternalId(ResourceManagerRuntimeData.CatalogLocations[0].InternalId)

    Addressables.ResolveInternalId(ResourceManagerRuntimeData.CatalogLocations[0].Provider)

    Addressables.ResolveInternalId("{UnityEngine.AddressableAssets.ResourceProviders.ContentCatalogProvider}")

    Addressables.ResolveInternalId("{RemoteLoadPath}")


    I have no idea how this is supposed to work.
    The closest I'v gotten is a result of "Library/com.unity.addressables/aa/iOS/catalog.json" as stated above. But other than the fact that it seemed to resolve anything at all, this is far from what I'm looking for.
     
    Last edited: Apr 19, 2021
  10. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    763
    If you step through your code can you check rtdRuntime.CatalogLocations and see what that list looks like? The catalog location order should be deterministic but perhaps it isn't See if any of those CatalogLocations contain the remote location you're looking for. I just tested your code exactly as it is in my project and it got me the remote load path.

    Also, if you see less than 3 entries in the CatalogLocations double check that Build Remote Catalogs has been turned on and you've rebuilt your Addressable data after turning it on (I figure it probably is but I wanted to mention it just in case).

    As a potential workaround you might want to set the remote location to a PlayerPrefs as part of your build
    Code (CSharp):
    1. PlayerPrefs.SetString("myremotelocation", AddressableAssetSettings.RemoteCatalogLoadPath.GetValue(AddressableAssetSettings));
    and then you should be able to retrieve that at runtime using
    PlayerPrefs.GetString
    which, of course, isn't ideal and I'll open a ticket because this shouldn't be this difficult. There's definitely some quality of life improvements we can make here. But this might help you in the meantime.
     
    Noblauch likes this.
  11. Noblauch

    Noblauch

    Joined:
    May 23, 2017
    Posts:
    275
    Aha! Due to our use case and issues with the vanilla functionality, we had to disable the Remote Catalog (which is actually the very reason why we need the remote location). If I enable it and rebuild, it appears in the rtdRuntime.CatalogLocations.

    Since we have it disabled, this is everything I get:
    CatalogLocations.png

    And I was trying and trying to convert
    {UnityEngine.AddressableAssets.Addressables.RuntimePath}
    to the server url somehow, yikes.

    Hm, however, since this server variable is a global define, that is definitely used inside the Build, it would be great if we could access it in runtime. Something like Addressables.Profile.GetValue("RemoteLoadPath").

    Since we changed some behaviour and merging in our local groups and still have problems with our update workflow, we will try one last time next month to see if we can get the system to work for our use-case (multiple apps / same remote bundles).

    If there is any possibility to get support for the Addressables Package that Unity can offer, we would highly appreciate any guidance. The success Team can't help us, and I already created numerous posts in the forum that show the limitations we run into. Our use case of the system is kind of extensive, and I bet it would be interesting for the Addressables Dev-Team as well to see how a production like ours is going about using it – and hitting limitations.

    PS: I didn't know that PlayerPrefs saved in the editor, are available in the build, interesting.
     
  12. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    763
    Hey, I'm glad you got it figured out!

    I don't have the full context but regarding your "different apps/same bundles" situation I'd recommend looking into
    Addressables.LoadContentCatalogAsync
    . You may have already done so. In my mind the setup looks like this:
    - Project A: Houses the actual assets and builds the remote AssetBundles
    - Project B: Uses remote bundles from Project A
    - Project C: Also uses remote bundles from Project A

    Now, for Project A you'd build your remote catalogs and AssetBundles like normal, no issue there. You might want to take advantage of the Player Version Override in Project A. Normally a remote catalog is going to be named something like catalog_2021.9.3.2.4.json or whatever. If you put in a string in the Player Version Override, lets say "abc" the remote catalog will be named catalog_abc. It'll always be "catalog_abc" which is useful for your dependent projects.

    For Projects B and C you can do this however makes sense for your project but you basically want to construct the url to the remote catalog created by Project A. The Player Version Override is useful because you don't have to try and save/reconstruct a time stamp to add to your URL. You have a static string that you already know.

    Once you have the remote path constructed, pass that into
    Addressables.LoadContentCatalogAsync
    and those projects should now download and use those AssetBundles like any other project. Of note: make sure these apps are only downloading bundles built for their specific platform. This might mean that you need to divide up builds on your CDN into different folders based on the platform and use that in the construction of your URL.

    Re: PlayerPrefs at Runtime - I'm pretty sure you can. I don't use it much but I'm almost positive that that's a thing. I might be mistaken though.

    I hope some of this helps. If you have more questions/concerns about multi project set ups feel free to make a new thread. It helps me and our community team keep track of issues
     
    Noblauch likes this.
  13. emerge-sjh

    emerge-sjh

    Joined:
    Oct 16, 2020
    Posts:
    14
    Any update on this? It'd super useful to resolve paths at runtime
     
    tylo likes this.
  14. hejalejandro

    hejalejandro

    Joined:
    Oct 26, 2021
    Posts:
    5
    +1. its a bit absurd that there isnt yet a sensible way of checking paths in runtime...
     
  15. peter_unity996

    peter_unity996

    Joined:
    May 5, 2021
    Posts:
    2
    I'm also having issues with addressable profiles not reflecting what I've set in the editor. Currently the only way to verify I'm pointing to the correct RemoteLoadPath is catching any exceptions from failed downloads. It would be super useful to log which profile/loadPath the build is using to catch this earlier.
     
  16. Mehlian

    Mehlian

    Joined:
    Jun 7, 2021
    Posts:
    6
    bump!
     
  17. bbbottle

    bbbottle

    Joined:
    Dec 1, 2022
    Posts:
    1
    The first option works for me.