Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Bug (Case 1260305) Asset location dependencies always treated as asset bundles?

Discussion in 'Addressables' started by dlegare-synapse, Jul 1, 2020.

  1. dlegare-synapse

    dlegare-synapse

    Joined:
    Jan 17, 2018
    Posts:
    54
    I'm experimenting with a custom Addressables extension in order to directly load sprites from sprite atlases by name (i.e. without needing to specify the address of the atlas that contains the sprite). To do this, I am using some custom build scripts to generate additional catalog entries for each sprite that is contained within an atlas. This approach seems to be working well for my custom versions of
    BuildScriptFastMode
    , however with
    BuildScriptVirtualMode
    and
    BuildScriptPackedMode
    I'm running into some issues. Specifically, when I create custom catalog data entries that depend on the
    SpriteAtlas
    asset, in multiple places the Addressables system seems to assume that all dependencies for catalog entries/resource locations are asset bundles.

    Addressables Version: 1.10.0 (I've also tested somewhat on 1.11.2 and had similar issues, but most of my investigation has been done using 1.10.0)
    Unity Version: 2019.3.11f1

    Current Setup

    My custom build scripts do roughly the following to add additional catalog entries for each sprite in an addressable sprite atlas:

    Code (CSharp):
    1. aaContext.locations.Add(new ContentCatalogDataEntry(
    2.     typeof(Sprite),
    3.     spriteName,
    4.     typeof(AddressableAtlasSpriteProvider).FullName,
    5.     new object[] { spriteName },
    6.     new object[] { atlasEntry.CreateKeyList()[0] }));
    7.  
    (Link to source code)

    This gives each sprite a (hopefully) unique address and marks the sprite entry as depending on the atlas entry.
    AddressableAtlasSpriteProvider
    (source code) then knows to load the first dependency as a
    SpriteAtlas
    and load the sprite by name from the atlas.

    Downloading Dependencies

    I've confirmed that I can do
    Addressables.LoadAssetAsync<Sprite>("my_sprite")
    and successfully load the sprite. However, if I do
    Addressables.DownloadDependenciesAsync("my_sprite")
    I get an error about the atlas failing to load:

    Code (text):
    1. Exception: ChainOperation of Type: System.Collections.Generic.IList`1[UnityEngine.ResourceManagement.ResourceProviders.IAssetBundleResource] failed because dependent operation failed
    2. Unable to load asset of type UnityEngine.ResourceManagement.ResourceProviders.IAssetBundleResource from location Assets/Art/Sprites/my_atlas.spriteatlas.
    The failing operation that gets logged is an attempt to load
    my_atlas.spriteatlas
    as an object of type
    IAssetBundleResource
    ; Effectively, it's trying to load the sprite atlas as an asset bundle, which doesn't work.

    I did some digging into the Addressables source code to track down why this was happening. As far as I can tell,
    AddressablesImpl.DownloadDependenciesAsync()
    will always attempt to load all dependencies of the specified key as
    IAssetBundleResource
    without checking the actual provider type for the dependencies.

    This seems like a bug to me, but I can't be entirely certain. Is there anyone who's more familiar with the Addressables internals that can either confirm if this is a bug or if there's something I'm doing wrong in my setup? I intend to continue to investigate this on my end, but I appreciate any help anyone can offer!
     
  2. TreyK-47

    TreyK-47

    Unity Technologies

    Joined:
    Oct 22, 2019
    Posts:
    1,816
    dlegare-synapse likes this.
  3. dlegare-synapse

    dlegare-synapse

    Joined:
    Jan 17, 2018
    Posts:
    54
  4. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    762
    Hey @dlegare-synapse so, having location dependencies point to asset bundles has always been the expected behavior. This is because generally if an asset is loaded, lets say a Cube prefab, from AssetBundleA and it has a reference to a material in AssetBundleB we don't need to know the exact asset that our Cube references. We just know we need AssetBundleB loaded and from there the Cube will be able to get the desired material.

    For these sprite locations you really should only need a dependency on the bundle the atlas is in. Let me know if this doesn't work for you.
     
    dlegare-synapse likes this.
  5. dlegare-synapse

    dlegare-synapse

    Joined:
    Jan 17, 2018
    Posts:
    54
    Ah, that's good to know! That's potentially a problem for the case I'm trying to setup, where the idea is to assign an asset location to a sub-asset. My idea was to track the main asset as a dependency of the location, but if that won't work I'll have to find some other workaround.

    Fortunately, I've done some more digging since writing this original post and it looks like I may not need this custom setup at all, since it looks like you don't actually get any texture duplication if you mark both a sprite and an atlas that contains the sprite as addressable. If that proves to be the case, then I shouldn't need to deal with this custom workaround at all.

    @DavidUnity3d Thanks for confirming the intended behavior for me, though! That will be helpful to know if I end up revisiting this approach :)
     
    davidla_unity likes this.