Memory management issues

For example,
Bundle_A contains Prefab_A And Prefab_B,
Bundle_B contains Picture_A And Picture_B,
Bundle_C contains Sound_A, Sound_B,
Prefab_A directly refers to Picture_A and Sound_A,
Prefab_A as AssetReference(a_AssetRef).

I want to know which one is the operation of a_AssetRef.LoadAssetAsync():

  1. Load only reference information from three bundles into memory.
  2. Load the reference information of three bundles and the Prefab_A of Bundle_A, Picture_A of Bundle_B, Sound_A of Bundle_C into memory.
  3. Load all resources of three bundles into memory.

No. 2. See Addressable Group Memory question

Great!
I just need to take care of a_AssetRef. ReleaseAsset() and Resources.UnloadUnusedAssets() when switching scene.Is this the best way to do it?

Addressables.LoadAssetAsync() should pair with Addressables.Release(). Same for AssetReference.LoadAssetAsync() and AssetReference.ReleaseAsset(), which are wrapper methods.

Addressables.InstantiateAsync() could pair with Addressables.ReleaseInstance(), because objects created this way are managed, and will be destroyed (and decrementing the ref count of the loaded asset) when changing scenes.

For Resources.UnLoadUnusedAssets, in general I would like to avoid using it. See the documentation - MemoryManagement.md

When is memory cleared

An asset no longer being referenced (the end of a blue section in the profiler) does not necessarily mean that the item has been unloaded. The key scenario in question is multiple assets in an asset bundle. Say you have three assets: “tree”, “tank”, and “cow” in an asset bundle called “stuff”. When “tree” is loaded, you’ll see a single ref count on “tree” as well as one on “stuff”. Then later, if you load “tank”, you’ll see a single count on each “tree” and “tank”, and a count of two on “stuff”. Now if you release “tree”, it’s count will go to zero, and the blue bar will go away. The asset is not actually unloaded at this point. With asset bundles, you can load a bundle, and part of the contents, but you cannot partially unload a bundle. No asset in “stuff” will be unloaded until that bundle is done with and completely unloaded.

The exception to this rule is the engine interface Resources.UnloadUnusedAssets (see Unity - Scripting API: Resources.UnloadUnusedAssets). If you execute this in the above scenario, “tree” will be unloaded. Because we cannot be aware of these events, we only have the graph reflecting our ref-counts, not exactly what memory holds. Note that if you choose to use Resources.UnloadUnusedAssets, it is a very slow operation, and should only be called during a screen that won’t show any hitches (such as a loading screen).

1 Like

If a project has dozens of roles. Each role’s resource is a bundle, but there will be a situation of shared resources. If the shared part is as a separate bundle, it is not easy to manage, because finding shared resources is cumbersome and the situation of sharing resources will change with the development of the project.

If player keep choosing different roles to fight and do not use Resources.UnLoadUnusedAssets(), there is a risk of memory bursting.

Is there a better solution in this case?

You can call Resources.UnLoadUnusedAssets() at a good time.

Or use a better packing mode results in smaller bundle size.

  • A group packs into a bundle by default (PackTogether).
  • PackTogetherByLabel results in a bundle per unique label set. If you make each role a label, this will generate the “shared resources” bundles for you automatically.
  • PackSeparately results in a bundle per (top-level) entry. it’s the smallest scale, but probably means more IO operations.

Notice that PackTogetherByLabel has a bug in 1.1.5, and will be fixed soon.

1 Like

Thanks very much! I will try these methods.