Can anyone at unity explain the choice made to not free up memory when Addressable assets are released (ref count 0)

From the docs

“However, Unity doesn’t unload released assets from memory immediately, as the memory that an asset uses isn’t freed until the AssetBundle it belongs to is also unloaded.”

Can you imagine how much work goes into any non trivial game to arrange assets so that bundles might hopefully go to zero refs as you move through the world/game.

Its made worse by addressable builds seem to go up in time based on the number of bundles.
Rebuilding back to back without changes still takes 30 minutes with about 500 bundles..
(non addressable build 6 minutes, addressable stand alone builds take an hour )

I’ve worked for years in AAA across multiple huge studios and have never seen such a terrible way of trying to work with streaming assets..

Also to make matters worse the addressable report tool is so slow its unusable, doing anything freezes it from 30 seconds to a minute.

Mike Diskett.

It’s not so much a choice as it a limitation of the fact addressables is a wrapper system for the old Asset Bundles system, which has the same limitation.

The real choice in question is that they chose to do this rather than build a new asset management system from the ground up.

There ought to be a single, central place for you to load Addressables, just like there’s a single central place to manage the Inventory, the web requests, and so forth.

If you do that, it’s easy to implement your own reference counting mechanism and automatically free any bundles when there are no more loaded resources, or when you tell it to.

One of the most common problems developers face working with Unity is that they tend to use Unity’s APIs all over the place, creating systems only for the game logic that sits atop. But the menu itself makes webrequests, saves things directly to playerprefs, using JsonUtility just about everywhere, making almost everything a MonoBehaviour, and so forth.

I often, frequently judder seeing code like that. As if there needn’t be any boundaries between your code and Unity’s APIs. Even experienced developers somehow “forget” best practices to isolate your own code from the framework it is tied to - perhaps in Unity this is bolstered by the impression that one’s code is “embedded” in Unity’s framework, when in reality it still sits above it.

If by chance this is what you’re doing, I hope that this provides an eye-opener. Separate your code from Unity’s, perhaps with the exception of things where this would be awkward, like Transform, Rigidbody and systems the likes of which we just have to make close ties with or it would become unwieldy.

Hey Mike,

Honestly - we hear you.

As a couple of the Unity-regulars above noted, Addressables are inherently tied to the limitations of the underlying technology they were built on (AssetBundles).

That said, for the next generation of Unity we’re actively working on a significant overhaul of our content loading & distribution system, which will deliver much-needed improvements to the issues you’ve raised here - more precise loading and unloading at runtime, more granular content upload and distribution over CDNs, more incremental and efficient content builds, and more. However, as with any major engine update, it’s a process that requires real time / investment.

If it’s a topic you’re particularly interested in, we’d love to pick your brains on some of the pain points you’ve hit with Unity content management so far vs. previous engines.

Cheers,

George

I’m assuming that’s likely a Unity 7 thing?

Would being able to access and use an asset’s guid be on the cards too?

Still looking forward to such an overhaul.

Its great to hear you have a plan to fix it.

But its really perplexing that such an obvious point of pain for users was part of the initial plan. Replacing AssetBundles with a more granular asset loading system seems like something that could have happened in the last 6 years of addressable Work. :frowning:

I will describe our use case for you incase its of benefit.

Artsists have created 2 square KM of dressed world placing prefabs into the world

I split this world into 128Mx128M grid of scenes that are async loaded additively on the fly using addressables. with 4 of these streaming scenes loaded at a time.
(we have a relatively top down view with a small render window into the world)

the scenes reference all kinds of textures/materials/meshes some unique to a scene some reused in any number of scenes.

I have to figure out a cunning way to arrange all the meshes/Textures/Materials into groups so that items arent duplicated in memory (well not too much), and that as many asset bundles ref counts drop to 0 as possible as scenes are unloaded. (Noting that I have to manually call UnloadUnusedAssets to actually free memory used by bundle data structures)

This arranging of groups part is extremely challenging in a real world situation with many many shared materials/textures/meshes.

To make matters worse, rebuilding addressable assets somehow takes an hour (when prior to addressables a game build took 6 minutes) , infact just two rebuilds back to back without any assets changing takes 30 minutes, this is after solving the multi hour builds caused by shader compiling, we now strip shaders to absolute minimum. So iterating on this is very slow.. Further the Addressable Report tool is unusable typing a character into the filter box takes 30 seconds for the first character with each subsequent character being some fraction of the initial.

The build time appears to increase in time proportional to the number of groups.

To add to the challenge I also have to deal with remapper memory , which appears to be a black box thats a source of a great deal of memory allocation, but seems related to long chains of asset bundle references. (Any info on this gratefully recieved)

Mike.

I’m assuming that’s likely a Unity 7 thing?

Would being able to access and use an asset’s guid be on the cards too?

Still looking forward to such an overhaul.

My product managers out today; so I’ll defer on talking about Unity versions so I don’t get in trouble :grin:

That said, I’d be very interested to hear about your specific use cases for accessing / using an asset by guid. I don’t want to hijack Mikes thread so feel free to drop me a DM if you’d like to discuss. I’ve seen you around a bunch, so perhaps we can stay in touch about what we’re working on longer-term.

Its great to hear you have a plan to fix it.

But its really perplexing that such an obvious point of pain for users was part of the initial plan. Replacing AssetBundles with a more granular asset loading system seems like something that could have happened in the last 6 years of addressable Work. :frowning:

For sure - I worked with AssetBundles in production a bunch before joining Unity. 100% get the frustration.

Internally, I know the Addressables folks were fighting a lot against both inherent AssetBundle limitations, and continuing to support a long legacy of backwards compatibility for tons of live service games. I wouldn’t be surprised if that made things more complex for them, but hey - at least we have the chance to solve it properly now!

Further the Addressable Report tool is unusable typing a character into the filter box takes 30 seconds for the first character with each subsequent character being some fraction of the initial.

Honestly, that sounds like a bug. I’ll get someone to look into it.

We chatted about your follow-up in our engineering sync today, so someone from our team will follow up shortly on some shorter term suggestions!

Would it be possible to make the prefabs that are placed in the world use AssetReferences to the “visual” part of the prefab (mesh, etc) and manage loading/unloading based on the camera position? Then the bundles could be fairly fine grained and you would hopefully end up with much simpler dependency trees. The dependency set of a single asset can expand when there are a lot of other assets in the same bundle that have dependencies on other bundles. That should also reduce build times since dependency calculation is a big part of it. There is a file generated during the build that can help identify areas that are causing it to take a long time:

The basic approach is to use more addressables references instead of direct references, as those can pull in many other bundles as dependencies even when they are not needed for the specific asset you are loading at the time.

Here is a good explanation that I got from another dev about how asset bundle dependencies work

Asset Bundles are effectively file systems. As each Asset Bundle is required it is effectively mounted putting its equivalent of a File Allocation Table into memory. If you have direct references in an Asset, they will be resolved and loaded before the bundle that has the Asset is loaded. The dependency will only be unloaded when the bundle with the main Asset is unloaded. One problem we see a lot is people mark objects that are are referenced directly as Addressable and put them in their own bundle. This can be helpful for deduplication if multiple Assets have direct references to that Asset. But if only one Asset has direct references putting the dependency it its own bundle can actually increase the number of bundles to load and the amount of memory being used to track those virtual file systems.

Thanks for the suggestion Paul.

I certainly could try doing as you suggest, I still need to stream in scenes (to save memory on all the gameObjects and transforms, memory is that tight on the target platform that has 1.3GB available)

The scene could effectively be devoid of Mesh/Material(and therefore texture) references that get loaded by a different system..

I would still have the issue of determining a good way to split all these referenced assets into groups, effectively exactly the same issue. If an asset is referenced once, its easy it can go in the bundle for the scene that references it. its all the assets with reference counts from 2 to 1000 that get complicated..

I didnt specify but currently every streaming scene I have that represents 128x128m is in its own group/bundle.

I am also considering what would happen if I just made scenes addressable, and made all textures and meshes non addressable and therefore auto added and duplicated across every scene group

Maybe the memory saved by a smaller PersistentAsset.Remapper memory might offset any duplication in the 4 loaded scenes..

I don’t think I’d be making an addressables group or every chunk/scene. I’d probably be splitting them up in asset groups for larger batches of chunks or even distinct ‘regions’ in this world if there is any.

Then assets then be organised into their respective groups based on where they show up in this 2 x 2km area. Ergo, if there’s a distinct area or feature with its own unique assets, that can be a group.

Naturally there’ll be some assets that show up just about everywhere. Though hard to say without knowing the specifics of your project.

The issue arises when your designers use assets meant to be unique for one location in another.

This would probably blow out the size of your final build.

As @spiney199 mentioned, this is definitely not the right approach. It would cause each non-Addressable asset to be duplicated in every Asset Bundle that reference them, increasing their size on disk, download time and loading time. It would also lead to duplicates in runtime memory. You can check the Addressables Report after you do a build to confirm how much memory would be wasted due to duplicates.

You’re not wrong to question this — the confusion mostly comes from how Unity’s memory system and AssetBundle lifecycle actually behave under the hood.

When an Addressables handle reaches ref count 0, it only means Addressables has released its reference. It does not automatically guarantee:

  • The AssetBundle is unloaded
  • All dependent bundles are unused
  • The allocator returns memory to the OS immediately

Unity will only truly free memory when:

  1. No objects from that bundle are referenced anywhere (including indirect references)
  2. The bundle itself becomes unloadable
  3. A cleanup pass like Resources.UnloadUnusedAssets() runs

Even then, the memory graph may not visibly shrink due to allocator pooling and fragmentation. Unity often keeps memory reserved for performance reasons instead of aggressively returning it.

This design is likely intentional. If bundles were unloaded immediately at ref count 0, many real-world scenarios (UI transitions, scene swaps, frequently reused assets) would cause heavy reload churn and performance spikes.

The real issue is that the documentation doesn’t clearly explain this distinction. Many developers assume “ref count 0 = memory freed,” which isn’t how Unity’s asset system is structured internally.

It would definitely help if Unity clarified whether this behavior is policy-driven (cache-friendly design) or simply a side effect of the current memory architecture.