Whether your application streams assets from a content delivery network (CDN) or packs them all into one big binary, you’ve probably heard of AssetBundles. An AssetBundle is a file that contains one or more serialized assets (Textures, Meshes, AudioClips, Shaders, etc.) and is loadable at runtime.
AssetBundles can be used directly or through systems like the Unity Addressable Asset System, (aka Addressables). The Addressables system is a package that provides a more accessible and supported way to manage Assets within your projects. It is an abstraction on top of AssetBundles. While Addressables minimizes the direct interactions developers have with AssetBundles, it is helpful to understand how the usage of AssetBundles can affect memory usage. For an overview of the Addressables system, please refer to Unity Addressable Asset System and Unity Addressable Asset System
Developers working on new projects should consider using Addressables rather than working with AssetBundles directly. If you are working on a project with an already established AssetBundles approach, the information here about how AssetBundles affect runtime memory will help you get the best possible results.
Losing memory to the memory cache
When Unity downloads an LZMA AssetBundle using the WWW class (which is now deprecated) or UnityWebRequestAssetBundle (UWR), Unity optimizes the fetching, recompressing, and versioning of AssetBundles using two caches: the memory cache and the disk cache.
AssetBundles loaded into the memory cache consume a large amount of memory. Unless you specifically want to frequently and rapidly access the contents of an AssetBundle, the memory cache is probably not worth the memory cost. Instead, use the disk cache.
If you provide a version or a hash argument to the UnityWebRequestAssetBundle API, Unity stores your AssetBundle data into the disk cache. If you do not provide these arguments, Unity uses the memory cache. Note that Addressables uses the disk cache by default. This behavior can be controlled via the UseAssetBundleCache field.
AssetBundle.LoadFromFile() and AssetBundle.LoadFromFileAsync() always use the memory cache for LZMA AssetBundles. We therefore recommend using the UnityWebRequestAssetBundle API instead. If it is not feasible to use the UnityWebRequestAssetBundle API, you may use AssetBundle.RecompressAssetBundleAsync() to rewrite an LZMA AssetBundle on disk.
Internal testing shows that there is at least an order of magnitude difference in RAM between using the disk cache and using the memory cache. You must weigh the tradeoff in memory cost versus added disk space requirements and Asset instantiation time for your application.
To determine what effect the AssetBundle memory cache may have on your application’s memory usage, use a native profiler (our tool of choice is Xcode’s Allocations Instrument) to examine allocations from the ArchiveStorageConverter class. If this class is using more than 10MB of RAM, you’re probably using the memory cache.
Xcode’s Allocations Instruments showing the amount of memory used by the ArchiveStorageConverter class
Find out what your AssetBundles are actually loading
When building AssetBundles for large projects, do not assume that Unity by default will minimize the amount of duplicated information across them. To identify instances of duplicated data in the generated AssetBundles, you can use the handy AssetBundle Analyzer, written in Python by one of our colleagues in the Consulting & Development group. Used via the command line, the tool extracts information from generated AssetBundles, which is then stored in an SQLite database that features several useful views. You can then query the database using tools such as DB Browser for SQLite. This tool can help you find and resolve any inefficiencies in your build pipeline, whether you created bundles manually or via Addressables.
Analyzing the results from the AssetBundle Analyzer tool using DB Browser for SQLite class
Alternatively, check out the AssetBundle Browser toolAssetBundle Browser tool, which you can download and integrate into your project straight away. Note that this tool provides similar functionality to Addressables, so if you are using Addressables, this tool is not relevant.
The AssetBundle Browser tool allows you to view and edit the configuration of AssetBundles in a given Unity project and provides build functionality. It also provides some neat features, such as informing users about duplicated Assets that are being pulled due to dependencies, such as textures.
The AssetBundle Browser tool warns us about duplications due to dependencies being pulled by more than one bundle
Losing memory to duplicate Assets
When deciding how to organize your Assets into AssetBundles, you need to be careful about dependencies. Regardless of your AssetBundle topology, Unity makes a distinction between Assets that live inside the application binary (in or involving a Resources folder) and those that you need to load from AssetBundles. You can think of these two types of Assets as living in different worlds. It is impossible to create an AssetBundle that has a hard reference to the instance of an Asset inside the Resources folder world. To reference those Assets, Unity instead makes a copy of the Assets that it uses in the AssetBundle world.
Two Components have a hard reference to the “logo” image. If these Components are serialized into different archives (bundled with the player or included in an AssetBundle), each will include their own copy of the image.
Take for example a game’s logo. The logo may be displayed in the UI of a loading scene while the game starts up. Because this loading screen must be shown before remote Assets are streamed to disk, you might include the logo Asset in the build so that it can be used immediately.
This same logo is also used on an options panel in the UI, where users can select their language, sound preferences, and other set