從UI(UGUI)上面的優化,我想從三個方向來分析:
drawcall的優化
動靜分離的優化
三個優化,性能佔比,從高到底。
一. drawcall的優化
具體的觀察drawcall的方式講了,下面來講一下幾個容易造成drawcall數量偏大的原因和優化drawcall的小tips
1.mask的多次使用。
mask對於drawcall的影響應該是所以組件裏面最大的。每存在一個mask,就把mask以內和以外的UI分割成兩個“世界”,依次計算兩個“世界”的drawcall,然後再相加。原因是mask以內和以外的UI不能通過unity3d一次渲染(batch)。所以在使用mask的時候要仔細思考,能不用就不用,實在要用可以考慮用帶通道的圖片代替mask的遮罩功能。
2.圖集整理不規範。
影響drawcall數量的根本是batch(批處理數),而batch是根本一個一個圖集來進行批處理的。簡單來說,兩張image重疊在一起,當兩張image的sprite是一個圖集裏的時候,這兩張image就是一個batch;當不是一個圖集的時候,兩張image就變成了兩個batch。所以在處理圖集的時候,通常做法是,常用圖片放在一個共有圖集,然後獨立界面的圖片放在一個圖集,一個UI最好控制在2-3個圖集。
3.圖文交叉。
unity3dUGUI的batch規則除了依賴於圖集之外,還依賴於組件關係,當2張圖片(同一圖集),1個文字進行重疊時,處理不好會發生一些drawcall的多餘。比如:image->image->text,這樣的話,drawcall就是兩個,但是當:image->text->image的時候,就算兩張image的sprite是一個圖集的,這樣的drawcall都會有3個。所以儘量不要出現image->text->image,圖文交叉的情況。根據原因2,也有個小tips,當存在兩個圖集的三張image的時候,也儘量不要出現image1->image2->image1這樣的操作。
4.UI層級的深度。
在不必要的情況下,我們儘量減少UI層級的深度,在UGUI中Hierarchy面板,節點的的深度,表現的就是UI層級的深度,我們UI中有N層,N越大越靠前,會遮住後面的組件。當深度越深,不處在同一層級的UI就越多,drawcall就會越大。
二. 動靜分離的優化
以一個遊戲的主界面爲例:
我把界面簡單的規劃成了4個區域:
1.上方按鈕區域
2.右方按鈕區域
3.技能區域
4.人物頭像及任務區域
如果按照簡單的動靜分離原因:1.2區域是不常變化的,我們放在一個節點以下;3.4區域是常變化的,幾乎每一秒都在變化,我們放在一個節點以下。這樣就可以達到動靜分離的效果。
動靜分離,可以減少UIMesh動態更新,在某些比較複雜,常駐的界面可以這樣優化。小的界面就沒必要了,因爲不必要的節點有可能會造成drawcall的增加的。
三. 文本,圖片預選項的優化
1.image和text組件的Raycast Target屬性
在組件不需要射線檢測的時候,我們可以儘可能的把射線檢測去掉,在運行的時候,就可以減少不必要的性能開銷。
這裏給一段小代碼,在創建image和text的時候,就可以去掉Raycast Target
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
public class CancelImgandTxtRay
{
[MenuItem("GameObject/UI/Image WithoutRay", false, 10)]
static void CreatImage(MenuCommand menuCommand)
{
EditorApplication.ExecuteMenuItem("GameObject/UI/Image");
GameObject go = Selection.activeGameObject;
GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject);
go.GetComponent<Image>().raycastTarget = false;
}
[MenuItem("GameObject/UI/Text WithoutRay", false, 10)]
static void CreatText(MenuCommand menuCommand)
{
EditorApplication.ExecuteMenuItem("GameObject/UI/Text");
GameObject go = Selection.activeGameObject;
GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject);
go.GetComponent<Text>().raycastTarget = false;
}
}
2.text組件的Rich Text屬性
當text組件勾選了Rich Text的時候,其實每次文本顯示都會先判斷一下是否擁有這個屬性,然後做正則匹配,如果不勾選的話,其實還是有一些優化的。但是這個優化點其實是最小的,不必要的話,其實沒必要優化這個,事實證明,在通常情況下如果我們不勾選,但是後期又要對text進行富文本的操作,容易引出一些不必要的bug。
第一條和第二條優化是必須的,帶來的性能提升是巨大的。但是當不存在性能瓶頸的時候,不建議去優化第三條,性能的提升不是很大,容易引出不必要的bug,但是如果存在性能瓶頸,我就差這麼一點了,那麼可以去優化他,是可行的。
以上個人一點愚見,僅供參考。