We just discovered a nasty problem on a project (in production)… Some background first.
We have an Asset Group (we call it “Preloaded”) that contains all the assets that we need to be always loaded in memory throughout the game (to be used synchronously at any moment). Because this bundle is rather large, it takes some time to load. So I used various ways to optimize loading time. First I created a custom BundledAssetProvider that uses sync version of AssetBundle.LoadAsset API to load assets (because it is much faster this way). But later after upgrading to newer Addressables I discovered the new “Asset Load Mode” option and got excited… Basically it calls AssetBundle.LoadAllAssetsAsync() when you request the first asset. This actually improved loading time quite a bit, and didn’t cause any issues at first, so I was happy to push this change to production…
Now the nasty part. It appears when you do LoadAllAssetsAsync the Unity will not only load all assets in the bundle itself into memory, it will also load all parent assets that contain any dependency sub-assets in them, even if parent assets themselves are not needed. This behavior is different from loading every asset in the bundle using LoadAssetAsync.
Here’s a concrete example. In a Preloaded bundle we have a prefab with Animator component. This component has reference to an Avatar asset, which is contained within an FBX model asset. This FBX also contains a bunch of meshes and references to materials. When loading this asset normally, only the Avatar sub-asset is pulled from model into memory. However when LoadAllAssetsAsync is used, we see all the textures references by this FBX loaded in memory! Because we had a lot of textures in one FBX, the memory load becomes catastrophic on certain devices.
I think this pitfall needs to be mentioned in documentation or maybe fixed. Because as API user I expect the LoadAllAssets to do the same thing as iterating over all assets and loading them with LoadAsset.
Hi @phobos2077
Can I get some clarification on your situation.
In your situation, do you have like the following:
Group: Preload (Load mode set to load all)
Entries:
Prefab (references FBX)
Group: Others
Entries:
FBX
In the above situation the behaviour you described should be the case, the Prefab load within loadAll, should only get the referenced Objects and not load the full thing.
If you have the FBX in with the Prefab
Group: Preload (Load mode set to load all)
Entries:
Prefab (references FBX)
FBX
Then that would load the entire FBX at the point where the bundles Assets are requested. (Requesting Prefab will load everything in the FBX).
@andymilsom To clarify, I get different memory situation based on Load Mode setting alone. So when I switch it to normal mode (no preload) then I don’t observe extra textures in memory profiler.
I have a prefab that only references Avatar asset inside FBX asset, but not the root GameObject (the model itself). The FBX asset is not in any group at all. It contains a model with a bone structure, an Avatar and a bunch of SkinnedMeshRenderer GameObjects. Via import settings material references are set up that in turn reference a number of textures.
Case A: “Requested Assets And Dependencies” mode is used:
Prefab is loaded but textures are not loaded into memory
Base B: “All Packed Assets And Dependencies” mode is used:
These extra textures (not referenced anywhere by themselves) are seen in Memory Profiler.
@phobos2077 It is not very clear what is happening there.
Just to be sure: if this is in Fast mode in Editor. Then that behaviour is not unexpected.
If it’s a built Player or Use Existing bundles mode. Then it should not happen based on your description.
It sounds like the full FBX is being built, where it should not be.
Like in your example. if you have a Prefab that references an Object in the FBX prefab (say Avatar), and build the Prefab to Addressables/AssetBundle. Then only the referenced objects, the Avatar (not the full FBX) is expected to be added as an implicit inclusion of the Prefab.
The issue you described is not so much that the textures are loaded with load all mode. But the problem that they are included in the bundle at all.
Would it be possible to make a repro bug report?
I do not think we can solve the problem without investigating it as a bug.
It definitely adds the whole FBX, at least if buildlayout.txt is to be trusted.
I don’t know… I can only say based on the observed results.
This issue isn’t a blocker for the my project atm because we got rid of that big FBX (replaced with multiple smaller FBX) and disabled “All Packed” mode. Because in our case not only did it result in much higher memory footprint, but also made the player crash often during load (strangely enough, with Mono backend it crashed 100%, without “All Packed” mode it does not crash). Something tells me I wouldn’t be able to reproduce the crash on an empty project…
Not sure what other information I can give, but there’s definitely something wrong with how AssetBundle.LoadAllAssetsAsync is working on Unity’s side, based on this experience.
Ok, thanks @phobos2077
Glad you solved the issue with splitting it up.
It sounds like these are bugs that we would not be able to fix without a reproduction of the issue. Something in the build is causing the full fbx to be included, and probably also the cause of the crash.
If you continue having the issue then please file a bug report and we will be able to debug the issue locally and fix it.