當前位置:網站首頁>Unity3d:UGUI源碼,Rebuild優化

Unity3d:UGUI源碼,Rebuild優化

2022-07-23 12:39:58四夕立羽

Image怎麼繪制的

Unity中渲染的物體都是由網格(Mesh)構成的,而網格的繪制單元是圖元(點、線、三角面)
繪制信息都存儲在Vertexhelper類中,除了頂點外,還包括法線、UV、顏色、切線。

Rebuild概念

Canvas負責將子節點的UI元素的網格合並,並生成相應的渲染指令再發送到Unity的圖形管道的過程。所以Canvas就是渲染UI的組件,當UI發生變化就要執行一次Batch,它是影響性能更大的元凶。注意Canvas的Batch只會影響其子節點,但不會影響其子Canvas。

Rebuild的程序流程

  1. Image,Text都是繼承Graphic,Graphic有ICanvasElement接口,實現rebuild函數
   public interface ICanvasElement
   {
    
       /// <summary>
       /// Rebuild the element for the given stage.
       /// </summary>
       /// <param name="executing">The current CanvasUpdate stage being rebuild.</param>
       /// // 根據CanvasUpdate的不同階段重建元素
       void Rebuild(CanvasUpdate executing);
  1. CanvasUpdateRegistry監聽Canvas的willRenderCanvases事件,這個事件會在渲染前進行每幀調用
   public class CanvasUpdateRegistry
   {
    
         //布局重建隊列,當UI元素的布局需要更新時將其加入隊列
       private readonly IndexedSet<ICanvasElement> m_LayoutRebuildQueue = new IndexedSet<ICanvasElement>();

       //圖形重建隊列,當UI元素的圖像需要更新時將其加入隊列
       private readonly IndexedSet<ICanvasElement> m_GraphicRebuildQueue = new IndexedSet<ICanvasElement>();

       protected CanvasUpdateRegistry()
       {
    
           //監聽了Canvas的willRenderCanvases事件,這個事件會在渲染前進行每幀調用
           Canvas.willRenderCanvases += PerformUpdate;
       }
  1. PerformUpdate收集布局重建隊列,圖形重建隊列調用ICanvasElement.Rebuild完成重建

何時加入重建

通過設置“髒數據”實現的,包括布局(Layout)、材質(Material)和頂點(Vertices)三部分,設置布局為髒,將進行布局重建,設置頂點或材質為髒,則進行圖形重建。布局重建會將自身加入m_LayoutRebuildQueue中,圖形重建則會將自身加入m_GraphicRebuildQueue中,等待被調用。
SetLayoutDirty:加入到布局重建隊列
SetVerticesDirty,SetMaterialDirty:材質,頂點變換加入到圖形重建隊列

布局重建:比特置或者大小 ;

圖像重建:頂點變化,材質變化(大小,旋轉以及文字變化、圖片的修改)

優化

主要目標,把Profile裏Canvas.SendWillRenderCanv參數調小。通過限制頂點數量,頂點變化等。

  1. text屬性改變(“123”–>“1234”),觸發SetLayoutDirty:在做倒計時相關,按照每1s改變,不要實時改變

  2. 改文字,圖片顏色,觸發SetVerticesDirty(頂點改變),所以改圖片顏色最好是改材質球顏色

  3. layout組件引起重建問題

  4. text 描邊,陰影性能問題
    一個字符產生4個頂點,
    如果再加上Shadow則相當於又把Text複制了一遍產生8個,
    Outline則會將Text複制4遍產生20個頂點。
    用相應的shader替換

  5. text漸變

  6. Image格式選擇
    Image:頂點數量取决於Image Type的選擇。
    ①Simple 4 個頂點;
    ②Sliced 勾選FillCenter的頂點數是 36 個,不勾選是 32 個;
    ③Tiled 取决於Rectranform 設置的大小和原圖大小,鋪開了 N 張圖就是 4*N 個;
    ④Filled 選擇比較多,但最少也有4個。
    所以對於Image首選Simple模式其次則是Sliced模式且不勾選FillCenter

  7. 動靜分離 :Canvas.SendWillRenderCanvases()與Canvas.BuildBatch()的計算是以Canvas為根節點進行的,不同Canvas不會影響另外一個Canvas。但是,大量的動靜分離反而影響Canvas的合批,所以可以針對性的對戰鬥UI,主界面做分離

源碼中查看影響重建因素

觸發SetLayoutDirty

Graphic:

  1. protected override void OnRectTransformDimensionsChange():當UI的RectTransform更改時的回調,只要繼承UIBehavior即可獲取回調

Image:

  1. protected override void OnCanvasHierarchyChanged():父畫布的狀態改變

Text:

  1. text屬性改變:在做倒計時相關,按照每1s改變,不要實時改變
  2. public bool supportRichText:設置是否開啟富文本時,開關規則(只要狀態跟上次不同,SetLayoutDirty一下,而不是開啟後實時Dirty)
  3. public bool resizeTextForBestFit:設置是否允許文本自動調整大小時,開關規則
  4. public int resizeTextMinSize:允許的最小文本大小
  5. public int resizeTextMaxSize:設置最大文本大小
  6. public TextAnchor alignment:文本相對其 RectTransform 的定比特。
  7. public int fontSize:文本大小
  8. public HorizontalWrapMode horizontalOverflow:水平溢出模式
  9. public VerticalWrapMode verticalOverflow:垂直溢出模式
  10. public float lineSpacing:行間距,指定為字體行高的一個因子。值為 1 時將生成標准行間距
  11. public FontStyle fontStyle:字體樣式

觸發SetVerticesDirty:頂點變化

Graphic:

  1. public virtual Color color:顏色,所以改圖片顏色最好是改材質球顏色
  2. protected override void OnRectTransformDimensionsChange():當UI的RectTransform更改時的回調,只要繼承UIBehavior即可獲取回調

Image:

  1. public Type type:Simple,Sliced等
  2. public bool preserveAspect:是否保持高寬比,開關規則
  3. public bool fillCenter
  4. public FillMethod fillMethod:填充模式
  5. public float fillAmount
  6. public bool fillClockwise
  7. public int fillOrigin
  8. public bool useSpriteMesh:圖片透明部分裁剪
  9. protected override void OnCanvasHierarchyChanged():父畫布改變

RawImage:

  1. public Texture texture
  2. public Rect uvRect

Shadow:

  1. public Color effectColor
  2. public Vector2 effectDistance
  3. public bool useGraphicAlpha

Text:

  1. public virtual string text
  2. public bool supportRichText
  3. public bool resizeTextForBestFit
  4. public int resizeTextMinSize
  5. public int resizeTextMaxSize
  6. public TextAnchor alignment
  7. public bool alignByGeometry:使用區段的字形幾何執行水平對齊,而不是字形指標。
    這可以導致更好的擬合左和右對齊,但可能會導致不正確的定比特當試圖覆蓋多個字體(如專業輪廓字體)上
  8. public int fontSize
  9. public HorizontalWrapMode horizontalOverflow
  10. public VerticalWrapMode verticalOverflow
  11. public float lineSpacing
  12. public FontStyle fontStyle

觸發SetMaterialDirty:材質改變

Graphic:

  1. public virtual Material material

Mask:

  1. public bool showMaskGraphic:
  2. protected override void OnEnable()
  3. protected override void OnDisable()
  4. protected override void OnValidate():編輯器用

MaskableGraphic:

  1. public bool maskable
  2. protected override void OnTransformParentChanged()
  3. protected override void OnCanvasHierarchyChanged()
  4. public virtual void RecalculateMasking():為此元素和所有子元素重新計算遮罩。

觸發SetAllDirty,全改變

Image間接繼承自Graphic,當它的Sprite發生變化時,會調用SetAllDirty函數
SetAllDirty改變時機

Graphic:

  1. protected override void OnTransformParentChanged() 父物體改變
  2. protected override void OnEnable()
  3. protected override void Reset():賦值默認值,只在編輯器下有用,可無視
  4. protected override void OnDidApplyAnimationProperties():動畫屬性改變
  5. protected override void OnValidate():脚本加載或Inspector中的任何值被修改時會調用,只在編輯器下有用,可無視

Image:

  1. static void RebuildImage(SpriteAtlas spriteAtlas) 圖集改變
  2. sprite屬性改變
  3. overrideSprite 臨時修改圖片
  4. public override void SetNativeSize() 設置大小

Text:

  1. public void FontTextureChanged():字體紋理被修改:TTF動態字體,Text每次賦值的時候Unity會生成貼圖,以及保存每個字的UV信息,那麼顯示字體的時候根據UV信息去生成的貼圖裏取最終渲染在屏幕上。
  2. font屬性更改

版權聲明
本文為[四夕立羽]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2022/204/202207230540018823.html

隨機推薦