Addressables is not grasp SpriteAtlas dependencies

Hello!
Now I have problem When I include a Sprite and an Atlas in Addressables and build,
In my think, only to include atlased texture in AssetBundle, But the real behavior also include unatlased texture.
Is it supposed to work?

I’m not sure I see what you’re saying. It looks like you’ve made Unity.png as addressable. Which adds the actual texture, and the sprite object to the bundle. You’ve also made “new sprite atlas” addressable, which adds the generated texture, and the atlas object data to the bundle.

What is in the atlas? Unity.png or something else? If it’s Unity.png you can’t mark a sprite addressable and expect to load it out of an atlas. You have to just have the atlas as addressable. If Unity.png is not in the atlas, then I’m not exactly sure what you’re asking.

Sorry to my lack of Information.
Atlas in only to include Unity.png and actual usage is resolve dependencies SpriteAssetReference.
In my think that pattern only to include SpriteData(All Sprite data without Texture)but constract data is include Sprite TextureData.

I’m not good at English so I put it together in the diagram


This is what I wanted to convey.
If you don’t know what I’m saying ,I will tell you in addition.
Thank you for your support.

If you have a sprite in the editor, and you mark it as addressable, and load it at runtime, it is it’s own thing. It has no idea if you happened to also include it in a SpriteAtlas. Similarly, if you load a SpriteAtlas, and then get the sprite out of it (GetSprite or GetSprites, see Unity - Scripting API: SpriteAtlas) you’ll get the sprite that’s contained inside the SpriteAtlas, and it has no idea if you happened to have included the original source in the build.

I’ve altered your drawing to match what actually happens. You have two things you can reference from code. They are independent. At runtime, a SpriteAtlas is not dependent on the source sprite. It sucked in all the info it needed during the build.

Supposed I have my entire GUI in an addressable scene and this scene refers sprites through the “Image” component. Furthermore, all sprites are included in an atlas that is addressable. At runtime, after loading the atlas, the GUI uses the atlas texture as expected. However, due to the scene refering a sprite that is a sub-asset of the sprite texture, the sprite texture has to be included in an asset group as well in order to satisfy the dependency.

What is the best way to handle this situation when it comes to UGUI using sprites?

While this makes sense from an asset management level, this does not make sense from a Unity 2D workflow level. The sprites in the 2D workflow (whether for UGUI or 2D) use the sprite references when dragging references into the SpriteRenderer or UI.Image components. They never use the atlas that the sprite is built into. Expecting artists and designers to change up their workflow for addressables should not be an acceptable solution.

This is a pretty big miss by the addressable team for not knowing this. Please consider adding an asset reference that will respect the sprite’s atlased state so it knows how to load it and can accept Sprite references correctly.

7 Likes

I wonder if there is anything on the roadmap to tackle this design flaw. If I understand it correctly, this is more related to Unity itself than AAS. As a solution, for example, a SpriteAtlas could generate sprites as sub-assets similar to single or multi sprite textures. When referring SpriteAtlas sub-assets only, the original sprite textures could be excluded from the asset bundle completely.

I’m thinking of writing some kind of post-processing script that automatically resolves sprite references in all scenes by deleting them and attaching a component that loads the addressable sprites on scene start and then puts the reference back. I don’t like this solution, but if nothing else is out there that retains both the 2D design workflow and sprite atlas generation, I will go with it.

Ok, I’ve done some additional digging just to make sure I can explain it as best I can.

Assets contain objects.
Unity’s built in direct reference system is looking at the object level
Addressable Assets is looking at the asset level.

For example, the sprite asset on disk in your project actually has a texture asset and a sprite asset inside it. If your game has some prefab/ui/whatever that references a sprite, it’s just referencing the sprite object. As such, that reference can be whatever to sprite to atlas.

In Addressables, however, if you mark the asset as addressable, we don’t know which object you want. We include all in the build. The sprite object, and the texture object. Because you might do Addressables.LoadAssetAsync(“whatever”); We have no way of knowing you don’t want to be able to do that.

So if your UI references a sprite that’s in an atlas, as long as the sprite itself is not addressable, you should be fine. If you want a way in addressables to get to a sprite that’s in an atlas, you need to mark the atlas as addressable, and use the atlas interface to pull the sprites from it.

1 Like

I understand what you’re saying @unity_bill , but I don’t think duplicating the texture data is an acceptable solution for mobile in particular. Mobile users constantly delete apps that are the largest on their devices when they need to clear up space. Doubling the size of these types of assets is not helping.

If I’m understanding you’re saying to do the following:

Instead of doing the typical addressable way of marking the asset addressable and using a reference
public AssetReferenceSprite mySprite;

You’re asking us to unmark the sprite assets as addressable and do something like this?
public AssetReference mySpriteAtlas;
public string mySpriteName;

If this is correct, this is not an good workflow for 2D sprite assets. Not only do artists and designers not work with atlases in the typical 2D workflow, we’re back to super fragile string references to assets. Addressables was supposed to be a solution here and use the asset database GUID to keep file moves/renames so that it doesn’t fail finding the sprite at runtime.

I’m surprised that this hasn’t been brought up as a problem before now. I really feel that this is should work with the 2D team to see if there is anything that can be done to get around this flaw. Maybe we can mark the sprite sub asset as addressable instead of the parent texture asset in situations where we only want to link the sprite and not the texture information? The other thought is that you don’t include texture information on textures imported as sprites if they are atlased. I’m sure that loading texture data for an atlas sprite should be rarer, and thus a better alternative than duplicating texture data. If there is still a need for having texture data, the user can duplicate the asset and load the non-atlased version. While not perfect, you’re targeting the higher use case scenario rather than the all or virtually nothing approach you currently have with sprite sub-assets.

1 Like

So at present the best way is not to use Sprite Atlas. Use this ASTC compression format.

Agree with @Ferazel , this workflow is very weak.
It’s like if 2D team asks us to reference atlas and load sprite manually, it’s not acceptable because mistakes and team work :face_with_spiral_eyes:.

I agree.

also agree.

We are working on a solution. Historically SpriteAtlas and AssetBundle systems have not played great together (and addressables is built on asset bundles). Our goal is to create something to mask that from you, but we haven’t completed it yet. It’s high on our to-do list.

3 Likes

If you wanted no batching or to make the atlas yourself at runtime sure you could skip the Unity atlas asset. I don’t think either of these options are great, since the 2D atlas system has some nice built-in features. UI in particular can really benefit from batching with atlases.

I appreciate you acknowledging the problem and putting it high on the to do list. You are correct that SpriteAlases and AssetBundles have always been problematic. Thus I was disappointed to hear that they are still problematic with Addressables. I understand that the first release is primarily to create the abstraction of assets built on top of AssetBundles, but I was hoping it would be better. Please keep a solution to this high on the todo list, which is all I can ask. Thanks!

Thank you for recognize this issue and make solution!
I hopinng it would better.
Thank you!

Just wondering if there’s been movement on this issue or a rough ETA on when we might see something? I’m currently banging my head up against some similar assetbundle / sprite atlas issues.

We’ll release version 1.2.something this week (or early next week if some bugs pop up).

That will include two main features (quoting the upcoming change log):

  • Added sub-object support to AssetReference. For example, you can now have an AssetReference to a specific sprite within a sprite atlas.
  • Added sub-object support to addresses via [ ] notation. For example, sprirte atlas “myAtlas”, would support loading that atlas via that address, or a sprite via “myAtlas[mySprite]”
5 Likes

Hi, @unity_bill
Nice work.
But in our project, we use the workflow like what @Ferazel said, we directly use sprite and sprite name when build UI and fill data.
This struct is what we are using:
5252024--524786--upload_2019-12-6_11-14-49.png

But the solution about “myAtlas[mySprite]” makes we must know the atlas name when the Designer fill data.
so my question is:

  1. Is it possible to load sprite by sprite name when use addressables?
  2. we test some workthrought, but all of them need load all atlas and find the right sprite by GetSprite, we thougt this maybe make a memory issue on mobile, is it right?

Hi, @unity_bill
i have a new workthrought by modify the addressables code.
In ResourceLocationMap.cs, modify the function ‘Add’

        /// <summary>
        /// Add a list of locations.
        /// </summary>
        /// <param name="key">The key to reference the locations with.</param>
        /// <param name="locations">The list of locations to store at the given key.</param>
        public void Add(object key, IList<IResourceLocation> locations)
        {
            Locations.Add(key, locations);
            Debug.Log("Locations add:" + key);
            if (typeof(string) == key.GetType())
            {
                string newKey = key.ToString();
                if (newKey.Contains("[") && newKey.Contains("]"))
                {
                    newKey = newKey.Substring(newKey.IndexOf("[") + 1,newKey.Length - newKey.IndexOf("[") - 2);
                    if(!Locations.ContainsKey(newKey))
                        Locations.Add(newKey, locations);
                }
            }
        }

for “myAtlas[mySprite]”, this will add “mySprite” as the key.
and
The important is : All sprite name must be difference in this way.
now, my question is :
is this a good way to do this ?

1 Like

So right now to provide a good workflow for artist, we must create our own Image class that support AssetReference from Addressables - to include preview within the editor and change the pick window to preview images ?
It seems counter intuitive. Shouldn’t it be part of Addressables ?
Also there needs to be a way to upgrade project to such a workflow.

Are upgrade to Sprite Atlas and Asset Bundles within Addressables still on the priority list ?

2 Likes

I wasted a few hours on this … but I have figured out through trial and error that best workaround currently is to just exclude the png files from the addressable bundles. Include only the atlas files. I usually put whole folders into addressable groups to make everything inside addressable, so in my case I just move the pngs that are in atlases to another folder.

Then you can assign the sprites to UI.Images as usual and it will include only the atlas textures in the asset bundle and at runtime it will use and load only the sprite atlas textures.

If you don’t do this then

  • Your asset bundle will include both all the source textures and the atlas textures.
  • I am not completely sure, but at runtime both the source textures and the atlas textures are loaded, wasting memory. (I have seen this from inspecting with the profiler and memory profiler.)

So actually this is pretty important if you use texture atlases.

2 Likes