首页 > UI, 其他 > 【UGUI源码分析】四、Canvas

【UGUI源码分析】四、Canvas

2018年11月8日
目录
[隐藏]

Canvas是UI的最上层,负责管理下面子节点UI元素的布局、渲染、排序。Canvas类本身不在UGUI里面实现,包括Canvas, CanvasGroup, CanvasRenderer这几个,在UGUI实现的有CanvasScaler和GraphicRaycaster。本文包含Canvas相关组件和Canvas的更新(Canvas Update System)以及它是如何从最上层管控所有的组件布局和渲染更新的。

Canvas本身是一个抽象的容器,并不会渲染(不是RT!不是RT!不是RT!),用来容纳下面的UI。所有的UI元素都必须在一个Canvas GameObject下。

1. 基本设置

1) Canvas组件

Canvas有3中render mode

简单来说分3种

  • Overlay
  • 相机空间
  • 世界空间

三者的具体介绍看官方文档。Overlay适合做一般的UI\HUD,相机空间适合做头盔显示器、VR,世界空间适合做场景中的交互UI。

Overlay和相机空间中,canvas都会永远朝向相机,世界空间的canvas不需要。稍微解释一下参数的含义

参数 适用于 含义
Pixel Perfect Overlay \ Camera Space 是否开启抗锯齿
Render Camera Camera Space canvas所属的相机空间,射线检测的相机
Plane Distance Camera Space canvas在相机空间中离相机的距离
Event Camera World Space 世界空间中,canvas的GraphicRaycaster射线检测的相机
Sort Order Overlay overlay类型的所有canvas的渲染顺序,决定了下面UI的渲染顺序
Sorting Layer Camera Space \ World Space 对于相机空间和世界空间,会给canvas分不同的sorting layer,不同的sorting layer 按次序先后渲染,同一个sorting order内,按Order in Layer值从小到大先后渲染(后渲染的在上面),一个canvas内,UI元素按照hierachy顺序先后渲染
Order in Layer Camera Space \ World Space 相同sorting layer时,由order in layer决定渲染顺序
Additional Shader Channels Camera Space \ World Space 控制下面的Graphic组件的Mesh数据除了position和UV0之外还可以包含哪些数据,对做UI特效非常必要,比如PositionAsUv1需要开启UV1

2) GraphicRaycaster组件

为了做射线检测,会同时添加一个GraphicRaycaster

参数 含义
Ignore Reversed Graphics 忽略反转背对相机的UI元素的射线检测
Blocking Objects 可以阻断射线检测的物体类型,2D\3D\所有,要求这类物体有Collider组件。在Camera Space 和World Space能体现出来,UI射线检测是否可以穿透3D物体
Blocking Mask 可以阻断射线检测的物体的layer

3) CanvasScaler组件

CanvasScaler不重要,后面布局系统再看。

4) CanvasGroup组件

CanvasGroup用来以canvas为单位一并管理很多canvas下的所有UI元素而不需要一个一个UI元素修改,比如设置透明度。Canvas Group参数改动时会给下面的UI元素(继承了UIBehaviour)发送OnCanvasGroupChanged消息。

参数 含义
Alpha 这个group下的UI元素透明度基数,会和UI元素本身的alpha值相乘
Interactable 这个group下的UI元素是否可交互(射线检测),取消勾选意味着是单纯的HUD
Block Raycasts 这个group下面的UI是否会阻断射线检测,在Camera Space或World Space的canvas可以阻断射线穿透UI到后面的3D物体
Ignore Parent Groups 忽略父canvas group的设置,用这个canvas group的设置覆盖

Canvas Group的用途有

  1. 通过设置alpha,做UI整体的淡入淡出
  2. 设置一个canvas为纯粹显示、不可交互的HUD,避免下面的某个UI元素误勾选raycaster target
  3. 设置一个或几个UI元素不阻断射线检测

5) CanvasRenderer组件

CanvasRenderer用来渲染Graphic类型的UI元素(Image、RawImage、Text三个),每个元素都需要一个CanvasRenderer,其他UI元素不需要加CanvasRenderer组件,可以去掉。

没有可配置参数。CanvasRenderer会做UI基于canvas的剔除、网格提交、材质绑定、渲染,本质上和MeshRenderer做的内容类似。在总结Graphic的时候会涉及。

2. Canvas Update System

Canvas是UI的最上层,会管理下面UI元素的布局和渲染,也就是canvas update system。涉及Canvas类、CanvasUpdateRegistry类、ICanvasElement接口和CanvasUpdate枚举。核心是CanvasUpdateRegistry。

Canvas向外提供了一个事件willRenderCanvases,发生在管线渲染所有canvas之前(也就是每个逻辑帧的最后,仅在渲染之前,这个很重要,这也是为什么布局不会立即重建,而是要等到“下一帧”才会刷新的原因,后面的文章会提到)。CanvasUpdateRegistry向其中注册了一个PerformUpdate方法,这个方法是整个UGUI布局和渲染更新的入口。

CanvasUpdateRegistry维护了两个缓存队列,分别缓存需要更新布局和渲染(网格、材质)的UI元素

当一个UI元素需要更新布局和渲染时就加入对应的队列中,在PerformUpdate方法中对它们进行处理。

与布局和渲染更新有关的方法定义在接口ICanvasElement中

主要是Rebuild(CanvasUpdate  executing)方法,这个方法负责此UI元素的布局或者渲染更新。CanvasUpdate枚举是PerformUpdate的不同阶段

在UI元素实现的Rebuild方法中,switch不同的阶段做不同处理。之所以要分阶段,是因为UI无论布局还是渲染的更新都需要按照一定顺序和阶段,才能保证结果正确。

PerformUpdate()方法

在PerformUpdate()方法中会调用UI元素的Rebuild方法,完成后调用两个Complate方法。

UI元素在必要的时候主动调用Register方法加入队列。以Graphic为例,在以下几种情况下会加入m_GraphicRebuildQueue

  1. OnRectTransformDimensionsChange,即大小改变的时候
  2. OnTransformParentChanged,即父节点层级改变的时候
  3. OnDidApplyAnimationProperties,即通过animation clip改变属性值的时候
  4. 设置材质的时候
  5. OnEnable
  6. OnValidate
  7. Reset

这些情况下,Graphic会调用CanvasUpdateRegistry的Register方法注册进队列,之后就会在管线的willRenderCanvases阶段执行Rebuild。

3. 自定义和扩展

综上所述,如果要自定义UI元素,至少要继承UIBehaviour(或者至少MonoBehaviour)并实现ICanvasElement接口,这样才能完美地更新UI元素的布局和渲染。

 

官方文档

https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/class-Canvas.html

https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/HOWTO-UIWorldSpace.html

https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/HOWTO-UIMultiResolution.html

https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/script-CanvasScaler.html

分类: UI, 其他 标签: