Unity场景ab包加载压缩(LZ4,LZMA)格式的测试

情况

最近场景越来越大,大概800M的场景加载时间可能长达40秒左右,所以需要测试看看发生了什么。

测试环境

测试环境Win10,21thI5-12600KF,32GRam , Nvidia GF RTX2060 32G
Scene1大小:741M

加载代码

首先放上部分的加载场景的代码:

        public float sceneprog;
        public AsyncOperation sceneAsync;
        async public Task LoadScene(string path)
        {
            sceneprog = 0f;
            await Task.Delay(10);
            StreamAssetVer sav = GameJsonMain.inst.Get(path);
            if (sav == null)
            {
                Debug.LogWarning("不存在的场景:" + path);
                return ;
            }
            if (!sav.isab)
            {
                Debug.LogWarning("场景isab必须对勾:" + path);
                return;
            }
            float loadtime = Time.realtimeSinceStartup;
            float computloadtime;
            float ratetime = 0.9f;
            //Application.backgroundLoadingPriority = ThreadPriority.Low;
            
            Debug.Log("LoadScene - begin ..."+ Application.backgroundLoadingPriority);
#if UNITY_EDITOR && TESTRES
            string[] dirs = UnityEditor.AssetDatabase.GetAssetPathsFromAssetBundle(path);
            //Object[] listobj = new Object[dirs.Length];
            if(dirs.Length == 0)
                Debug.LogWarning("找不到这个资源:" + path);
            for (int i = 0; i < dirs.Length; i++)
            {
                string assetPathAndName = dirs[i];
                LoadSceneParameters ls;
                ls = new LoadSceneParameters();
                ls.loadSceneMode = LoadSceneMode.Additive;
                
                sceneAsync = EditorSceneManager.LoadSceneAsyncInPlayMode(assetPathAndName,ls);  // .LoadSceneInPlayMode(assetPathAndName, ls);
                sceneAsync.allowSceneActivation = false;
                while (sceneAsync.progress < 0.9f)
                {
                    sceneprog = sceneAsync.progress;
                    await Task.Delay(100);
                    Debug.Log("load - " + sceneprog);
                }
                //sceneAsync.allowSceneActivation = true;
                //listobj[i] = null;
            }
            sceneprog = 1f;
            //Debug.Log("load1 - " + sceneprog);

            computloadtime = Time.realtimeSinceStartup - loadtime;
            Debug.Log("LoadScene unity- load file time : " + computloadtime);
            return ;
#endif
            Task<UnityWebRequest> task;
            if (sav.include)
            {
                task = streamingAssetsLoader(sav);
            }
            else
            {
                task = AssetsLoader(sav);
            }
            await task;
            UnityWebRequest www = task.Result;
            if (www.result != UnityWebRequest.Result.Success)
            {
                www.Dispose();
                return ;
            }

            computloadtime = Time.realtimeSinceStartup - loadtime;
            Debug.Log("LoadScene - load file time : " + computloadtime);
            //这个LoadFromFileAsync函数的路径不需要file://
            AssetBundleCreateRequest abRequest;
#if UNITY_EDITOR
            abRequest = AssetBundle.LoadFromFileAsync(sav.savepath.Replace(filelink, ""));
#else
            if(Application.platform == RuntimePlatform.Android)
            {
                abRequest = AssetBundle.LoadFromFileAsync(sav.savepath);
            }
            else
            {
                abRequest = AssetBundle.LoadFromFileAsync(sav.savepath.Replace(filelink, ""));
            }
#endif
            abRequest.allowSceneActivation = false;
            
            while (!abRequest.isDone)
            {
                sceneprog = abRequest.progress;
                await Task.Delay(100);
                //Debug.Log("ab:"+ sceneprog);
            }
            abRequest.allowSceneActivation = true;
            AssetBundle ab = abRequest.assetBundle;

            computloadtime = Time.realtimeSinceStartup - loadtime;
            Debug.Log("LoadScene - load AssetBundle time :" + computloadtime);
            //Debug.Log("ab1:ok," + sav.path +" - "+ sav.url);

            sceneAsync = SceneManager.LoadSceneAsync(sav.path, LoadSceneMode.Additive);
            sceneAsync.allowSceneActivation = false;
            while (sceneAsync.progress < 0.9f)
            {
                sceneprog = ratetime + sceneAsync.progress * (1- ratetime);
                await Task.Delay(100);
                //Debug.Log("load:" + sceneprog);
            }

            sceneprog = 1f;
            computloadtime = Time.realtimeSinceStartup - loadtime;
            Debug.Log("LoadScene - load LoadSceneAsync time :" + computloadtime);
            await Task.Delay(300);
            
            //sceneAsync.allowSceneActivation = true;
            //SceneManager.LoadScene(ab.GetAllScenePaths()[0]);
            //Object[] objs = ab. ab.LoadAllAssets();
            www.Dispose();
            ab.Unload(false);
            return ;
        }

大致代码分为2部分,在编辑器下#if UNITY_EDITOR && TESTRES 使用编辑器加载方式。

首先我们直接用编辑器通过UnityEditor.AssetDatabase.GetAssetPathsFromAssetBundle(path);方法来载入,大概需要5.5-7秒时间。为什么AB包需要那么久 ?

异步和同步加载测试

所有有了下面的AB包测试。
因为是AB包下载,所以关闭宏定义TESTRES ,我在想是不是使用了AssetBundle.LoadFromFileAsync来异步加载的,所以比较慢,所以把函数改为了AssetBundle.LoadFromFile,发现:

同步LoadFromFile方式:33秒
异步LoadFromFileAsync方式:38秒

时间都挺长的,发现有一个修改后台CPU级别的函数Application.backgroundLoadingPriority

  • ThreadPriority.Low - 2ms
  • ThreadPriority.BelowNormal - 4ms
  • ThreadPriority.Normal - 10ms
  • ThreadPriority.High - 50ms
    改为了High,发现测试的结果相差不大。

压缩方式的对比

把场景的AB包我又打包成了无压缩格式和LZ4格式。我们看看测试结论
默认我的场景是LZMA格式

LZMA : 38秒
无压缩: 4.8秒
LZ4 : 4.7秒

结论

LZ4的压缩方式解压速度非常快和无压缩相差不大,压缩后大小比无压缩强的多,这种不需要从公网下载资源的推荐LZ4。

知识点

LZMA通过UnityWebRequestAssetBundle加载的LZMA格式AB包将自动重新压缩为LZ4压缩,并缓存在本地文件系统上。而通过自己写的下载方案,则可以调用AssetBundle.RecompressAssetBundleAsync API重新压缩。

参考:

https://zhuanlan.zhihu.com/p/342694796

Gzip_vs_Bzip2_vs_LZMA_vs_XZ_vs_LZ4_vs_LZO

https://segmentfault.com/a/1190000019656656

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
This is a shared library for Android, iOS, OSX, Windows, Linux and webGL to decompress 7z (7zip) files and to compress/decompress zip/gzip (.zip/.gz), LZ4 (.lz4), brotli (.br), fastLZ files and buffers. ZIP plugin: iOS/tvOS compilation may require to add the -lz linking flag at Build Settings-> Linking- > Other Linker flags on xcode. webGL for flz,lzma & lz4 supports buffers compression/decompression only. Brotli supports buffer decompression. webGL for zip supports all functions except those that require file system operations. 7ZIP section: The library serves the scope to have fast decompression of 7z files and compress/decompress lzma files and buffers. - The library does 7z decompression and not 7z compression. Compression of lzma alone files is supported. Passwords are not supported. - It is about 2.5x times faster then using a c# implementation for 7z decompression. - You can extract a single file out of the 7z archive. - If you intend to decompress large files it would be better to use the largeFiles flag.(consumes less ram) - You can extract the contents of the 7z file keeping its folder structure. - Ability to get the filenames and file sizes of files in a 7z archive. - get progress of extraction when the 7zip archive has multiple files. - get byte level progress of 7z decompression (single or multiple files). - get byte level progress of lzma compression/decompression. - Ability to encode/decode to/from .lzma alone format. - Ability to decode a specific file in a 7z archive to a byte buffer. - Ability to decode/encode a byte buffer to/from the lzma alone format. - Ability to cancel the decompression when the 7z archive has multiple entries.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值