https://unity3d.com/cn/learn/tutorials/topics/best-practices/fundamentals-unity-ui?playlist=30089
理解組成Unity UI系統的各個部分很重要。一些基礎的類和組件一起組成了這個系統。這一章節介紹一些的這系列文章所用到的術語,然后討論一些Unity UI 關鍵系統的底層行為。
術語
Canvas是Unity的一個內部組件(native-code Unity Component)。由Unity渲染系統使用,可以提供將在游戲世界空間中繪制的分層幾何圖形。
Canvas負責把它們上面幾何體合並成批次,生成合適的渲染指令,發送給Unity的圖像系統。所有這些都是Unity 本地C++代碼實現的,被稱作rebatch 或者 batch build。當一個Canvas被標記為包含需要被rebatch的幾何圖形,那這個Canvas被認為dirty。
幾何圖形通過 Canvas Render 組件傳遞給Canvas。
一個 Sub-canvas 是一個嵌套在另一個Canvas下的Canvas。Sub-canvas 是它的子級和它們的父級隔離:一個dirty的子級不會強制它的父級去重新生成幾何圖形,反之亦然。(一個canvas是一個重繪單位)[1]
Graphic是Unity UI庫提供的基類。它是所有能為Canvas系統提供可繪制幾何圖形的Unity UI C# 類的基類(Image,RawImage,Text)。大部分內置的Unity UI圖形都是 MaskableGraphic的子類,這樣它們可以通過IMaskable接口來實現遮罩。主要的可繪制的子類是 Image 和 Text,它們提供了同名的組件。
Layout components 控制RectTransform的大小和位置,通常被用來創建一些復雜的排版,這些排版依賴於它們內容的相對大小和相對位置。排版組件只依賴於RectTransform,並且只影響它們管理的RectTransform。它們不依賴圖形類,並且它們可以獨立於Unity UI圖形組件使用。
圖形組件和排版組件,都依賴於CanvasUpdateRegistry類,這是UnityEditor內不可見的接口。這個類記錄那些需要被更新的排版和圖形組件,並且當其關聯的Canavs觸發willRenderCanvases事件時,觸發更新。
圖形組件和排版組件的更新被稱為重建(rebuild)。重建的過程會在之后的文檔中詳細介紹。
渲染細節
當使用Unity UI 制作用戶界面時,記住,所有的被canvas繪制的圖形都是被放在透明渲染隊列。這意味着,Unity UI產生的圖形都會使用透明混合(alpha blending)從后向前渲染。有一個重要的性能點要注意:圖形上的每一個像素都會被采樣,即使它被另一個不透明的圖形完全覆蓋。在移動設備上,大量的的過度繪制(overdraw)可以快速超出GPU填充率的上限。
合批過程(Canvases)
合批過程是指Canvas合並UI元素的網格,並且生成發送給Unity渲染管線的命令。這個過程產生的結果會被緩存住,直到他們被重新標記為dirty,組成它的任何一個網格變化都會使其變為dirty。
Canvas使用的網格都是從綁定在Canvas上的CanvasRenderer獲得,但是不包含子Canvas的網格。
計算合批需要按照網格的深度,是否遮擋,是否共享材質等方面排序。這個操作是多線程的,因此不同的CPU結構,它的性能也不同,特別是移動SoCs(通常有幾個CPU核)和台式CPU(通常有4個或更多的核)。
重繪過程(Graphics)
重繪過程是指Unity UI 的C# 圖形組件的排版和網格被重新計算。這在 CanvasUpdateRegistry類中執行。記住這是一個C#類,並且可以再Unity Bitbucket上找到。
在CanvasUpdateRegistry內部,需要關注的方法是PerformUpdate。當Canvas組件觸發WillRenderCanvases事件時都會調用這個方法。這個事件每一幀都會執行一次。
PerformUpdate執行三個步驟:
- 標記為dirty的排版組件通過ICanvasElement.Rebuild方法重建布局。
- 任何注冊過的裁剪組件(如mask),需要去裁剪所有可剔除的組件。這是通過ClippingRegistry.Cull實現的。
- 被標記為dirty的圖形組件,重建它們的圖形元素。
對於排版和圖形的重建,這些過程都會分解成過個部分。排版重建分成三個過程(PreLayout, Layout and PostLayout),圖形重建包含兩個過程(PreRender and LatePreRender)。
排版重建
要重新計算包含一個或多個布局組件合適的位置(大小),設置合適的層級順序很重要。在層級監視器(hierarchy )中排版靠近根節點的可以能會影響它子集的排版,所以需要被先計算。
為了實現這個,Unity UI 按照hierarchy中深度對dirty的排版組件排序,越高的(父節點少的)排在前面。排序后的布局組件被要求重建它們的布局;這就是通過改變布局組件來控制UI元素位置和大小。有關布局如何影響單個元素更多詳細信息,參閱Unity 手冊中UI Auto Layout部分。
圖形重建
當重建UI的時候,Unity UI 會調用ICanvasElement的Rebuild接口。圖形實現這個接口,在PreRender階段執行兩個步驟。
- 如果定點數據被標記為dirty(如RectTransfom改變大小),那么需要重建網格。
- 如果材質數據標記為dirty(如材質或者紋理改變),關聯的CanvasRenderer的材質也需要被更新。
圖形重建不是通過按照指定順序設置圖形組件層級執行的,不需要任何排序操作。
尾注
- 有一些說法是不正確的,如改變父物體的畫布,會導致子物體畫布調整大小。