Unity技術分享連載(64)|Shader Variant Collection|Material.SetPassFast

Unity技術分享連載(64)|Shader Variant Collection|Material.SetPassFast

https://www.jianshu.com/p/ed347dcff35e

原文鏈接:
https://blog.uwa4d.com/archives/TechSharing_64.html
我們將從日常技術交流中精選若干個開發相關的問題,建議閱讀時間15分鐘,認真讀完必有收穫。如果您有任何獨到的見解或者發現也歡迎聯繫我們,一起探討。
UWA QQ羣:465082844
UWA 問答社區:answer.uwa4d.com


資源管理

Q1:Unity 5 的 Shader Variant Collection 功能是否推薦使用?我有以下3個疑點:
1)使用 Shader 變體之後,Shader 是否還能走資源更新?抑或 Shader 不推薦走資源更新?
2)Shader 變體和 Shader Always Include 的主要區別是什麼?二者對內存和幀率影響如何?
3)在 Unity 5 較早的版本中,Shader 變體功能似乎有一些Bug,現在是否可靠?

經過測試,在較新的版本中(如Unity 5.5.3),將ShaderVariantCollection與Shader打包在相同的AssetBundle中後,其中會包含該Shader在ShaderVariantCollection中指定的Variant。因此:

1)使用 ShaderVariantCollection後依然可以進行資源更新(通過更新AssetBundle,來更新Shader的實現或者ShaderVariantCollection中包含的Variant)。

2)ShaderVariantCollection與Always Included Shaders的區別主要在於打包時所包含的Variant。Always Included Shaders中的Shader,其所有的Variant都會被包含,好處是,理論上不會出現Variant丟失的情況;壞處是,會導致更大的發佈包以及額外的內存佔用,而影響最大的是手動進行Warmup時的耗時以及ShaderLab的內存佔用。因此一般來說,對於Variant特別多的Shader(如Standard Shader),並不推薦放入Always Included Shaders中。

3)目前即使是較新的版本,其可靠性我們也並不能確保,依然建議在使用前進行一些測試來驗證。

此問答來自於UWA 問答社區:
https://answer.uwa4d.com/question/591418087640b5a822204e73
如您對該問題仍有疑問,可以轉至社區進行進一步交流。


性能優化

Q2:請問爲什麼我項目渲染中Material.SetPassFast的開銷這麼高?這個該如何優化?

 

Material.SetPassFast是Unity引擎在渲染過程中Material的輪循切換開銷,一般在Unity5.0~Unity5.3版本中出現。它的開銷主要分爲兩種:

1) Shader.CreateGPUProgram峯值開銷
這種情況主要出現在Shader第一次渲染時。在Unity5.0以後,引擎爲了避免Shader加載時過高的CPU峯值出現,已經將Shader.Parse和Shader.CreateGPUProgram兩種操作分開執行,前者在Shader加載時,後者在Shader第一次渲染時。下圖則爲一款項目運行時渲染時的Shader.CreateGPUProgram開銷。

 

2) 渲染狀態切換開銷
這種情況是幾乎每一幀都發生的,有渲染的地方就會有Material的切換。從問題圖中可以看出,在運行的16000幀中,Material.SetPassFast一共被調用137萬次。這裏可以認爲幾乎全部是渲染時Material的切換操作。因此,該項較高的主要原因還是材質切換操作過多所致。所以,建議研發團隊在報告中的詳細材質頁面查看是否有過多「冗餘」的材質出現,如有則儘可能降低材質的使用冗餘度。

 


動畫

Q3:Animator會把所有狀態的AnimationClip加載到內存,有什麼好的辦法可以動態加載?

1)Animator Controller結構不需要改變,但動畫需要變化。比如隨着人物等級或技能升級,同種的攻擊動作隨着變化等。該種需求可以通過AnimatorOverrideController來進行完成,即按需加載新的AnimationClip,然後替換AnimatorOverrideController中相應的AnimationClip即可。目前,Unity的AnimatorOverriderController不僅可以進行單個替換,同時也可以ApplyOverrides成組替換;

2)Animator Controller結構需要改變,類似於Animation老版本動畫的AddClip功能。這種需求需要替換AnimatorController,研發團隊可以在動態加載AnimationClip的同時,動態加載相應的Animator Controller,然後進行替換即可。

以上方法研發團隊可根據自身實際情況而定。


動畫

Q4:爲什麼Transform.設置Parent會觸發Animator的初始化嗎?Parent是等於null的。

 

把 Parent 設爲null,相當於把這個 GameObject 變爲根節點。如果在設置之前這個 GameObject 本身是**狀態,但其的父節點是未**狀態,那麼設置之後,相當於把這個GameObject **。而**GameObject 時就會觸發 Animator.Initialize 等操作了。


資源管理

Q5:美術做粒子的時候,粒子與粒子之間共用資源的情況很多,例如某幾個粒子共用一個Material,某幾個粒子共用一個貼圖等,應該如何組織AssetBundle?要是對應到最細的那個程度,凡是共用過的資源都單獨打一個AssetBundle,好像又會很瑣碎,假如不那麼做,粒子與粒子之間的AssetBundle又會有冗餘。這方面有什麼好的建議?

AssetBundle打包沒有標準的方式,單就粒子系統而言,因爲其個體本身比較小,並且在項目中經常大量出現,所以並不建議將粒子系統逐個打包,而是建議根據其出現頻率進行打包,比如將同一段時間、同一出現場景等的粒子系統打包在一起。同時,由於粒子系統的Shader基本上都是Unity內置Shader,因此,儘可能將Shader進行依賴打包。我們在UWA Day 2017上對於這種情況進行了詳細說明,其Shader在中低端移動設備上的加載開銷較高,需要研發團隊特別關注。

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

官網:www.uwa4d.com
官方技術博客:blog.uwa4d.com
官方問答社區:answer.uwa4d.com
官方技術QQ羣:465082844(僅限技術交流)

作者:侑虎科技 鏈接:https://www.jianshu.com/p/ed347dcff35e 來源:簡書 著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。