Search Unity

  1. Unity 2018.3 is now released.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Our response to Improbable’s blog post (and why you can keep working on your SpatialOS game). Read more here
    Dismiss Notice
  4. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  5. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

The problem with Addressables and the new AssetBundles system

Discussion in 'Asset Bundles' started by gsantosgeneragames, Jan 11, 2019 at 10:03 AM.

  1. gsantosgeneragames

    gsantosgeneragames

    Joined:
    Nov 21, 2018
    Posts:
    4
    Hi, guys
    First of all I would like to appreciate the whole job with asset bundles during these years, many things have been improved a lot. However I think many useful things are getting lost from the asset bundles legacy system.

    When I talk about this legacy system I am referring to the very old legacy functions that even though are marked as obsolete are still working today. We have been working with this legacy option for 5 years so far because they were added into one of our projects (still being updated) long ago when it was the only option available. The system had a lot of issues but we were able to create a workflow where dealing with all this was almost transparent

    Recently we have been taking a look into the new system, and more specifically Addressables and even though all the improvements are really welcome we are missing a lot of features... I'd like to show you what we have been doing first so you can understand our problem easier.

    1. Asset bundle Creation
    We created all our builds using one script called "CustomBuilds". This script manages a lot of things for properly delivering the different builds we needed. It is also the script responsible of the creation of our Asset bundles using BuildPipeline.PushAssetDependencies, BuildPipeline.PopAssetDependencies, BuildPipeline.BuildAssetBundle and BuildPipeline.BuildPlayer. So at the end of our build process we have a code similar to this

    BuildPipeline.PushAssetDependencies();

    foreach (string assetBundle in BundlesList) {
    BuildPipeline.BuildAssetBundle(...);
    }
    BuildPipeline.BuildPlayer(...);

    BuildPipeline.PopAssetDependencies();

    Basically, every call to BuildAssetBundle was putting some assets into the specific asset bundle but also was removing them from the list of assets to include in the next asset bundles and the final build. You could create dependencies between assetbundles this way. There were already plugins to manage these dependencies and also to explore and create the asset bundles (we were using one of these available plugins on the store to manage the assetBundles content but in the end we were creating them ourselves).

    AssetBundles dependencies are not possible now with the new system. If you add an asset to a bundle and also to the build then this asset is duplicated. There is no way to create a "reference" to an asset included in an asset bundle, imagine a material not included in any bundle referencing a texture inside a bundle for instance. You might think this is a good thing since you remove this annoying dependence but this also breaks what we consider the most useful part of the bundle system (see below)

    2. Asset bundle loading
    There were two ways to load assets from a bundle: direct access and indirect access.
    - In direct access we called AssetBundle.LoadAsset similar to when you call Resources.Load. This function is not marked as obsolete (yet) so we can still use it. There is also AssetBundle.LoadAssetAssynch that we never used basically because we never needed it and also because it complicated things a lot. Interestingly this is the approach the new Addresables system is taking: assynch loading. You may have already guessed by the posts of other people in the forums that this is not a good idea, we need non-assynch functions
    - Indirect access is more interesting. This way of using asset bundles was poorly documented which I think is the main reason why most people were not using it (and probably didn't even know about its existance). At some point of our application we just opened the bundles calling WWW.LoadFromCacheOrDownload (note this is marked as obsolete) from a local uri usually pointing to StreamingAssets folder or Application.persistentDataPath where we had previously downloaded them. After this call all asset dependencies were magically resolved and we didn't have to change a single line of code. In the previous example where there is a material on the build referencing a texture on an AssetBundle if we used this material after opening the bundle it was working. No extra lines of code loading the texture from the bundle was needed. Also, we never closed any of the opened bundles because the memory impact was minimum (opening the bundle was not loading all its content into memory) and asset references were managed the same way any other asset not included in bundles was, no extra ref count were needed (another big problem of the new system)

    Indirect access required to work with some limitations on the asset bundles. The kind of stuff we put on a bundle were basically textures, sounds and FBXs. We never included any scripts or shaders to avoid annoying issues that were very known back in the day. For this same reason we were never including prefabs or materials because they could potentially lead to the inclusion of scripts or shaders.
    But the main benefit of indirect access was that we didn't need to change any line of code when moving stuff to bundles. This was important for us since we included Assetbundles after being working in the project for a couple of years (imagine changing all our loading stuff to assynch calls). We needed to open the bundles before using any resource from them and we had to download everything manually but that was ok. The approach now seems to make this transparent but this was never a problem for us. We clearly prefer to manage the download of assets (because we know the app and we know when we are going to need to do it) than having to move all our loading stuff to an assynch approach, besides it is very common to move to a loading screen where all needed assets bundles are being loaded in the background. It is impossible to make this transparent

    Not sure if I have properly explained it but, our biggest concern now that we are starting a new project is that we are losing a lot of benefits we had and we are getting a lot of issues that we never had to deal with.

    So now that I have explained our workflow, here are the things I wanted to ask:
    - What is the main reason to deprecate WWW.LoadFromCacheOrDownload? Why not fix all the issues it had instead.
    - Why are you guys deprecating assetbundles dependencies? I understand they create some problems but let us deal with them, the benefits are higher
     
  2. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    302
    - UnityWebRequest completely replaces WWW (see https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequestAssetBundle.GetAssetBundle.html)
    - dependencies within asset bundles are now handled automatically (e.g. if an asset in A references an asset in B, then asset bundle A has a dependency on asset bundle B). this enables to give a proper error when you load things wrongly, instead of missing references. Addressables will manage correctly loading asset bundles with dependencies.

    I don't want to make a build, have half of my assets missing, and I don't know why, if I loaded a scene before loading the bundles...

    also with your workflow (having direct references to stuff in bundles) you are still forced to have everything downloaded and loaded in memory when loading the scene, that does not provide any benefit vs having them in the build.
     
  3. gsantosgeneragames

    gsantosgeneragames

    Joined:
    Nov 21, 2018
    Posts:
    4
    Yes, you are right. But I was talking about references with the build itself, not between asset bundles. When you use an asset in a build (contained in a scene) and also in any asset bundle, the asset is duplicated. That's very different to how it was, and it forces you to change the code when moving stuff to bundles

    Neither do I, but that is going to happen to you anyway both with the current system and the legacy one. Now with addressables you have a worst scenario where you load an asset from a bundle and that can take minutes to get downladed forcing you to pause your game execution meanwhile

    No, as I said assets are not loaded into memory when you open a bundle, we checked this with the profiler and have been using this on several games. Also the main benefit of not including assets in the build is reducing the build size
     
  4. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    302
    but you still need to download them, and also you lose the automatic stripping that normal builds have.

    example:
    - you have a scene in the build with objects that reference a material that references a texture. you have 3 other unused material in the project.
    - you build the game. Unity pulls the scene from build setting, and the material and texture that you used.
    - you change stuff and rebuild. Unity naturally tracks the change and your build has the new mat/tex and not the old ones.
    now you use AB your way:
    - your scene has a hard reference to material, but material and texture are in AB
    - you either have an AB with all your assets (so you have a game effectively 3 times bigger) or you need to manually sync the AB build with the game build.
    - if you load the scene with the wrong AB, you simply don't see the object (or you get a missing/null reference somewhere without explanations)

    also, you mentioned in your post that you only put meshes and textures in the bundles, because of limitations of old system.
    we have put basically everything in AB with the new system: prefabs, materials, sprites, scriptable objects (with references to other assets) everything works, and we manage duplication using the AssetBundle Graph Tool (and we have our own AssetBundleManager based on the unity one, customized for our apps) I plan to use Addressables when it will become stable and feature-parity.

    I think your use case of having working hard references to stuff in bundles was undocumented / undefined behaviour, so you were basically hacking with Unity internals.
     
  5. gsantosgeneragames

    gsantosgeneragames

    Joined:
    Nov 21, 2018
    Posts:
    4
    Of course I need to download the asset bundles, how is it going to work otherwise?

    This is what happens with our system in the scenario you are suggesting:
    - We create the AB with the Texture (we never included materials), this is nothing different from the regular workflow. You have an AB with a Texture wether it is used or not in the final build
    - If you build without using the material and the Texture (which doesn't make sense really) you will never use it and nothing happens
    - If you create a new build using the scene with the material, the AB content hasn't changed so you can still use the previous one (there is an option that has to be enabled to ensure internal ids doesn't change between builds that has to be enabled)
    - Now you need to open the AB before loading the Scene (this doesn't load the texture into memory) where the material is used and because it is treated as a dependancy it is loaded when the material is loaded (this is exactly what happens now with dependencies between ABs, first you need to open the bundle where the dependency is)

    The problem with prefabs and shaders could have been fixed instead of creating a whole new system (I am pretty sure in this new system scripts are not included in the ABs because that doesn't make sense)

    And this way of working was perfectly documented. As I have said already the trick was to include dependecies between the build and the AssetBundles. It is as risky and undefined as doing it with the AssetBundles with the current system. I have used the functions that were available back then, never have to hack anything

    And again, the main benefit was that we never had to change a single line of code to move stuff to Asset Bundles.
     
  6. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    302
    you can do this with the new system:
    - move EVERYTHING into asset bundles
    - put only a single script in the build that loads the first scene from Ab, and nothing else
    - direct references between bundles are correctly treated as dependencies, just as before

    scripts are never included in anything, they are compiled into a DLL and that is included in the build (you can include DLL in asset bundle, then manually load it in the mono runtime from its
    byte[]
    contents. it's not allowed on iOS (and probably other platforms) though)