Use AssetBundle for On-Demand Resource Loading
1. Using AssetBundle
Note: The minigame environment does not support loading assetbundle locally.
1.1 Recommended AssetBundle Build Parameters
public static void Build()
{
string dst = Application.streamingAssetsPath + "/AssetBundles";
if (!Directory.Exists(dst))
{
Directory.CreateDirectory(dst);
}
BuildPipeline.BuildAssetBundles(dst, BuildAssetBundleOptions.AppendHashToAssetBundleName | BuildAssetBundleOptions.ChunkBasedCompression | UnityEditor.BuildAssetBundleOptions.DisableWriteTypeTree | BuildAssetBundleOptions.None, BuildTarget.WebGL);
}When building bundles, please use the following parameters:
BuildAssetBundleOptions.AppendHashToAssetBundleName: Adds a hash to the bundle. When the minigame layer caches bundles and evicts the cache, the hash is an important basis. Please refer to Minigame resource caching.
BuildAssetBundleOptions.ChunkBasedCompression: LZ4 compression, which is more balanced between loading speed and package size.
Unless compatibility between old and new Unity engine versions is needed, please use DisableWriteTypeTree to improve loading speed and reduce memory.
1.2 Downloading AssetBundle
There are two main ways to download a bundle from a server:
- UnityWebRequestAssetBundle.GetAssetBundle
UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(uriPath);
yield return request.SendWebRequest();
if (request.isHttpError)
{
Debug.LogError(GetType() + "/ERROR/" + request.error);
}
else
{
AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
// ab.LoadAsset
ab.Unload(false);
}
request.Dispose();- UnityWebRequest
UnityWebRequest www = new UnityWebRequest(uriPath);
DownloadHandlerAssetBundle handler = new DownloadHandlerAssetBundle(www.uri.ToString(), 0);
www.downloadHandler = handler;
yield return www.Send();
if (www.isHttpError)
{
Debug.LogError(GetType() + "/ERROR/" + www.error);
} else
{
AssetBundle ab = handler.assetBundle
// ab.LoadAsset
ab.Unload(false);
}
www.Dispose();In particular, never use <WWW.LoadFromCacheOrDownload>, WWW, or other cache-bearing interfaces. In WebGL mode, they will use JS to simulate the file system, causing extra memory consumption!
2. Differences in the AssetBundle Cache Update Flow Between Minigame and APP
Due to the special nature of the minigame platform, loading speed must be guaranteed, so we cache bundle files at the low level; developers do not need to implement caching themselves.
Game logic can still be written as if uncached and needing to be downloaded from the network; the plugin layer will determine whether a cache already exists. If not cached, it caches this bundle; if already cached, it returns the cached file and does not actually initiate a network request.
Refer to Resource caching and eviction.
The differences in resource caching and updating lead to different loading flows for APP and minigame.
Common APP AssetBundle usage: Check for updates --> Download all updated resources --> Write to the file system --> LoadFromFile at runtime
From the business side's perspective: always use asynchronous interfaces to download from remote and use; the caching and updating of underlying resources have been automatically completed by the adaptation layer, and the game no longer directly reads or writes the file system.
3. AssetBundle Memory Analysis
3.1 Never Use Cache-Capable Pipeline Interfaces
The loaded bundle file size is 5403162 bytes.
The three loading methods UnityWebRequestAssetBundle.GetAssetBundle/UnityWebRequest/WWW show no memory change before and after loading.
Note that in your business you should not use the deprecated WWW class, especially <WWW.LoadFromCacheOrDownload>; when there are many bundles, it wastes a lot of memory.
3.2 Use Unload Whenever Possible
When a bundle is downloaded from the resource server and used, it goes through multiple memory allocations: browser HTTP object --> copy to WASM temporary memory --> Unity ab in-memory file (slightly larger than the ab itself; compared with LoadFromFile commonly used by APPs, this part is extra overhead in WebGL)
When the HTTP object is disposed, the Unity ab in-memory file remains
When ab.Unload is called, the Unity ab in-memory file is released
Therefore, the best practice is that the business should call ab.Unload(false) as early as possible, and maintain its own Asset reference counting to manage resources.
