ShaderLab佔用疑問

1)ShaderLab佔用疑問
​2)關於Android下ARM64和ARMV7的問題
3)關於ILRuntime相關的性能檢測工具
4)字體加載問題
5)LZ4壓縮模式下的資源打包網絡


這是第239篇UWA技術知識分享的推送。今天咱們繼續爲你們精選了若干和開發、優化相關的問題,建議閱讀時間10分鐘,認真讀完必有收穫。架構

UWA 問答社區:answer.uwa4d.com
UWA QQ羣2:793972859(原羣已滿員)框架

Shader

Q:我從官網下載了一分內置Shader,本身寫工具刷了一遍,確認界面裏面材質球已經沒有引用內置Shader,而且把Standard Shader都清除了,從內存去看也沒有這個,可是ShaderLab的佔用仍是有點大,如今在主場景有47MB。工具

A1:變體太多就會這樣,仔細看看那些不少關鍵字的Shader。

感謝deviljz@UWA問答社區提供了回答性能

A2:樓上說的對,分享一段幾年前寫的掃描工程Shader變體的代碼,掃描一下,把Top前幾的Shader改改就能降不少了。測試

[MenuItem("Find/GetAllShaderVariantCount", false, 20)]
    public static void GetAllShaderVariantCount()
    {
        #if UNITY_5_6
        Assembly asm = Assembly.LoadFile(@"D:Program FilesUnity_5.6.5f1EditorDataManagedUnityEditor.dll");
        System.Type t2 = asm.GetType("UnityEditor.ShaderUtil");
        MethodInfo method = t2.GetMethod("GetComboCount", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
        #elif UNITY_2017_1_OR_NEWER
        Assembly asm = Assembly.LoadFile(@"D:Program FilesUnity_2018.3.0f2EditorDataManagedUnityEditor.dll");
        System.Type t2 = asm.GetType("UnityEditor.ShaderUtil");
        MethodInfo method = t2.GetMethod("GetVariantCount", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
        #endif
        var shaderList = AssetDatabase.FindAssets("t:Shader");

        var output = System.Environment.GetFolderPath(System.Environment.SpecialFolder.DesktopDirectory);
        string pathF = string.Format("{0}/ShaderVariantCount.csv", output);
        FileStream fs = new FileStream(pathF, FileMode.Create, FileAccess.Write);
        StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);

        EditorUtility.DisplayProgressBar("寫統計文件", "正在寫入統計文件中...", 0f);
        int ix = 0;
        sw.WriteLine("ShaderFile,VariantCount");
        foreach (var i in shaderList)
        {
            EditorUtility.DisplayProgressBar("寫統計文件", "正在寫入統計文件中...", 1f * ix / shaderList.Length);
            var path = AssetDatabase.GUIDToAssetPath(i);
            Shader s = (Shader)AssetDatabase.LoadAssetAtPath(path,typeof(Shader));
            var variantCount = method.Invoke(null,new System.Object[]{ s,true});

            sw.WriteLine(path + ","+variantCount.ToString());
            ++ix;
        }
        EditorUtility.ClearProgressBar();   //清除進度條
        sw.Close();
        fs.Close();
    }

感謝李星@UWA問答社區提供了回答字體

A3:URP有一套變體裁剪代碼,拿來改改,加入你的打包流程會裁剪掉沒用的變體(我估計你不少關鍵字用不到,因此應該會減很多)。

感謝Robot.Huang@UWA問答社區提供了回答優化

A4:推薦使用UWA的本地資源檢測,看下哪一個Shader的變體多,是否是變體的問題,另外再確認一下是否是還有Shader的冗餘。

感謝芭妮妮@UWA問答社區提供了回答網站

Build

Q:關於Android下ARM64和ARMV7的問題,從經驗上講,同一個Unity的遊戲在這兩個架構下會出現運行效率的差別嗎?渲染效率會受到CPU架構的影響嗎?ui

A:ARM64能解決不少因地址空間不足、內存分配時出現地址衝突而致使的內存分配失敗的問題。比較典型的就是高通的Adreno顯存不足,或者說字典這種容器類型大量使用致使的內存泄露問題。可是,伴隨着的問題也就來了,一樣的包64位比32位要大,對於對內存有嚴格要求的遊戲,原本優化內存就已經夠頭疼了,換成64位忽然又漲了一截,一股蒼白無力感又油然而生。至於效率問題,沒測試過也沒對比過,樓主能夠測測FPS、溫度、能耗等有多大區別。

感謝李星@UWA問答社區提供了回答

ILRuntime

Q:UWA已經出了針對Lua的性能分析,求ILRuntime,新項目打算改用ILRuntime,看中Await和Async來實現網絡通信的「同步」代碼,戰鬥部分的邏輯代碼也打算在ILRuntime中實現(強CPU計算會盡可能用C#實現),可是性能方面略有擔憂。如有性能分析工具特別是與C#相互交互部分,能夠在初期定技術框架給本身一顆定心丸就行了。

另外,請問ILRuntime已經有哪些項目在線上成功應用嗎?再就是穩定性方面能接過Lua的拉力棒擔當重任嗎?

A1:基本知足平常須要。其實底層機制仍是與Lua相似的,開發習慣和語言上會舒服很多。做爲功能模塊附加或者熱更新功能仍是很不錯的。不過性能方面沒有很是針對性地去作測試,目前只能說知足項目須要。高計算量處理方面仍是不建議在ILRuntime作太多,基礎緣由其實跟Lua問題仍是蠻相似的。

使用上來講,要注意Adaptor的定義。還有熱更新方面,不一樣代碼節點多是須要分別出ILRuntime的熱更包。這個在出包管理上會煩瑣一些,不過開發語言統一上仍是有很多好處的。

感謝阿里@UWA問答社區提供了回答

A2:性能方面其實不須要太大的擔憂,分享一下個人經驗:

  1. 必定要用Release方式去編譯DLL,而且打開DISABLE_ILRUNTIME_DEBUG的宏;
  2. 因爲解譯執行,因此執行效率跟直接執行自然就有20-100倍的差距,太複雜的計算確定不行;
  3. 運行時也是純C#的,因此用UWA工具就能檢測出一些性能問題;
  4. 咱們項目安卓用的有原生DLL效率確定是比Lua要快的,iOS上面測試下來比Lua要慢一點,可是蘋果設備以及IL2CPP的性能都不錯,因此也能作到跑滿幀;
  5. 對對象中的結構體賦值會有沒法避免的GC,建議先轉成本地變量,或者V3這種直接存成XYZ;
  6. Foreach會產生GC,寫的時候不要用。

感謝蕭小俊@UWA問答社區提供了回答

A3:知識搬運工芭妮現身,搬於某國內新一線大廠的大柴:
有朋友用這個作上線了還行,計算密集型不能勝任,計算密集型能夠用Lua,雙熱更核心也是個值得參考的點子。

  1. 核心代碼用C#,例如:物理系統模擬之於閃暖。
  2. 戰鬥庫邏輯層用Lua,例如:秒算戰報的回合制的戰鬥核。
  3. 業務邏輯用ILRuntime,例如:裝備系統,升階升星強化轉生。
  4. 再套一層Injectfix,修非Burst的C#。

感謝芭妮妮@UWA問答社區提供了回答

A4:由於ILRuntime是C#實現的,因此直接看Profiler就能看性能消耗。

感謝終極大菜狗@UWA問答社區提供了回答

Resource

Q:我如今真機測試,在內存發現有兩份字體的加載,一份是好比登陸界面,或者其餘自己有字體的場景引用到的,引用的是原始的Font,另外一份我發現是由於預製體加載到場景,會引用一份複製出來的字體。這個要怎麼解決?

A:若是預設體是從AssetBundle中加載的,場景卻不是AssetBundle加載的,那麼確定是會有兩份的,由於普通的場景打包和AssetBundle走的是不一樣的路線,是引用不到同一份字體資源的,一份是來自場景的Sharedassets,一份是來自AssetBundle。因此要麼場景也走AssetBundle打包,要麼場景中的用到這個字體的UI部分從AssetBundle動態加載。

感謝Xuan@UWA問答社區提供了回答

Addressable

Q:LZ4壓縮模式下,Addressables加載Bundle只會加載Headers到內存中,那麼是否能夠將全部資源打包成一個Bundle?這樣就能夠不用考慮資源粒度以及資源重複打包的問題了?

A1:若是是文件級別的資源更新,而且AssetBundle很大的狀況下和從新下載整包沒什麼太大區別,資源粒度主要是爲了方便減小更新資源量。

感謝鄭驍@UWA問答社區提供了回答

A2:說一下個人總體思路,請大佬看看有沒有什麼隱患。

全部資源使用Addressable打成一個Bundle包,固定讀取路徑爲UnityEngine.Application.persistentDataPath,即永遠讀取本地。捨棄邊玩邊下這個模式,實際體驗起來,邊玩邊下會致使頻繁的卡頓,體驗很很差。

首包發佈一個小包,遊戲啓動時檢查資源更新,資源Bundle(包括後續的增量包)經過C#的HttpWebRequest下載(本身管理下載),支持斷點續傳,統一下載到persistentDataPath,下載完成後正式進入遊戲流程。

優勢:

  1. 資源管理簡單。
  2. 不用考慮資源拆分粒度。
  3. 不用考慮資源重複打包。
  4. 不用考慮首次啓動下載太多Bundle包致使的下載速度緩慢的問題。

缺點:
目前沒想到有什麼隱患,請你們幫忙指正。

感謝題主ShiltonLi@UWA問答社區提供了回答

A3:從資源卸載的角度來講這樣作是不太合理的。Addressable是通引用計數來處理卸載的,只有當AssetBundle的引用計數減小到0的時候纔會觸發,觸發時會調用AssetBundle.Unload(true)。因此若是這個大的AssetBundle裏面有一個資源須要一直常駐內存,就說明那個AssetBundle也須要常駐內存,那麼其它用不到的資源,如某張短期使用事後就能夠卸載的紋理,就卸載不掉了。固然這個說法的前提是用Addressable的加載接口和卸載接口來加載卸載資源。

感謝Xuan@UWA問答社區提供了回答

封面圖來源:Unity Shader Sketches
https://lab.uwa4d.com/lab/5b564b46d7f10a201fd903de
使用ShaderLab繪製草圖。


今天的分享就到這裏。固然,生有涯而知無涯。在漫漫的開發週期中,您看到的這些問題也許都只是冰山一角,咱們早已在UWA問答網站上準備了更多的技術話題等你一塊兒來探索和分享。歡迎熱愛進步的你加入,也許你的方法恰能解別人的燃眉之急;而他山之「石」,也能攻你之「玉」。

官網:www.uwa4d.com
官方技術博客:blog.uwa4d.com
官方問答社區:answer.uwa4d.com
UWA學堂:edu.uwa4d.com官方技術QQ羣:793972859(原羣已滿員)

相關文章
相關標籤/搜索