文章目录
一. 前言
Unity
游戏开发中,模型、界面、特效等等,需要规划好层的概念,涉及到摄像机(Camera
)、画布(Canvas
)、Shader等相关内容。
二. 摄像机(Camera)
一般3D
游戏项目,会创建至少两个摄像机,一个3D
摄像机(使用透视视角)和一个UI
摄像机(使用正交视角)。
1. 3D摄像机
2. UI摄像机
3. 摄像机的Depth和Clear Flags设置
一般UI
摄像机的Depth
要大于3D摄像机的Depth
,这样才能使UI
在3D
摄像机渲染的物体的前面显示。
摄像机的Clear Flags
建议使用Depth only
,然后在Culling Mask
选择相应的层(Layer
)。
比如3D摄像机的Culling Mask
如下:
UI
摄像机的Culling Mask
如下:
这个Culling Mask
的下拉列表中就是一个个的层(Layer
),如果要添加新的层,可以点击Inspector
窗口中的Layer
,然后点击Add Layer...
进行添加。
创建3D
物体或UI
界面的时候,都会设定物体的Layer
,3D
物体默认是Default
层,UI默认是UI
层。
摄像机会根据Depth
从小到大的顺序,渲染各自Culling Mask
的层。
注意,在世界坐标下,物体A挡在物体B前面,但是只要渲染物体A的摄像机的Depth
大于渲染物体B的摄像机的Depth
,那么在Game
视图中看到的效果就是物体B挡在物体A前面,如果物体A和物体B同在一个摄像机中渲染,那么正常情况下就是物体A挡住物体B(这里说正常情况下,是因为还可以通过下文的RenderQueue、SortingLayer、SortingOrder等的设置,让物体B挡在物体A前面)。
三. 画布(Canvas)
UGUI
中,所有UI
元素都必须在画布(Canvas
)的子节点中。Canvas
的Render Mode
一般是使用Screen Space - Camera
模式,把UICamera
赋值给Canvas
的Render Camera
。
这个时候,可以看到Canvas
的面板中,出现了两个关键的属性:Sorting Layer
、Order in Layer
。
1. Sorting Layer
添加Sorting Layer
可以点击Inspector
窗口的Tag -> AddTag -> SortingLayer
然后Canvas
就可以在Sorting Layer
中看到新加的Sorting Layer
了(有点绕口)
为什么要有这个Sorting Layer
呢,因为我们可以创建很多个Canvas
,默认Sorting Layer
是Default
,这个时候,渲染顺序是根据Canvas
的节点在Hierarchy
窗口中的顺序来决定的,上层的节点先渲染,下层的节点后渲染。
而有时候,可能需要打破这个顺序,让上层节点的Canvas
后渲染,这个时候,就可以设置这个Sorting Layer
为高的值,当然,也可以保持相等,通过设置Order in Layer
。
拓展:UGUI会自动合并批次,原理是它会把一个Canvas下的所有元素合并在一个Mesh里,如果Canvas下的元素很多,任意一个元素发生位置、大小的改变,就需要重新合并所有元素的Mesh。如果元素非常多的话,就可能会造成卡顿。
一个比较好的做法是每个UI界面都设置成一个Canvas。如果这个界面下的元素比较多,可以考虑嵌套多几个Canvas。尤其是会频繁改变位置大小的元素,这样可以降低它们合并Mesh的开销。但是Canvas嵌套太多也不好,Mesh合并是降低了,但是DrawCall又上去了,因为每个Canvas都会单独占用一个DrawCall。
注意:到这里,应该明白了Layer与Sorting Layer无关,它们是两个概念。
2. Order in Layer
Order in Layer
顾名思义,就是Sorting Layer
的内部排序,这样配合Sorting Layer
就是两级的排序,可以解决大部分情况的渲染顺序需求。
当然,如果创建多个UI
摄像机,不同Canvas
绑定不同的UI
摄像机,再配合摄像机的Depth
,就是三级排序,但一般不创建太多的UI
摄像机,除非逼不得已。
小结: 渲染排序级别:Camera的Depth > Canvas的Sorting Layer > Canvas的Order in Layer
另外,ParticleSystem
也有Sorting Layer
和Order in Layer
。
四. Shader的RenderQueue
Unity
提供给我们一些默认的渲染队列,每一个对应一个唯一的值,来指导Unity
绘制对象到屏幕上。这些内置的渲染队列被称为Background, Geometry, AlphaTest, Transparent, Overlay
。这些队列不是随便创建的,它们是为了让我们更容易地编写Shader
并处理实时渲染的。
示例
Tags{ "RenderType" = "Geometry" }
在材质球中可以看到显示。
Properties | Value | 渲染队列描述 | 备注 |
---|---|---|---|
Background | 1000 | This render queue is rendered before any others. | 这个队列通常被最先渲染(比如 天空盒)。 |
Geometry | 2000 | Opaque geometry uses this queue. | 这是默认的渲染队列。它被用于绝大多数对象。不透明几何体使用该队列。 |
AlphaTest | 2450 | Alpha tested geometry uses this queue. | 需要开启透明度测试的物体。Unity5以后从Geometry队列中拆出来,因为在所有不透明物体渲染完之后再渲染会比较高效。 |
GeometryLast | 2500 | Last render queue that is considered “opaque” | 所有Geometry和AlphaTest队列的物体渲染完后 |
Transparent | 3000 | This render queue is rendered after Geometry and AlphaTest, in back-to-front order. | 所有Geometry和AlphaTest队列的物体渲染完后,再按照从后往前的顺序进行渲染,任何使用了透明度混合的物体都应该使用该队列(例如玻璃和粒子效果) |
Overlay | 4000 | This render queue is meant for overlay effects. | 该队列用于实现一些叠加效果,适合最后渲染的物体(如镜头光晕)。 |
当RenderQueue
填-1是使用shader
自定义的值,否则使用手动填的值。
2500是关键值,它是透明跟不透明的分界点。
知识点:
RenderQueue > 2500
的物体绝对会在RenderQueue <= 2500
的物体前面,即渲染时RenderQueue
大的会挡住RenderQueue
小的,不论它的Sorting Layer
和Order in Layer
怎么设置都是不起作用的。
当两个的RenderQueue
都在同一侧时,在Sorting Layer
高的绝对会在Sorting Layer
前面,无视RenderQueue
跟Order in Layer
,只有在Sorting Layer
相同的前提下,Order in Layer
高的会在Order in Layer
低的前面,无视RenderQueue
。当Sorting Layer
跟Order in Layer
相同时,才看RenderQueue
的高低,高的在前面。