文章目录

  • 1. Canvas的三种模式
  • 2. 两个相同模式的canvas之间的显示
  • 2-1 都是ScreenSpace-Overlay
  • 2-2 都是WorldSpace
  • 2-3 都是ScreenSpace-Camera
  • 3. 两个不同模式的canvas之间的显示
  • 3-1 ScreenSpace-Overlay与WorldSpace
  • 3-2 ScreenSpace-Overlay与ScreenSpace-Camera
  • 3-3 ScreenSpace-Camera与WorldSpace
  • 4. 总结


之前做了一下三维物体的显示层级测试,这一章做一下Canvas之间的相互显示。

如果直接看最后的总结,可以点击这里:
在Unity的UGUI系统里使用Renderer的显示层级研究 (零) 规律总结

1. Canvas的三种模式

canvas的显示有三种显示模式,也就是WorldSpace、ScreenSpace-Overlay、ScreenSpace-Camera:

  1. ScreenSpace-Overlay
    这种模式是Canvas的默认模式,在Canvas上的Graphic物体都会先显示在Canvas上然后盖在渲染完成之后的三维空间图像的最上层,并且永远跟相机保持相对静止。
  2. WorldSpace
    顾名思义,也就是把一整个Canvas当成一个三维物体在三维空间中来显示,与相机不存在位置上的关联关系,把它身上的所有对象显示完成后当成一个物体来显示。
    在这种模式下,Canvas会有一个参数,sortingOrder(在Inspector中显示为Order In Layer),与Renderer的sortingOrder相同。
  3. ScreenSpace-Camera
    这可以算是与前两种模式的结合,既存在三维物体的位置,但也会与相机相对静止,并且也有sortingOrder参数。

同一个canvas之内的UGUI组件会使用在Canvas之内SiblingIndex参数来层级的渲染,但是多个Canvas之间的渲染顺序是怎么样的?这一节就来做一下测试。

因为有三种显示方式,所以可能存在多种情况:

1. 两个相同模式的Canvas的显示方式:
	都是ScreenSpace-Overlay、
	都是WorldSpace、
	都是ScreenSpace-Camera;
2. 两个不同模式的Canvas的显示方式:
	ScreenSpace-Overlay与WorldSpace,		
	ScreenSpace-Overlay与ScreenSpace-Camera,
	ScreenSpace-Camera与WorldSpace;

下面逐个验证

2. 两个相同模式的canvas之间的显示
2-1 都是ScreenSpace-Overlay

我们知道,ScreenSpace-Overlay模式下,UI会自动拉伸布满整个显示区域,所以如果有两个同为ScreenSpace-Overlay模式的canvas,那么肯定会出现一个覆盖另一个的情况。

首先创建两个canvas,结构如下:

unity onpostrender unity onpostrender在canvas上_渲染器

  1. 当两个canvas的SortingLayerr相同时
    在这种情况下,canvas之间的层级关系受两个参数影响,一是加入scene的先后顺序,另一个是active的顺序。
    加入scene越早的canvas在屏幕上显示的层级越靠近用户,越晚active的canvas越靠近用户。
    1-1 加入scene的影响,在上面图里的两个canvas中,canvas-3加入更早,canvas-4加入更晚,运行效果如下(注意,这与在editor中如何显示无关,一旦进行runtime,就会进入这个初始状态):
  2. unity onpostrender unity onpostrender在canvas上_ugui_02

  3. 1-2 修改active的值会使最后被active的显示在最上层,这里我修改了一个canvas-4的显示
  4. unity onpostrender unity onpostrender在canvas上_unity_03

  5. 当两个canvas的SortingLayerr不相同时
    经过第一节的测试,这应该是最稳定的方式了,SortingLayerr越大的,越在上层。这里我修改了canvas-4的SortingLayerr:
  6. unity onpostrender unity onpostrender在canvas上_unity_04

2-2 都是WorldSpace

首先我们知道WorldSpace本质上是将这一整个canvas放到世界坐标系中进行渲染,所以需要增加考虑的参数多了一个——相对camera的景深位置。
经过测试,在ScreenSpace-Overlay中先加入显示在最上层的效果已经没有了,毕竟是在WorldSpace下,存在固定的位置关系。

  1. Order In Layer的控制效果仍然正常,此时canvas-3的Order In Layer为0,canvas-4的Order In Layer为1:
  2. unity onpostrender unity onpostrender在canvas上_渲染器_05

  3. 也可以使用位置关系来控制,这里我把canvas-4的z轴位置修改成了-102,显示就到了canvas-3之上:
  4. unity onpostrender unity onpostrender在canvas上_ugui_06

  5. 需要注意的是,由于canvas是一个z轴深度为0的渲染对象,所以要想做到把一个canvas夹在另一个canvas的两张图中间是不可能的,要么这个canvas完全显示在其中一个之上,要么完全显示在另一个下面。
    此外,也是由于WorldSpace的原因,Z轴距离不同,如果Camera是Perspective的,会存在近大远小的情况。
  6. Order In Layer的优先级要高于位置关系,可以看下面两张对比图,canvas-4的Z轴位置为-700,canvas-3的位置为-900,一开始两者的Order In Layer都为0,第二张图我把canvas-3的Order In Layer修改为了-1。
  7. unity onpostrender unity onpostrender在canvas上_渲染器_07


  8. unity onpostrender unity onpostrender在canvas上_unity onpostrender_08

2-3 都是ScreenSpace-Camera

ScreenSpace-Camera是一个结合了WorldSpace和ScreenSpace-Overlay两者特点的模式,它既会跟ScreenSpace-Overlay一样自动填充整个显示区域,也会跟WorldSpace存在景深关系,不过Z轴位置不能直接调整,而是通过canvas上的PlaneDistance来控制的,可以看到的是PlaneDistance和Z轴数值之间存在一定的关系,这个关系跟摄像机的参数相关。

unity onpostrender unity onpostrender在canvas上_优先级_09


unity onpostrender unity onpostrender在canvas上_unity_10

  1. 首先还是Order In Layer,还是一样,数值越大,越在上层:
    下图中PlaneDistance均为100,Canvas-3和Canvas-4的Order In layer分别为0和1,可以发现,Canvas-4显示在更上层。
  2. 顾名思义,Plane Distance的意思就是平面距离,也就是Canvas和Camera之间的距离,通过Plane Distance来进行控制,也可以达到在WorldSpace模式下的层级效果,这个值越小,距离Camera越近,那么显示的位置也就越上层:
    下图中Order In layer均为0,Canvas-3和Canvas-4的PlaneDistance分别为100和60,可以发现,Canvas-4显示在更上层。
  3. 冲突测试——当PlaneDistance和Order In Layer出现冲突时,Order In Layer的优先级更高
    下面图中,Canvas-3的PlaneDistance为60,OrderInLayer为0;Canvas-4的PlaneDistance为100,OrderInLayer为1。

3. 两个不同模式的canvas之间的显示
3-1 ScreenSpace-Overlay与WorldSpace

我们知道ScreenSpace-Overlay模式是会覆盖在最上层,而WorldSpace显示在正常渲染空间中,所以很容易想到的是,WorldSpace会被渲染在下层显示如下:

unity onpostrender unity onpostrender在canvas上_优先级_11


但是问题在于OrderInLayer是否还有效?,我这里把Canvas-4 - overlay的OrderInLayer修改为1,而Canvas-4 - overlay的SortingLayer保持为0,可以看到的是,这个修改没有发生任何变化 ,Canvas-4 - overlay仍然显示在最上层。

unity onpostrender unity onpostrender在canvas上_优先级_12

3-2 ScreenSpace-Overlay与ScreenSpace-Camera

ScreenSpace-Camera本质上还是在WorldSpace中显示,可以预期的是,显示效果还会与上面的情况相同。

unity onpostrender unity onpostrender在canvas上_unity onpostrender_13

3-3 ScreenSpace-Camera与WorldSpace

因为这两者都是在WorldSpace中渲染,那么Z轴的值就成为了一个需要考虑的因素。

  1. Z轴位置的影响
    在SortingLayer都为0的情况下,将Canvas-4 - world的Z轴位置调整为-800,Canvas-3 - camera的Z轴位置通过PlaneDistance调整到-754.2,发现Canvas-4 - world显示在上层,说明Z轴也可以控制这两者的层级。
  2. Order In Layer 的影响
    保持上面的位置不变,直接修改之间显示在下层的Canvas-3 - camera的SortingLayer为1,发现Canvas-3 - camera显示到了上层,说明SortingLayer优先级高于位置:
4. 总结

总的来说,会影响到两个Canvas之间的渲染层级的参数有下面几个:是否是Overlay模式、SortingLayer、Z轴位置,这几点的优先级是Overlay模式最高,如果不是Overlay模式,那么SortingLayer优先级更高,最后是Z轴位置控制显示。