Search Unity

Can I ask Addressables if a specified key (addressable name) is valid?

Discussion in 'Addressables' started by chanon81, Oct 25, 2018.

  1. chanon81

    chanon81

    Joined:
    Oct 6, 2015
    Posts:
    92
    Hello,

    I'm porting a game from another game engine to Unity.

    In the previous engine, I would check the file system and ask it whether certain textures exist at a specified file path, and if they don't, then fall back to another one.

    So what I would like is something like:
    Code (CSharp):
    1. Addressables.IsKeyValid("Powers/PowerLevel_2");
    and then if it isn't valid and Powers/PowerLevel_1 is, then I'd fallback to using Powers/PowerLevel_1.

    Is something like this possible?
     
  2. chanon81

    chanon81

    Joined:
    Oct 6, 2015
    Posts:
    92
    OK, from looking at the Addressables source code, I see that I can use
    Addressables.ResourceLocators
    for this.

    This is what I got:
    Code (CSharp):
    1.  
    2. public bool AddressableResourceExists(object key) {
    3.     foreach (var l in Addressables.ResourceLocators) {
    4.         IList<IResourceLocation> locs;
    5.         if (l.Locate(key, out locs))
    6.             return true;
    7.     }
    8.     return false;
    9. }
    10.  
    Then when using I need to make sure that Addressables has been initialized first. Eg.

    Code (CSharp):
    1.  
    2. Addressables.Initialize().Completed += (op) => {
    3.     string key;
    4.     key = "My/Texture.png";
    5.     Debug.Log("Resource exists for " + key + " = " + AddressableResourceExists(key));
    6. };
    7.  
     
  3. unity_bill

    unity_bill

    Unity Technologies

    Joined:
    Apr 11, 2017
    Posts:
    954
    What you have above probably could work. But the thing I would actually recommend is to just do Addressables.LoadAsset<IResourceLocation>("key");

    This will not load your asset, but will load the location that points to your asset. If your key is valid, then you'll get a valid location back. Otherwise you will not. You can keep and use that location (doing LoadAsset<GameObject>(myNewLocation)) or you can just discard it and continue to load with key once needed.

    -Bill
     
    chanon81 likes this.
  4. Rafarel

    Rafarel

    Joined:
    Jul 21, 2017
    Posts:
    146
    @unity_bill how can I do that please ?


    I've done this but it isn't working :

    Code (CSharp):
    1.  
    2. var asyncKeyExists = Addressables.LoadAsset<IResourceLocation>(key);
    3.  
    4. if (asyncKeyExists.Status == AsyncOperationStatus.Failed)
    5. {
    6.     Debug.LogError("TurretsManager can't preload " + key + " this key does not exists!");
    7. }
    8.  
    9.  
    Thanks for your help!
     
  5. unity_bill

    unity_bill

    Unity Technologies

    Joined:
    Apr 11, 2017
    Posts:
    954
    In the soon-to-be-released 0.7.x, you can use a dedicated interface for this: `LoadResourceLocations`. I don't particularly like the name. It should probably be GetResourceLocations, but haven't had time to change that. so fair warning, it may get renamed going into 0.8.x
     
    marcianosd and Rafarel like this.
  6. d_grass

    d_grass

    Joined:
    Mar 6, 2018
    Posts:
    11
    @unity_bill
    Hello,
    I am trying right now to check if the location that points to the asset is available.
    Unfortunatly Addressables.LoadAsset<IResourceLocation>("key"); does not work anymore in 7.5.

    Error Log Shows:
    Exception encountered in operation Resource<IResourceLocation>(2019-001-020749.prefab)

    I also tried Addressables.LoadResourceLocations(key).Status == UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationStatus.Succeeded but it is always false.

    Could it be possible that it isnt checked synchronusly and if its the case, how can i archive a check that an key is available?

    I would be grateful to you if you have an solution.
     
  7. senfield

    senfield

    Joined:
    Apr 1, 2019
    Posts:
    22
    If you get a reference to a catalog (an IResourceLocator) then you can iterate through its .Keys and check for a match. I believe you can get to the active set of IResourceLocator(s) from Addressables.ResourceLocators.
     
  8. d_grass

    d_grass

    Joined:
    Mar 6, 2018
    Posts:
    11
    The Amount of ResourceLocators in Addressables.ResourceLocators is 0. But i can load Adressables how is this possible?
     
    Last edited: May 10, 2019
  9. senfield

    senfield

    Joined:
    Apr 1, 2019
    Posts:
    22
    It sounds like the Addressables system might not be done initializing when you are asking for the length.
    If I ask for the Count after initialization has finished I do get 1.
     
  10. senfield

    senfield

    Joined:
    Apr 1, 2019
    Posts:
    22
    The loading routines for addressables are all setup to wait for initialization to complete.
    E.g.
    public AsyncOperationHandle<TObject> LoadAsset<TObject>(object key)
    {
    if (!InitializationOperation.IsDone)
    return LoadAssetWithChain<TObject>(key);

    That's why your loads work... they are simply waiting patiently for the initialize callback.
    You can manually initialize addressables with something like Addressables.Initialize().Completed += yourCallback;
     
  11. unity_bill

    unity_bill

    Unity Technologies

    Joined:
    Apr 11, 2017
    Posts:
    954
    This is an async operation. So you need to do Addressables.LoadResourceLocations(key).Completed += whatever. Then check status. If that doesn't work, please let me know.
     
  12. d_grass

    d_grass

    Joined:
    Mar 6, 2018
    Posts:
    11
    @unity_bill & @senfield Thank you for your support, that helped me a lot and cleared things up. In particular initialize missed for me. Sorry that I bothered you with that.
     
    unity_bill likes this.
  13. marcianosd

    marcianosd

    Joined:
    Nov 6, 2018
    Posts:
    3
    Hello @unity_bill.

    When Addressables.LoadResourceLocationsAsync(address) is called and the address is not found, is it supposed to throw an exception? Or is it supposed to complete with AsyncOperationStatus.Failed?

    Currently, it's throwing an exception. I remember that it was the other case back when it was still Addressables.LoadAsset<IResourceLocation>(address). Just wondering if that is the correct behavior moving forward.

    Thanks!
     
  14. unity_bill

    unity_bill

    Unity Technologies

    Joined:
    Apr 11, 2017
    Posts:
    954
    We're planning to remove that exception to make LoadResourceLocationsAsync be a safe & easy way to validate an address or label.
     
  15. marcianosd

    marcianosd

    Joined:
    Nov 6, 2018
    Posts:
    3
    Hi @unity_bill ,

    Thank you for your response.

    I've just updated to 1.1.4, and according to the changelogs for 1.1.3, there's this line:
    • Made LoadResourceLocations no longer throw an exception if given unknown keys. This method is the best way to check if an address exists.
    But upon testing (as of 1.1.4), LoadResourceLocationsAsync still throws an exception when:
    • passing a single unknown key
    • passing a list where all keys are unknown (lists work if there is at least 1 known key)
    Are there prior steps that need to be done for this to work?

    Thanks!
     
    NickZhao, DanielGamaga and chanon81 like this.
  16. unity_bill

    unity_bill

    Unity Technologies

    Joined:
    Apr 11, 2017
    Posts:
    954
    Is it the InvalidKeyException? Looking through the code I'm not sure how this could happen, and this is specifically what we fixed. Perhaps you could debug or add some logging to the code to see where this get's thrown? There are only a few spots where we throw it.

    If it's a different exception, then knowing which one would help.
     
    marcianosd likes this.
  17. marcianosd

    marcianosd

    Joined:
    Nov 6, 2018
    Posts:
    3
    my bad. they were Error Logs and i got Error Pause on.
     
    Last edited: Jul 18, 2019
    unity_bill likes this.
  18. funbites

    funbites

    Joined:
    Oct 9, 2015
    Posts:
    7
    I'm using Unity 2019.2.3f1 and Addressables 1.2.2 and I'm getting InvalidKeyException.

    Code (CSharp):
    1.  
    2. Addressables.LoadAssetAsync<GameObject>(lastLoadedSceneName).Completed += OnCompleteLoading;
    3.  
    Exception encountered in operation UnityEngine.ResourceManagement.ResourceManager+CompletedOperation`1[UnityEngine.GameObject], result='', status='Failed': Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown., Key=ALICE_01_A_MAOS_ALGEMADAS
    UnityEngine.AddressableAssets.Addressables:LoadAssetAsync(Object)
    Funbites.GudeInk.Core.LoadSceneFunction`1:OnCall(LineTag[]) (at Assets/_GUDE_CORE/Scripts/Story/ContextFunctions/LoadSceneFunction.cs:38)
     
  19. peeka

    peeka

    Joined:
    Dec 3, 2014
    Posts:
    31
    I don't want exception to Log into player.log when pack doesn't exist, I am using LoadResourceLocationsAsync, but it logs the file name and everything to player.log.

    in my addressableassetsettings I have Log Runtime Exceptions unchecked, but it still log the exception..

    I am on aa 1.2.4
     
    joaobsneto and funbites like this.
  20. joaobsneto

    joaobsneto

    Joined:
    Dec 10, 2009
    Posts:
    146
    Same here. No updates so far?
     
  21. unity_bill

    unity_bill

    Unity Technologies

    Joined:
    Apr 11, 2017
    Posts:
    954
    to be clear, the original post was about LoadResourceLocationsAsync, which will not throw an exception if the key is unknown.

    LoadAssetAsync (which is what your code is calling) will and should throw an InvalidKey exception if it does not recognize the key. So whatever you are passing in as "lastLoadedSceneName" is not actually an addressable thing.
     
  22. joaobsneto

    joaobsneto

    Joined:
    Dec 10, 2009
    Posts:
    146
    I understand, but a system that is based on string values, a typo or a missing address may happen in production. So, should I always ask for Location and then ask for the asset itself?