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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Enumerating available addressables with label

Discussion in 'Addressables' started by AlanRStagner, Oct 25, 2019.

  1. AlanRStagner

    AlanRStagner

    Joined:
    Jan 9, 2018
    Posts:
    11
    Trying to get to grips with using the Addressable system with a pure ECS example RTS project I'm working on.
    Right now, scriptable object "FactionInfo" assets are used to define information about civilizations/factions (what units they use, etc) and then those are marked as addressable together with the Unit game object prefabs.

    All FactionInfo assets are marked with a "Factions" label, and all unit prefabs are marked with a "Units" label. At runtime, I have a bootstrap script which iterates available assets for both of these via something like:

    Code (CSharp):
    1. var getFactionsOp = Addressables.LoadResourceLocationsAsync("Factions");
    2. yield return getFactionsOp;
    And then loads each asset in the list and caches it in memory (in the case of FactionInfo, it just caches each loaded FactionInfo in a simple List, whereas in the case of Unit prefabs, it converts the prefab to a template Entity using the GameObjectConversionSystem and then caches a reference to the template entity so that it can just be cloned any time an entity of that type needs to be spawned).

    My question is, this seems like it will enumerate *all* assets for any bundles I build from the game using this Addressables window. Is there a good way I can modify or extend this to support "optional" content? Say, having extra bundles with new units & factions that aren't loaded by default, and have it skip over assets in those bundles until they're explicitly loaded by the game (could be useful for expansion packs for example?)
     
    mbussidk likes this.
  2. Favo-Yang

    Favo-Yang

    Joined:
    Apr 4, 2011
    Posts:
    464
    Please search for mergeMode, then you can leverage a main label and an optional label to filter assets based on your logic.
     
  3. AlanRStagner

    AlanRStagner

    Joined:
    Jan 9, 2018
    Posts:
    11
    Aaaah, got it! So I guess content in an optional bundle could be tagged with another label and I can just keep track of which label I need to query for based on what's loaded in. And then it looks like I can query for, say, factions in a particular bundle using something like

    Code (CSharp):
    1. var op = Addressables.LoadResourceLocationsAsync(new[] { "Factions", "ExpansionPackLabel"  }, Addressables.MergeMode.Intersection);
    2. yield return op;
    Although as far as I can tell I'll need to query for each bundle label separately if I'm using Intersection. Oh well, a simple for loop ought to work here. Thanks!
     
    lclemens likes this.
  4. RickSaada1

    RickSaada1

    Joined:
    Mar 9, 2015
    Posts:
    17
    This post was super useful for me, once I found it, so I'm going to add a few more details for anyone else who's trying to do this kind of thing. My situation was that I wanted to present a picker grid of images to the user, populated with all the images in the game that matched a certain criteria. So what I had to do to make this work with Addressables was this:

    First, I went to the AddressableAssetSettings object in the Assets->AddressableAssetsData directory. In the inspector, I found the Labels section, and added a new label to use to flag the things I wanted. In my case, "StoryEventPicture". Once this label has been created, it appears as an option in the Addressables window.

    Second, Open the Addressables window using Window->Asset Management->Addressables.
    Here you'll find all your addressable assets, arranged by whatever groups you've made, with columns for Asset Address, Path, and <Tada!> Labels. Each entry has a dropdown with a multiple selection list of the labels from the settings info. Kudos to the Unity team for making the asset list multiple selection! You can select all the appropriate assets and then set the label on them all at once.

    Third, Once you've done this, you'll need to build your addressable data via Build->Build Player Content.

    Now, in your code you can do something like this:
    Code (CSharp):
    1.  
    2.  
    3. // Load all the assets that are marked with the label “StoryEventPicture”
    4.  
    5.   AsyncOperationHandle loadHandle = Addressables.LoadResourceLocationsAsync("StoryEventPicture");
    6.         loadHandle.Completed += InitDialogWithImages;
    7.      
    8.  
    9. .........
    10. private void InitDialogWithImages(AsyncOperationHandle obj)
    11.     {
    12.         if (obj.Status == AsyncOperationStatus.Succeeded)
    13.         {
    14.             if (obj.Result != null)
    15.             {
    16.                 IList<IResourceLocation> list = obj.Result as IList<IResourceLocation>;
    17.                 foreach(IResourceLocation irl in list)
    18.                 {
    19.                     // Do stuff with  irl.PrimaryKey like:
    20.                     AsyncOperationHandle loadHandle = Addressables.LoadAssetAsync<Texture2D>(Item.Name);
    21.             loadHandle.Completed += Sprite_Loaded;
    22.                 }
    23.             }
    24.         }
    25.     }
    26. // This function gets called once for each of the assets we async loaded
    27.  
    28. public void Sprite_Loaded(AsyncOperationHandle obj)
    29.     {
    30.         if (obj.Status == AsyncOperationStatus.Succeeded)
    31.         {
    32.             if (obj.Result != null)
    33.             {
    34.                 Texture2D tex = obj.Result as Texture2D;
    35.                // Do something with the loaded texture
    36.                 Picture.sprite = Sprite.Create(tex, new Rect(0.0f, 0.0f, tex.width, tex.height), new Vector2(0.5f, 0.5f), 100.0f);
    37.             }
    38.         }
    39.     }
    40.  
    So we do one async operation to get all the matching assets, then we do another one per matching asset to load that asset, and finally as each async call returns we do something with each loaded asset. In my case I was stuffing them into a tilegrid in a listbox, but your usage may vary. Just knowing how to tag and retrieve this stuff at runtime is super helpful.
     
    Arkyn974, wlwl2, DotusX and 3 others like this.
  5. duartedd

    duartedd

    Joined:
    Aug 1, 2017
    Posts:
    148
    Is that code not returning duplicates for you?
     
  6. duartedd

    duartedd

    Joined:
    Aug 1, 2017
    Posts:
    148
    figured out why - its returning texture2d AND sprite
     
  7. duartedd

    duartedd

    Joined:
    Aug 1, 2017
    Posts:
    148
    Addressables.LoadResourceLocationsAsync("SpriteSheets", type).Completed I guess we cant grab only certain Types like the other methods - for instance: Addressables.LoadResourceLocationsAsync("SpriteSheets", Sprite).Completed
    or
    Addressables.LoadResourceLocationsAsync<Sprite>("SpriteSheets").Completed
     
  8. duartedd

    duartedd

    Joined:
    Aug 1, 2017
    Posts:
    148
    ended up using an if statement to weed out the texture2d objects

    if (irl.ResourceType.Name == "Sprite")
     
  9. Brad-Newman

    Brad-Newman

    Joined:
    Feb 7, 2013
    Posts:
    184
    @unity_bill I'd like to see more examples like this in the getting started part of the documentation. Only thing I've found that is similar is in the Space Shooter example: https://github.com/Unity-Technologies/Addressables-Sample/tree/master/Basic/SpaceShooter
     
    Sylmerria likes this.
  10. Brad-Newman

    Brad-Newman

    Joined:
    Feb 7, 2013
    Posts:
    184
    Had same issue, figured out how to get the locations for only sprites with this code:

    Code (CSharp):
    1. AsyncOperationHandle op = Addressables.LoadResourceLocationsAsync("sprites",typeof(Sprite));
     
    DotusX likes this.
  11. zyc_dc

    zyc_dc

    Joined:
    May 11, 2018
    Posts:
    42
    I found I could not load single sprites. Addressables.LoadResourceLocationsAsync only returns one location which is a texture 2d.
     
  12. cathalmcd

    cathalmcd

    Joined:
    Jul 15, 2019
    Posts:
    5
    Hi, Is there a way we can get all the label names from the addressables from scripts.
     
    lclemens likes this.
  13. JasperCiti

    JasperCiti

    Joined:
    Jul 5, 2013
    Posts:
    17
    This is all good and well, but once we got the results back is there a way to determine which asset was loaded by which label or do we need to re-query the Addressables for each label one by one?
     
  14. MegatronusV

    MegatronusV

    Joined:
    May 2, 2020
    Posts:
    16
    Code (CSharp):
    1. var labels = AddressableAssetSettingsDefaultObject.Settings.GetLabels();
    this should get you all the labels.
     
    snowinrain, Pleija and DotusX like this.