前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Unity3d:UGUI源码,Rebuild优化

Unity3d:UGUI源码,Rebuild优化

作者头像
立羽
发布2023-08-24 15:32:13
发布2023-08-24 15:32:13
74300
代码可运行
举报
文章被收录于专栏:Unity3d程序开发Unity3d程序开发
运行总次数:0
代码可运行

Image怎么绘制的

Unity中渲染的物体都是由网格(Mesh)构成的,而网格的绘制单元是图元(点、线、三角面) 绘制信息都存储在Vertexhelper类中,除了顶点外,还包括法线、UV、颜色、切线。

Rebuild概念

Canvas负责将子节点的UI元素的网格合并,并生成相应的渲染指令再发送到Unity的图形管道的过程。所以Canvas就是渲染UI的组件,当UI发生变化就要执行一次Batch,它是影响性能更大的元凶。注意Canvas的Batch只会影响其子节点,但不会影响其子Canvas。

Rebuild的程序流程

  1. Image,Text都是继承Graphic,Graphic有ICanvasElement接口,实现rebuild函数
代码语言:javascript
代码运行次数:0
复制
   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事件,这个事件会在渲染前进行每帧调用
代码语言:javascript
代码运行次数:0
复制
   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属性更改
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-03-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Image怎么绘制的
  • Rebuild概念
  • Rebuild的程序流程
  • 何时加入重建
    • 布局重建:位置或者大小 ;
    • 图像重建:顶点变化,材质变化(大小,旋转以及文字变化、图片的修改)
  • 优化
  • 源码中查看影响重建因素
  • 触发SetLayoutDirty
    • Graphic:
    • Image:
    • Text:
  • 触发SetVerticesDirty:顶点变化
    • Graphic:
    • Image:
    • RawImage:
    • Shadow:
    • Text:
  • 触发SetMaterialDirty:材质改变
    • Graphic:
    • Mask:
    • MaskableGraphic:
  • 触发SetAllDirty,全改变
    • Graphic:
    • Image:
    • Text:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档