Search Unity

Android, Addressables, SpriteAtlases use case. Questions and suggestions.

Discussion in 'Addressables' started by MacroPinch, Sep 20, 2018.

  1. MacroPinch

    MacroPinch

    Joined:
    Dec 6, 2013
    Posts:
    43
    Hi,
    I've just checked the Addressables system and I must say that I'm very excited about it, because it has the potential to solve several big pains for us with the old asset bundles system.

    First, let me tell you our use case with the old system. We are doing this in almost all projects.

    In Android, we are breaking our game in 3 different APKs - low.apk, med.apk, high.apk

    all APKs contain <compatible-screens> in their manifests. This way the low.apk gets served by Google Play to the low-end devices, med.apk to medium-end devices, and high.apk to the high-end devices.

    So what do these APKs contain?
    low.apk contains a low.bundle asset bundle, which contains sprites with low resolution. med.apk contains medium.bundle and high.apk contains high.bundle with the highest resolution sprites. This way both the download size for the end user is optimal and the video memory, when the bundle assets are loaded, is also optimal for the device.

    How do these APKs get built?
    We have a custom build system, but basically it goes like this:
    1. We are exporting a gradle project with "Export Project" in Build Settings
    2. In a Pre-process script the assets bundles get built in some external directory
    3. Then, the gradle project gets exported by unity to some other folder
    4. In a Post-process script we are creating a gradle configuration with low, med, high productFlavors
    5. Then the generated asset bundles get copied to the right folders, so they can get bundled with the right APKs
    6. Then we build the product flavors

    How do we setup the asset bundles to contain the same sprite assets, but with different resolution?
    This is where the dark magic happens and where our hurdles start.

    First, this is what we would like to happen in a perfect world:
    1. We'd like to have a single sprite.png in the project
    2. We'd like to tell this sprite to go to high.bundle as it is
    3. Also, go to medium.bundle, but scaled down to 50% (and/or use another compression settings)
    4. Also, go to low.bundle, but scaled down to 25%

    Problem 1:
    Unfortunately, this is not possible with the old system, because you can't assign a single sprite to multiple bundles.

    The solution is to have sprite.png in 3 different folders for each asset bundle. This is very ugly, because you should keep the 3 folders always in sync. It's very easy to introduce errors, because only one of the sprites is really linked to the scene and unity can't give you warning if there is something wrong with the other 2 sprites (if they are missing and so on). Also, you have to keep all settings like compression level, mipmaps, etc. for these sprites in sync too.

    We partially, fixed this problem with the help of our source control system. We put our sprite.png in a folder named high_sprites and then configured the source control to create external links from this folder to med_sprites and low_sprites (excluding the .meta files)

    This way a file added to the high_sprites folder would automatically show up in the low_sprites and med_sprites.

    Problem 2:
    The source control can't scale down the sprites in med_sprites and low_sprites folders. Also, we can't really scale down the files in med and low folders, because the source control sees them as links and not as separate files, so changing the file in low_sprites folder would also change the original file. We had to do this somehow in unity.

    Fortunately, we had to use SpriteAtlases anyway and a slave SpriteAtlas can be set to scale down the assets to 50 or 25%.

    So what we did:
    1. create Master atlas and link the high_sprites folder. Assign this atlas to the high.bundle
    2. create Master_med atlas, link med_sprites and assign it to med.bundle. Also, create Slave_med (which is a slave atlas linked to Master_med), set the scale property to 0.5 (50%) and also assign it to med.bundle.
    3. Did the same for low

    From here on unity automatically check the high_sprites, medium_sprites, and lows_sprites for changes.
    If there are any new sprites in the folders they automatically inherit the compression settings of the atlas, because the whole folder is assigned to an atlas. Unity automatically scales down the sprites during build time before putting the sprites in their bundles.

    Cool 'eh? Not so much. The setup of this is a pain and there are still some problems. Since the source system doesn't link the .meta file of the original sprite (if it did Unity would go crazy, duplicate GUIDs and so on) we still have to keep manually many settings in sync like 9-patch slicing and others.


    So... I played a bit with the addressable system, but on the surface it looks like you can't have 1 sprite assigned to 2 different groups.

    I decided to try something else:
    1. Created a Master atlas and assigned a single sprite (relatively big in size) changed the compression settings of the atlas to high quality
    2. Created a Slave atlas, which inherits from master and changed the compression to low quality
    3. Assigned the Master atlas to a Content group called "High" and assigned the Slave atlas to a content group called "Low"

    Now, according to the Build Output Preview everything looks as it should - the master atlas goes to the appears in the High group and the Slave atlas appears in the Low group. The sprite is copied in both groups, because it is a dependency of both atlases.

    My question: is this how it's intended to work? Is this the way I have to go in order to migrate our old system?

    Meanwhile I saw some inconsistencies. For example, when I change the settings of the atlases the bundles don't seem to rebuild. For example if I change the compression of the atlases from high quality to low quality the bundles remain the same size when the project is exported. If I hit the refresh button in the Build Output Preview and then export the project the bundles do get lower size.

    Another inconsistency is when I set the master atlas compression quality to low and the slave atlas compression quality to high - both bundles get created with similar size on disk and it seems like both contain the sprite with low compression quality, which shouldn't be the case.

    And one more thing...
    It would be nice to have an Editor API to manage the Groups, Profiles, Labels and their settings or hook to the bundle build process.
    We have many project and configuring everyone take a lot of time. We have a configuration assembly, which we drop in an Editor folder and it configures the project, creates the PreProcess and PostProcess hooks and does everything our build system needs. It would be great if this assembly can create automatically the needed Groups and profiles, so it would be only a matter of assigning the assets.
     
    hololabs likes this.
  2. MacroPinch

    MacroPinch

    Joined:
    Dec 6, 2013
    Posts:
    43
    Anyone?