We have been using the Unity AssetBundle system since the earliest 4.x versions. Our application runs on iOS, Android, and WebGL. While the new updates found in Unity 5.x provide some incremental advantages and very nice tutorials, there still seem to be a number of issues in real world use.
We’d like to share some of our findings to compare notes with others to see if there are helpful workarounds or whether these issues can be scheduled into future releases of Unity 5.x. These are not meant to be a criticism of all of the hard work by the Unity team but rather an open discussion to help improve the product.
Everyone’s feedback is appreciated!
- Asset Dependencies On Resource Assets
Asset dependencies are a very useful feature and the new manifests make things much clearer as to which bundles are dependent on other bundles. But what about dependencies to assets that are in the “Resources” folder.
Since Assets in the Resources folder are already included in the binary, and since Unity 5.x forces the use of BuildAssetBundleOptions.DeterministicAssetBundle, why would multiple copies of these “dependent” Assets be included in each AssetBundle that uses them? Shouldn’t Unity be able to use the unique GUIDs to infer that an asset is located in the “Resources” folder and make it available to Assets loaded from an AssetBundle at load time without needing a copy of it inside the AssetBundle?
According to the latest AssetBundle tutorial for Unity 5.2:
Asset dependencies are never lost. Dependent Assets will be added to the AssetBundle automatically along with the selected Asset if that dependent Asset has not been assigned to any AssetBundle when the AssetBundles are built. This is very convenient and prevents the loss of dependent assets. However, this can also cause the duplication of Assets.
We have some resources that we consider “system” resources such as fonts, graphics used for system dialogs, etc. We have found that trying to put these inside an AssetBundle located in StreamAssets and loading them at runtime is exceedingly slow resulting in very slow load times for our app. We need these Assets to be nearly instantaneously available to the binary but would also like to share them with AssetBundles. Instead of having to put these “system” resources into an AssetBundle, we would like for downloaded AssetBundles to be able to reference them in place from the Resources folder without duplicating them into each AssetBundle that references them.
Interestingly, the AssetManifest generated by Unity 5.x does not show these dependent Resource Assets in it’s file list or in it’s dependency list. Are they actually being included in the AssetBundle without being explicitly listed? They are listed in the Editor log build output as “Used Assets”.
- AssetBundle Caching and Hash Identifiers
The new system provides the ability to append an AssetBundle’s hash identifier to the generated AssetBundle file name using BuildAssetBundleOptions.AppendHashToAssetBundleName. While this seems like a useful feature, it doesn’t seem to work as expected in practice when using WWW.
LoadFromCacheOrDownload.
The problem is that by including the hash in the file name, each change to an AssetBundle will result in a new file name and will be considered unique in regards to its presence in the cache. For example, assume changes are made to assets in an AssetBundle called ‘abc’ resulting in the creation of 3 different hash values and hence 3 different files (for simplicity the “_xxx” suffixes represent simplified versions of the actual Hash128 values generated by Unity):
abc_123.unity3d
abc_345.unity3d
abc_456.unity3d
Using WWW.LoadFromCacheOrDownload with these 3 different file names will cause all 3 AssetBundles to be loaded into the cache and remain in the cache.
According to the latest LoadFromCacheOrDownload documentation for Unity 5.x:
Cached AssetBundles are uniquely identified solely by the filename and version number; all domain and path information in url is ignored by Caching. Since cached AssetBundles are identified by filename instead of the full URL, you can change the directory from where the asset bundle is downloaded at any time.
To circumvent this issue, we have had to use our own naming convention where the hash value is included as part of the path instead of part of the file name. Because LoadFromCacheOrDownload ignores path information, each of the following AssetBundle files are considered the same (assuming we always pass the same version number into LoadFromCacheOrDownload as well).
/somepath/abc/123/abc.unity3d
/somepath/abc/345/abc.unity3d
/somepath/abc/456/abc.unity3d
Instead of having to remap our AssetBundle files, we would like the LoadFromCacheOrDownload to ignore the hash portion of AssetBundle file names. Perhaps the addition of some specific restricted naming convention could be included such as abc_hash123.unity3d. If Unity made it clear that the inclusion of “_hashxyz” was restricted to AssetBundle hashes, LoadFromCacheOrDownload could be modified to work without file renaming and made the BuildAssetBundleOptions.AppendHashToAssetBundleName more useful.
- AssetBundle Cache Flushing (Not Busting)
There still exists no way to flush an AssetBundle out of the cache. It’s understood that existing AssetBundles can be overwritten with new versions but there should be a way to explicitly remove AssetBundles from the cache altogether and free up precious space on user’s cell phones and PCs.
For example, we make use of lots of short-lived DLC like promotions, timed quests, timed store discounts, etc. Once these short-lived DLC items expire, there’s no reason for them to persist in the AssetBundle cache but we have no way of explicitly removing them.
This has been a glaring issue across multiple major versions of Unity. Is there a technical reason this can’t be easily implemented or just a major oversight?
To put this in perspective, our long time users often have several hundred megabytes of “dead” AssetBundles in their cache. Only a complete re-install of the app (not something we want them to have to hassle with) will flush the these “dead” AssetBundles for good.
Feedback Welcome!