Loading AssetBundles can consume memory depending on compressionA method of storing data that reduces the amount of storage space it requires. See Texture Compression, Animation Compression, Audio Compression, Build Compression.
See in Glossary formats and access patterns.
When you load an AssetBundle, Unity allocates memory to both the assets contained in the AssetBundle and to its internal data. The main types of internal data for a loaded AssetBundle include:
AssetBundle.memoryBudgetKB to control its size.
A TypeTree is an internal Unity data structure that describes the structure of data within a serialized binary object. It acts as a schema for Unity objects from the serialization system’s perspective.
Each serialized file in an AssetBundle contains a TypeTree for each object type in that file. You can use TypeTree information to deserialize files whose type definitions might have changed since serialization (for example, when fields are added, removed, or modified).
When Unity loads an AssetBundle, it loads all TypeTrees and keeps them in memory for the AssetBundle’s lifetime. TypeTree memory overhead depends on the number of unique object types loaded from AssetBundles and their complexity. Each AssetBundle contains a complete set of TypeTrees for its objects. Unity shares identical TypeTrees between AssetBundles to reduce memory usage when multiple AssetBundles are loaded.
You can reduce the memory requirements of AssetBundle TypeTrees in the following ways:
To test the impact that TypeTrees have on the size of AssetBundles, build them with and without TypeTrees disabled and compare their sizes. Use BuildAssetBundleOptions.DisableWriteTypeTree to disable TypeTrees in an AssetBundle.
Note: Some platforms require TypeTrees and ignore the DisableWriteTypeTree setting. Additionally, not all platforms support TypeTrees.
If you disable or strip TypeTrees then consider the following:
StreamingAssets folder.TypeTreeHash in the AssetBundle manifest can help, and the binary2text tool (with -typeinfo flag) exposes raw TypeTree details for comparison.
The table of contents is a map in the AssetBundle that you can use to look up each explicitly included asset by name. The size of the table of contents data increases with the number of assets explicitly included in the AssetBundle, and the length of the string names used to map them. The addressableNames property represents the string name, and if not defined the asset path is used instead.
To minimize the amount of memory dedicated to holding table of contents data, minimize the number of AssetBundles loaded at a given time.
The methods GetAllAssetNames and GetAllScenePaths expose the table of contents map.
The preload table lists all objects that an asset depends on. When you load an asset from an AssetBundle, Unity uses this table to automatically load all required dependencies.
Each asset has its own preload table. For example, a prefabAn asset type that allows you to store a GameObject complete with components and properties. The prefab acts as a template from which you can create new object instances in the scene. More info
See in Glossary’s preload table includes entries for all components attached to the prefab, referenced materials and textures, and any other assets the prefab uses.
Each preload entry uses 64 bits of memory and can reference objects in other AssetBundles.
When an asset references another asset that in turn references other assets, the preload table can become large because it contains duplicate entries where the assets share dependencies. If two assets both reference a third asset, then the preload tables of both assets contain entries to load the third asset.
Preload tables can contain duplicate entries where assets share dependencies. When an asset references another asset that in turn references other assets, Unity stores this information in each asset’s preload table. This can impact on memory usage.
You can reduce the impact of large preload tables in the following ways:
Unity manages memory efficiently, but temporary in-memory AssetBundles are created in the following scenarios:
AssetBundle.LoadFromFile, LoadFromMemory, or LoadFromStream APIs.UnityWebRequestAssetBundle on platforms without AssetBundle caching such as Web.Temporary files exist until reads complete and AssetBundle.Unload is called. These in-memory copies can significantly increase RAM usage and load times.
Caching.compressionEnabled is true (the default), downloaded AssetBundles are recompressed to LZ4 and stored in the cache. This conversion generally improves loading performance.Caching.compressionEnabled is false, temporary AssetBundles are stored uncompressed, potentially increasing RAM usage if the original AssetBundle was compressed.CRC checks for LZ4 files can affect load times because the entire file needs to be decompressed. This uses minimal memory because Unity decompresses each chunk individually instead of the entire file at once.
CRC checks for LZMA files incur no additional overhead, because full decompression is inherent. For more information, refer to Downloading AssetBundles.
It’s recommended to perform CRC checks only once, at download time, rather than at every AssetBundle load, especially on platforms with weak CPUs.
Beyond temporary in-memory AssetBundles, other structures consume memory:
ArchiveStorageReader.m_CachedBlocks) helps manage sequential reads. For uncompressed AssetBundles, this cache might still be used.SerializedFile cache: The PersistentManager uses a shared cache (PooledFileCacherManager) for pages of data read from SerializedFiles within AssetBundles. Its default size is 1MB.AssetBundle object that contains the table of contents, and the PreloadData object.PersistentManager.Remapper: Tracks relationships between instance IDs and source files. Can use noticeable memory for AssetBundles containing very large Prefabs (object hierarchies) as it never reduces in size once allocated. Objects in scenesA Scene contains the environments and menus of your game. Think of each unique Scene file as a unique level. In each Scene, you place your environments, obstacles, and decorations, essentially designing and building your game in pieces. More info
The following information summarizes the use of in-memory files and format conversions when loading AssetBundles of different formats using available APIs. This directly impacts runtime memory consumption.
Caching.compressionEnabled = true)
Caching.compressionEnabled = true)
Note: Converting and opening in-memory files involves opening the source, checking its format, converting it to LZ4 (or uncompressed if Caching.compressionEnabled is false) as an in-memory archive file, opening this in-memory file, and finally deleting it when unloaded and no more readers exist. This process can be an inefficient use of memory and loading time.
When loading assets, Unity supports loading by full project-relative path, file name, or file name without extension. The latter two options are implemented by building extra string tables. In AssetBundles with many loadable assets, these extra string tables can consume noticeable memory.
To reduce this overhead, it’s best practice to always load assets using their exact key (project-relative path or Addressables name) and disable the extra matching capabilities at build time:
BuildAssetBundleOptions.DisableLoadAssetByFileNameBuildAssetBundleOptions.DisableLoadAssetByFileNameWithExtensionRefer to the documentation for the name parameter in AssetBundle.LoadAssetAsync for more information.