Unity UI優化小結
最近在做Unity的專案,負責UI相關的工作,學習了一下Unity UGUI更新的原理,以及優化相關的部分。本文主要參考UWA的分享,UWA專注效能優化,感覺有很多值得學習的文章,UWA-簡單優化、優化簡單,打好理論基礎,少走彎路,後面實際專案中就是儘可能去實現這些細節了。
目錄
•1.元素更新方式
•2.Draw Call合併規則
•3.網格更新機制
•4.降低介面的渲染開銷
•5.降低介面的更新開銷
1.元素更新方式
UGUI
public class VertexHelper:IDisposable
{
private List<Vector3> m_Position = ListPool<Vector3>.Get();
private List<Color32> m_Colors = ListPool<Color32>.Get();
private List<Vector2> m_Uv0S = ListPool<Vector2>.Get();
private List<Vector2> m_Uv1S = ListPool<Vector2>.Get();
private List<Vector3> m_Normals = ListPool<Vector3>.Get();
private List<Vector4> m_Tangents = ListPool<Vector4>.Get();
private List<int> m_Indices = ListPool<int>.Get();
}
有這樣一個VertexHelper類,和UI元素有一一對應的關係,包含頂點資訊,UV,顏色,等等當UI元素髮生變化的時候,就會從位置,長寬等陣列填充這些list。
對製作的影響
當UI發生改變的時候,須要對陣列的元素進行更新,“動態元素”少用Outline,Tiled Sprite儘量減少“動態”長文字
如上圖Tiled生成了大量網格,在填充的時候耗時更長。OutLine,是通過把一個四邊形重複5次,畫出的OutLine的效果,會使文字的定點數乘以5,使更新的陣列過長。
更新方式
•UIPanel.LateUpdate
o輪詢
o UIPanel.UpdateWidgets
•Cavans.SendWillRenderCanvas
o佇列
o m_LayoutRebuildQueue
o m_GraphicRebuildQueue
NGUI每幀更新UIPanel,輪詢,不管發生變化與否,哪怕是靜態的,還是會有開銷
UGUI更新包含2個佇列,渲染之前在SendWillRenderCanvas的回掉裡面處理2個佇列的元素,如果大量靜態,消耗幾乎為0。
對動態HUD快取機制的影響
•NGUI
o適量元素:Color.a=0,移出
o大量元素:SetActive(false)
o Time+二級快取
•UGUI
o Scale=0,Alpha Group=0
如血條,傷害數字,經常會出現消失的UI元素,如果出現就建立,消失就destory,開銷會非常大。所以通常的做法通過快取,如果通過SetActive有時候會有額外的開銷,
UGUI通常的操作方式可以通過scale=0,或則Alpha Group為0,可以快速隱藏,不要直接alpha=0,在draw call上是沒變化的,實際上還是畫了個透明度為0的面片。
NGUI中和UGUI相反,如果設定alpha=0,是會把頂點移除掉,可以減少setActive的開銷。
2.DrawCall合併規則
渲染順序
•NGUI:Depth
o設定depth值,以UIPanel為單位,按照大小進行排序,相同材質進行合併
•UGUI:hierarchy
o重疊檢測
o分層合併
存在優勢,也有一些問題,UGUI的合併規則是進行重疊檢測,然後分層合併。下面的例子中,不同顏色代表不同圖集。
第一個圖,4種顏色,左邊和右邊數序相同,藍色是0層,白色都是1層,這樣會分層合批成4個DrawCall。
第二個圖,左邊的藍色是0層,右邊的黑色是0層藍色是1層,這種情況下不會合批,所以會是9個drawCall
第三個圖,把黑色延長到重疊的地方,黑色同處0層,所以DrawCall又降到了5。
所以在製作UI的時候,須要考慮層級關係,結合UGUI的合批規則,這樣可以達到對drawCall的優化,
除錯工具
•NGUI:DrawCall tool
•UGUI:Frame debugger
NGUI可以通過DrawCall tool看到多少個三角面,多少個widgets,通過觀察widgets的關係,對NGUI層級直接調整,來進行合批。
NGUI使用drawcall tool,通過調整index,把相同材質的放在同一層。
UGUI用frame Debug看每個drawcall繪製了哪些東西,再做調整
對介面的影響
•UGUI
o不規則圖示的擺放
o UI元素的旋轉
o動態遮擋
o 3D UI
•NGUI
o手動排序
UGUI中,對於不規則圖形,視覺上icon沒有重疊,但是UI層是包圍盒的形式,Icon重疊了,UGUI在判斷的時候沒辦法進行合併。
UGUI對於發生旋轉的UI,包圍盒是會發生重疊,會限制UGUI在合併DrawCall的操作。
如下圖:
NGUI把不同的元素設在一個圖集中,進行同批次繪製。
3.網格更新的機制
•UIPanel.LateUpdate兩種更新方式
o UIPanel.FillDrawCall更新單個DrawCall
o UIPanel.FillAllDrawCall更新所有DrawCall
•Canvas.BuildBatch更新所有DrawCall
o WaitingForJob子執行緒網格合併
o PutGeometryJobFence
o BatchRendere.Flush UI如果開多執行緒渲染,BatChRender.Flush會增高,主執行緒在等待子執行緒的結果時Flush會等待。
NGUI根據不同的DrawCall合併不同的網格UGUI以Canvas為單位,一個Canvas下的元素,合併成一個Mesh,不同的UI元素會以SubMeshes的形式存在。UGUI中如果一個Canvas中有很複雜的動態元素,儘量將靜態元素拆分出來,確保更新的效率。
優化方法:
•UGUI
o拆分Canvas
•NGUI
o控制FillAllDrawCalls
o拆分UIPanel
效能比較
•功能介面的DrawCall控制NGUI>UGUI(NGUI通過DC樹,通過調整Index進行調整)
•功能介面的網格更新機制NGUI>UGUI(UGUI更新任何一個UI,都會更新整個Canvas)
•動態HUD介面的網格更新機制UGUI>>NGUI(UGUI在處理動態UV的元素,如血條,動態UI會更有優勢)
•堆記憶體控制UGUI>>NGUI(NGUI堆記憶體佔用更高)
參考https://blog.uwa4d.com/archives/Implosion.html
4.降低介面的渲染開銷
•Profiling定位
•DrawCall控制
•Mesh.CreateVBO UI變化的網格開銷
•Overdraw UI比較容易產生Overdraw
Profiling
UGUI非多執行緒渲染Unity5.3主要集中在RenderSubBatch,
DrawCall控制
Z值!=0
合併時只會合併相鄰層級,相同圖集的元素
左邊的圖,4個血條紅色和白色的z值相同,共2個drawcall,但是右邊的圖,紅色和白色穿插,變成8個drawcall,在3D UI的時候尤其明顯,2DUI不要通過這種方法,改Z值,因為2D改了之後,
未“隱藏”的元素
包含Null Sprite,Color.a=0螢幕外
對於隱藏的元素,NGUI的image元件中,alpha為空和sprite為空,都是佔用drawcall渲染的,而且會打斷前後的drawcall,穿插在上下2個元素中間的時候。
Hierarchy穿插+重疊
如下圖紅點和Icon在不同圖集中,如果紅點稍微大一點,遮擋了旁邊的Icon,就不能合批,須要調整Icon和紅點的節點關係,4個Icons放在一個節點下,4個紅點放在一個借點下。在同步位置的時候可能稍微麻煩有點,須要寫個指令碼同步位置。
圖集分離
可能因為壓縮方式的不同,導致UI的sprite在不同圖集中,也會影響渲染開銷,不同圖集中無法進行合批
OverDraw
•減少UI層疊
•遮擋場景時,關閉場景相機
•不用Image檢測事件
參考:https://blog.uwa4d.com/archives/video_UI.html
5.降低介面的更新開銷
•動靜分離
•降低更新頻率
•避免“敏感”操作
•優化選項
動靜分離
在UGUI中細分Canvas下圖中,血量和經驗條會經常更新,如果在一個canvas中,PutGeometryJbFence和WaitngForJob,buildBatch出現的時候,表示更新的開銷在子執行緒中,主執行緒處在一個等待的狀態,差不多有5,6毫秒的等待。
拆分之後剛才的WaitingForJob等都沒有了,動態的canvas開銷就會很小。
降低更新的頻率
•設定移動閾值
•設定更新頻率
比如像小地圖這樣的介面,可能移動了一小段距離,小地圖上更新了也不明顯,可以通過設定閾值的方法,降低開銷,或者直接設定更新時間。
避免“敏感”操作
•元素的Position賦值->Canvas.BuildBatch
下面的一個例子是在Canvas中,所有元素基本是靜態的,但是有個元素,在Update中,會跟隨target的position,每次傳送改變的時候,會重建整個canvas,導致資源的浪費。
參考文獻:
https://blog.uwa4d.com/
[《聚爆Implosion》效能精析UI部分]
UGUI研究院之全面理解圖集與使用
專欄地址:https://zhuanlan.zhihu.com/p/43111806
相關文章
- Flutter UI 1.0.2落地與優化小結FlutterUI優化
- UI技術總結--效能優化UI優化
- unity ui的建立方式小記UnityUI
- vue效能優化小結Vue優化
- 前端效能優化小結前端優化
- 小程式效能優化總結優化
- UI效能優化UI優化
- 效能優化(二) UI 繪製優化優化UI
- [Unity] UGUI優化 - 知識點UnityUGUI優化
- Unity C# 反射效能優化UnityC#反射優化
- Tableau視覺化結果的優化小技巧(二)視覺化優化
- 機房合作UI優化UI優化
- Android效能優化(4):UI渲染機制以及優化Android優化UI
- unity postprocessing stack v2的優化Unity優化
- Unity2D之draw call優化Unity優化
- Android UI 顯示原理分析小結AndroidUI
- 淺談網頁基本效能優化規則小結網頁優化
- 【Unity3D】UI Toolkit容器Unity3DUI
- Kafka生產消費資料丟失和優化小結Kafka優化
- 六、Android效能優化之UI卡頓分析之渲染效能優化Android優化UI
- .NET程式設計5月小結 - Blazor, Unity, Dependency Injection程式設計BlazorUnity
- Spark效能優化:優化資料結構Spark優化資料結構
- 小程式優化實踐優化
- Java gc(垃圾回收機制)小結,以及Android優化建議JavaGCAndroid優化
- UI基礎(五)之代理、通知的小結UI
- APP優化總結APP優化
- webpack優化總結Web優化
- 深入詳解 Jetpack Compose | 優化 UI 構建Jetpack優化UI
- 乾貨|優酷小程式優化實戰優化
- 國內首發視覺化智慧調優平臺,小龍帶你玩轉KeenTune UI視覺化UI
- 微信小程式效能優化微信小程式優化
- 【微信小程式】效能優化微信小程式優化
- 淺談小程式效能優化優化
- Android效能優化——效能優化的難題總結Android優化
- 【Unity】(UI)抽屜式摺疊皮膚UnityUI
- 前端效能優化總結前端優化
- 斜率優化DP總結優化
- SYBASE優化總結(zt)優化