[Unity] UGUI DrawCall合并

這兩天跑項目性能,發(fā)現(xiàn)不少問題,其中某系統(tǒng)UI的DrawCall占到了135個之高,給項目的大佬們跪了Orz...UGUI是到這邊項目來之后才接觸的,對它DrawCall合并的規(guī)則有一點點了解,嘗試優(yōu)化的時候發(fā)現(xiàn)能改的地方不多,也就能降低5-10個左右...
  下面記錄下一番求助、查找、測試得出的結(jié)論,時間不多,這里沒有原理性的內(nèi)容,全是規(guī)則用來指導(dǎo)日常開發(fā),相對還比較實用吧。
  首先感謝丑哥提供的Gad解析文章,還有他的個人博客,高大上又實用。
  下面進(jìn)入正題。

1、UGUI元素Depth計算

UGUI內(nèi)部實現(xiàn)用到了Depth(層)的概念,感覺和NGUI開放出來的Depth作用類似,不過一個是內(nèi)部計算得到,一個是手動控制(在這方面NGUI還是非常方便的,真的?。。。?。
  UGUI會遍歷所有UI元素(以深度優(yōu)先排序),對當(dāng)前每一個UI元素(CurUI)進(jìn)行如下計算:

  1. 如果不渲染:CurUI.depth = -1
  1. 如果渲染,且底下沒有其他元素與其相交(Rect Intersects):CurUI.depth = 0
  2. 如果底下有元素與其相交,底下元素Depth最大(MaxLowerDepth)的只有一個,CurUI與這個元素可以Batch:CurUI.depth = MaxLowerDepth
  3. 其他:CurUI.depth = MaxLowerDepth + 1

稍微解釋下第3條,如果CurUI下面疊了多個元素,這些元素的最大層是MaxLowerDepth,如果有多個元素的層都是MaxLowerDepth,那么CurUI和下面的元素是無法合批的;如果只有一個元素的層是MaxLowerDepth,并且這個元素和CurUI的材質(zhì)、紋理相同,那么它們就能合批。

2、DrawCall合批(Batch)

上面Depth的計算是合批的關(guān)鍵,得出Depth后合批流程如下:

  1. 使用多條件Depth、MaterialID、TextureID、RendererOrder(HierarchyOrder)對UI元素進(jìn)行排序(條件的優(yōu)先級依次遞減)
  1. 剔除depth == -1的元素,得到Batch前的UI元素隊列(VisiableList)
  2. 對VisiableList中相鄰且可以Batch(相同Material和Texture等)的UI元素合批

3、Mask的坑

UGUI的Mask可以做出很好的遮罩裁剪效果,然而在DrawCall合并上是個大坑...
  下面記錄了自己試驗(Unity5.4.1)得出的一些結(jié)論,使用的時候加小心吧。
  Mask和RectMask2D最好對比著看,相同序號的內(nèi)容講的是同一個方面。

3.1 Mask

  1. Mask組件會占用兩個DrawCall,一個在底下設(shè)置Stencil Buffer,一個在頂上還原Stencil Buffer,Mask下的子元素夾在中間
  1. 如果多個Mask綁定的Image組件,屬于同一個Atlas,那么Mask之間的元素可以進(jìn)行合并(包括Mask自己產(chǎn)生的2個DrawCall);否則不能合并
  2. Mask外的元素和Mask內(nèi)的元素,無法合批。
  3. Mask完全裁剪的元素,依然占據(jù)DrawCall
  4. Hierarchy中被Mask分割的元素,可以正常合批
  5. Mask裁剪掉的部分還會影響其他元素的Depth計算,而它自己的也會受到其他元素的影響。即:裁剪掉到部分只是不可見,對Depth計算沒有任何影響。

3.2 RectMask2D

  1. RectMask2D本身不占DrawCall
  1. RectMask2D之間無法合并DrawCall
  2. RectMask2D外的元素和RectMask2D內(nèi)的元素,無法合批
  3. RectMask2D完全裁剪的元素,不再占用DrawCall,也完全不參與Depth計算
  4. Hierarchy中被RectMask2D分割的元素,如果Depth、Atlas與RectMask2D下的某元素相同,則無法合批。
  5. RectMask2D裁剪掉的部分,依然參與Depth計算
  6. 如果RectMask2D上綁定了Image,那么多個RectMask2D的Image如果屬于同一個Atlas可以合并

解釋下第5條,如果同一個圖集上可合批的元素,在Hierarchy中被一個RectMask2D分割在上下兩部分,那么這些元素的合批有可能被打斷。什么情況下會被打斷呢?用N代表要合批元素所在的層,如果RectMask2D中第N層的元素和外面要合批的元素屬于同一個圖集(Atlas),那么這個合批就會被打斷。

4、其他

  • UI元素Position的Z值不為0時,會被視為3D UI,不參與合批。父節(jié)點Z != 0,則下面的元素都無法合批了。
  • UI元素Rotation的X和Y修改后,若元素不在UI平面內(nèi),則無法合批,原因同上。
    例:X=0、X=180時,元素始終保持在UI平面內(nèi),合批是正常的;X=1,元素與UI平面相交,此時無法合批。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容