I’m currently working on a build tool that takes a list of levels, collects their dependencies and tags each asset in the dependency list with a bundle name according to a naming scheme (characters, models, sounds, etc). The scenes are also bundled (each one in its own bundle) and they’re loaded asynchronously at runtime.
What I could gather from the AssetBundle docs is that when an asset which gets touched by a bundle construction pass does not have its own bundle, it’s duplicated into the master bundle (which is the root of the dependency tree - in my case, the scene bundle). With that I mind, I set off to find a method to get an exhaustive dependency check, meaning that I needed a list which contains absolutely everything from the scene downwards, so I can minimize the amount of assets being duplicated into the scene (which makes sense anyway).
Before diving into some more complicated (and desperate) dependency checking schemes (with manually scanning unity files for guids and such), I thought I’d give a try to the usual suspects: AssetDatabase.GetDependencies and EditorUtility.CollectDependencies.
The first one seemed to be the jackpot at first glance, with a pretty hefty asset list and a very small scene bundle which indicated that pretty much all the dependencies were touched. But the horror came with the dump of all the assets touched by it. It includes pretty much everything in the project (obviously stuff that’s nowhere near the test scene i was using).
For my purpose, the second one can’t be used on its own, as it returns just the first dependency layer (the directly dependent assets), so I made a breadth search around it to collect all the assets. The resulting listing looks like it contains all the assets needed by the scene, however the scene bundle size is pretty big (almost as big as with no dependent bundles), so it seems that BuildPipeline.BuildAssetBundles applied to that scene disagrees with my breadth search list.
Is there something I’m missing with those two API methods or they just have a bad reputation when it comes to working properly?
It seems like GetDependencies returns all the assets i would need to make a unitypackage however i need something more at build time to get all the dependencies that are required for an asset bundle. can anyone assist?
While I haven’t exactly figured why the dependency mega-list happens (it’s also hard to come up with a repro for this, as the project is >3Gb in assets and it only happens on a full build), i’ve toned it down a bit and I’ve found a “workaround”, which is basically just another way of using GetDependencies:
When I build a scene, I use GetDependencies(false) on that scene, so I only get a list of direct assets and each of those assets is scanned in turn. So instead of calling that function in recursive mode, I do the recursive scan by hand and I add each of the returned assets into a mega-dictionary of assets (which is then linked into the asset bundle assignment phase). - The immediate advantage of this is that you’re likely to scan fewer resources from disk, because you’ll start hitting the dictionary resource cache pretty frequently towards the end. The scan is also exhaustive (provided you don’t mess up somewhere in the dependency chain and bypass some asset types or something).
So far, this method has yielded correct results and at the end I get a pretty hefty dictionary with assets which are tagged with usage reference counts and scene dependency flags (i can see which set of scenes use what asset, even if the asset is further down the hierarchy - like an .fbx file referenced by a .controller, referenced by a .prefab, etc).
With GetDependencies, the major thing I’ve noticed is that Materials keep asset references around, even if you’ve changed the shader, etc. I don’t think they get added to the build, but all those unused material properties interfere with dependency checks.
If you’re processing a set of assets with GetDependencies, you’re working with path strings, and you don’t acutally have to load the assets.
I haven’t worked with CollectDependencies, but I think it has different behavior from GetDependencies. There’s a recursive version called CollectDeepHierarchy, and its docs say that it will not collect everything:
“For example, having a MeshFilter component in the hierarchy will not cause the referenced Mesh to be included in the resulting list.”
Bump: Materials are not updated on AssetDatabase.Refresh();
I have a project that clearly updates everything, but not materials.
I am forcing every update possible, everything else works like a charm, only materials are stuck with old references in AssetDatabase.GetDependencies.
Then I can look at that and after ‘Shaking Unity’ - like doing a fake ‘Export package…’ (Just calling the Export window) instantly fixes the lack of materials update. Instantly. And also doing other things with other assets can sometimes suddenly get things shaken in place.