Let’s say we have prefab A and B, their main Asset Bundle is C, and Asset Bundle C is dependent on Asset Bundle D, because it contains prefab A’s texture. When I want to load prefab B at runtime, AssetBundleManifest tells me C has D dependency, so I have to load it too. Is it possible to know only B’s dependencies at runtime, so I don’t have to load Bundle D in this case?
Loading a bundle doesn’t automatically load all assets in it, only the bundle’s asset manifest. The texture from bundle D referenced by prefab A from bundle C will only be loaded when you actually load prefab A.
Unity doesn’t load asset bundle references automatically, so I’d have to load bundle C manually when loading prefab A.
Correct, you need to load the bundles (because Unity has no idea where they could be) but you don’t need to load the assets’ dependencies from the bundle: it does that automatically for you when needed.
You can verify this by taking a memory snapshot using the memory profiler. If you load a bundle using AssetBundle.LoadFromFile, none of its assets will show up in memory until you load them by calling LoadAsset on the bundle.
Nowadays it’s recommended to use the Addressable Assets package instead of managing asset bundles directly, because it manages the whole dependency loading/unloading for you.
Oh, that’s correct, I forgot about that.
Addressables package is awful though, I’m writing a better alternative for our project.
Be aware that writing a robust asset bundle manager can take a while , depending on your requirements.
Still, I agree that Addressables could be a lot better than they are, and if you have the resources it can pay off to go custom. I find its runtime side over-engineered (to the detriment of performance) and the tooling for managing what asset goes into which bundle too simplistic (the abandoned Asset Graph was quite more powerful).
Just make sure to use the scriptable build pipeline to generate your bundles. It’s poorly documented, yes, but it has a major advantage over the legacy build API: it assigns assets to bundles using guid+fileid, while legacy can only do it at the path level.
Why is this important? Two reasons:
- It allows sub-assets to be assigned to different bundles. Good for when you import models with several disparate meshes which aren’t used together, for example.
- It allows built-in Unity assets (which don’t have proper asset paths) to be assigned to bundles. If you use the built-in pipeline and built-in shaders, this makes a major difference because with legacy Unity would duplicate the shaders on every bundle that references them, using more memory, more storage space, and causing a hitch every time one of these duplicates is loaded into the GPU for the first time.
Thanks for the heads up, I didn’t even know about Scriptable Build Pipeline. Currently using the old method but will check it out after the system is functional