Unity 加載AssetBundle

隨着Unity的版本更新,加載AssetBundle的API也不斷變化,要熟悉這些API才能把資源包管理的更好,在這裏作個總結。html

WWW

Unty4.x - 5.x 用WWW類加載
WWW.LoadFromCacheOrDownload() 經過Url和版本號自動緩存資源包 注意必須是資源包 不能是其餘格式 不能加密segmentfault

www加載樣例:緩存

using UnityEngine;
using System.Collections;

public class LoadFromCacheOrDownloadExample : MonoBehaviour
{
    IEnumerator Start()
    {
        while (!Caching.ready)
            yield return null;

        using (var www = WWW.LoadFromCacheOrDownload("http://myserver.com/myassetBundle.unity3d", 5))
        {
            yield return www;
            if (!string.IsNullOrEmpty(www.error))
            {
                Debug.Log(www.error);
                yield return null;
            }
            var myLoadedAssetBundle = www.assetBundle;

            var asset = myLoadedAssetBundle.mainAsset;
        }
    }
}

UnityWebRequest

Unity2018.1之後 官方建議用UnityWebRequest類代替WWW類
UnityWebRequest.GetAssetBundle() 兼容WWW.LoadFromCacheOrDownload()的功能 並提供了更多的功能異步

UnityWebRequest加載樣例:函數

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

/// <summary>
/// 下載測試
/// <para>原文地址:https://segmentfault.com/a/1190000019656656</para>
/// </summary>
public class WebRequestTest : MonoBehaviour {

    private void Start () {
        StartCoroutine(DoLoadFile());
    }

    // 下載文本或二進制文件
    private IEnumerator DoLoadFile() {
        string url = Application.streamingAssetsPath + "/" + "test.txt";
        using (UnityWebRequest request = UnityWebRequest.Get(url)) {
            yield return request.SendWebRequest();
            if (request.isHttpError || request.isNetworkError) {
                // 下載出錯
                print(request.error);
            } else {
                // 下載完成
                string text = request.downloadHandler.text;
                byte[] bytes = request.downloadHandler.data;
            }
        }
    }

    // 下載圖片
    private IEnumerator DoLoadTexture() {
        string url = Application.streamingAssetsPath + "/" + "test.png";
        using (UnityWebRequest request = UnityWebRequestTexture.GetTexture(url)) {
            yield return request.SendWebRequest();
            if (request.isHttpError || request.isNetworkError) {
                // 下載出錯
                print(request.error);
            } else {
                // 下載完成
                Texture2D texture = (request.downloadHandler as DownloadHandlerTexture).texture;
            }
        }
    }

    // 下載AssetBundle
    private IEnumerator DoLoadAssetBundle() {
        string url = Application.streamingAssetsPath + "/" + "test.ab";
        using (UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(url)) {
            yield return request.SendWebRequest();
            if (request.isHttpError || request.isNetworkError) {
                // 下載出錯
                print(request.error);
            } else {
                // 下載完成
                AssetBundle assetBundle = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
            }
        }
    }

}

最重要的API

加載本地資源包最快的API:
AssetBundle.LoadFromFile(path) 同步 注意必須是AssetBundle格式 能夠壓縮 不能加密
AssetBundle.LoadFromFileAsync(path) 異步 注意必須是AssetBundle格式 能夠壓縮 不能加密性能

官方文檔翻譯:測試

同步地從磁盤上的文件加載一個資源包。
該函數支持任何壓縮類型的包。在lzma壓縮格式下,數據將被解壓到內存中。未壓縮格式和塊壓縮格式能夠直接從磁盤讀取。
與LoadFromFileAsync相比,這個版本是同步的,在建立AssetBundle對象以前不會返回。
這是加載AssetBundle的最快方法。
《官方文檔》https://docs.unity3d.com/Scri...加密

PS:從官方文檔能夠看出 彷佛不壓縮或LZ40要比LZMA壓縮性能更好 百度後發現確實如此
LZ4要比LZMA加載速度更快 內存佔用更小 缺點是包體積大url

參考資料:
《關於LZMA和LZ4壓縮的疑惑解析》https://blog.csdn.net/weixin_...
《一樣的場景,分別用LZMA和LZ4壓縮方式,經過AssetBundle.LoadFromFile(Async)加載,內存上能夠相差多少》
https://answer.uwa4d.com/ques...
《AssetBundleCompression Bundle的壓縮格式》http://blog.sina.com.cn/s/blo....net

下載遠程文件最好的API:
UnityWebRequest.Get() 至關於之前的WWW下載 能夠是任意格式文件 能夠壓縮 能夠加密
能夠經過Get()下載文件後解壓縮保存到本地 用LoadFromFileAsync()讀取 加快加載速度

下載遠程資源包最好的API:
UnityWebRequest.GetAssetBundle() 注意必須是AssetBundle格式 能夠壓縮 不能加密

各API加載測試:
資源包大小:48.5M 壓縮格式:LZ4 測試平臺:PC 本地文件

API 加載時間 內存上升 說明
new WWW(path) 49ms 49M 排除偏差 內存基本與資源體積一致
UnityWebRequest.Get(path) 48ms 49M 排除偏差 內存基本與資源體積一致
AssetBundle.LoadFromFile(path) 3ms 1.1M 加載速度最快 內存最小 只緩存索引
AssetBundle.LoadFromFileAsync(path) 18ms 1.1M 加載速度極快 內存最小 異步版LoadFromFile
AssetBundle.LoadFromMemory(path) 78ms 52M 數據徹底緩存在內存裏 內存佔用最大
AssetBundle.LoadFromMemoryAsync(path) 91ms 51M 數據徹底緩存在內存裏 異步版LoadFromMemory

資源包大小:41.7M 壓縮格式:LZMA 測試平臺:PC 本地文件

API 加載時間 內存上升 說明
new WWW(path) --ms --M 排除偏差 內存基本與資源體積一致
UnityWebRequest.Get(path) --ms --M 排除偏差 內存基本與資源體積一致
AssetBundle.LoadFromFile(path) --ms 52M 加載速度最快 內存最小 只緩存索引
AssetBundle.LoadFromFileAsync(path) --ms --M 加載速度極快 內存最小 異步版LoadFromFile
AssetBundle.LoadFromMemory(path) --ms --M 數據徹底緩存在內存裏 內存佔用最大
AssetBundle.LoadFromMemoryAsync(path) --ms --M 數據徹底緩存在內存裏 異步版LoadFromMemory

總結:
隨着Unity版本的迭代,API不斷變化以適應更多的需求,管理資源包的API變得愈來愈複雜了,官方儘可能提供一個簡單易用的API幫助開發者自動處理這個過程,可是當開發者處理的狀況愈來愈複雜時,就須要本身定製資源包生成管理器和資源包加載管理器了,熟悉官方API才能更好的掌控性能,多看官方樣例。

參考資料:
《Unity Assetbundle的加載方式的效率和內存佔用》https://blog.csdn.net/u012740...
《WWW.LoadFromCacheOrDownLoad官方文檔》https://docs.unity3d.com/2018...
《UnityWebRequest.GetAssetBundle官方文檔》https://docs.unity3d.com/2018...

轉載請標明原文地址:https://segmentfault.com/a/11...

相關文章
相關標籤/搜索