[Unity] UGUI優化 - 知識點

weixin_34337265發表於2018-05-10

參考文章:


  這篇的目的是記清楚UGUI中網格更新重建(合併)兩個概念。

1、網格更新(對應Canvas.SendWillRenderCanvases)

更新指的是UI元素本身的某些屬性發生變化,從而需要重新生成,或者更新頂點屬性。
總的來說,“網格更新”更新的是頂點屬性。

  這裡的頂點屬性,指的是UIVertex結構的成員,也就是下面幾個變數,其中常用的只有position和color兩個。清楚這一點,要分辯哪些操作會引發更新就容易了。

Variables Desc
UIVertex.color Vertex color.
UIVertex.normal Normal.
UIVertex.position Vertex position.
UIVertex.tangent Tangent.
UIVertex.uv0 UV0.
UIVertex.uv1 UV1.

在UGUI中顏色的變化是通過修改頂點色實現的

  修改Image、Text的color屬性,會改變UIVertex.color;修改RectTransform的Size、Anchors、Pivot等,會改變UIVertex.position,所以這些操作都會引發網格更新。
  直觀感覺上,修改RectTransform(Transform)的Position、Rotation和Scale會改變頂點的position。但測試下來,這些操作不會帶來更新的開銷,也不會改變頂點position。根據列印出來的資料看,UIVertex.position記錄的是本地空間下的座標,因此儲存值不會受到Transform屬性的影響。

SendWillRenderCanvases

1)Graphic.Rebuild()

  1. UpdateGemotry()
  • 改變RectTransform的Size
  1. UpdateMaterial()
  • 修改Color

2)LayoutRebuilder.Rebuild()


2、網格重建/合併(對應Canvas.BuildBatch)

在 UGUI 中,Batch是以Canvas為單位的,即在同一個Canvas下的UI元素最終都會被Batch到同一個Mesh中。而在Batch前,UGUI會根據這些UI元素的材質(通常就是Atlas)以及渲染順序進行重排,在不改變渲染結果的前提下,儘可能將相同材質的UI元素合併在同一個SubMesh中,從而把DrawCall降到最低。而Batch的操作只會在UI元素髮生變化時才進行,且合成的Mesh越大,操作的耗時也就越大。

  Unity的文件把這個問題說的更加明確。

Important reminder: Whenever any drawable UI element on a given Canvas changes, the Canvas must re-run the batch building process. This process re-analyzes every drawable UI element on the Canvas, regardless of whether it has changed or not. Note that a “change” is any change which affects a UI object’s appearance, including the sprite assigned to a sprite renderer, transform position & scale, the text contained in a text mesh, etc.

重要提示:當給定Canvas上的任何可繪製UI元素髮生更改時,Canvas必須重新執行合批過程。此過程重新分析Canvas上的每個可繪製UI元素,不管它是否被修改。注意,“更改”是指影響UI元素外觀的任何變動,包括修改sprite renderer的sprite、transform的position和scale、文字網格的text等。


  綜上,只要UI元素變了,就會引發網格重建(BuildBatch);只有當元素的頂點屬性發生變化,才會出現網格更新(SendWillRenderCanvases)。重建出現的頻率應該是高於更新的,因為更新總是伴隨著重建。
  根據我不太靠譜的測試,更新的開銷普遍高於重建,可能是由於重建在Native中執。

相關文章