【Unity】UGUI中Camera Depth,Canvas Sorting Layer、Order in Layer与Particle System渲染层级分析

目录

前言

一、项目需求

二、Camera

1.Clear Flags

2.Culling Mask

 三、Canvas

1.Sorting Layer

2.Order in Layer

四、Particle System

扫描二维码关注公众号,回复: 14694726 查看本文章

1.Sorting LayerID 与Order in Layer

总结


前言

        最近在做项目的过程中,发现项目中的部分3d模型会被粒子特效所遮挡,这并不是笔者想要的效果,于是经过一番面向百度编程,了解到了一些解决方案,本篇博客就记录一下所学到的新知识,如果有错误之处,还望各位读者朋友指正。


一、项目需求

        最近在做项目的过程中,发现项目中的部分3d模型会被粒子特效所遮挡,这并不是笔者想要的效果,于是经过一番面向百度编程,了解到了一些解决方案,本篇博客就记录一下所学到的新知识,如果有错误之处,还望各位读者朋友指正。

        这样的需求看起来非常绕,我们直接通过下图进行直观理解:

      

        通过该图我们就可以发现,要实现这样的需求就要求我们需要提前做好渲染层级的规划,避免层级间的相互影响。我们主要会通过设置Camera的Clear Flags、Culling Mask、Depth和Canvas的Sorting Layer、Order in Layer,以及Particle System中Renderer的Sorting Layer ID、Order in Layer进行处理。

        我们可以通过以3d模型为中点将上面的需求分为3个部分进行处理,第一部分是背景、UI、粒子特效、UI,第二部分则是3d模型,第三部分是UI、粒子特效、UI。

二、Camera

1.Clear Flags

        在一般的3d游戏中,我们通常会为场景和UI分别设置不同的摄像机,分别用来显示场景与UI。这里我们将场景摄像机用来显示3D模型,首先我们将其Clear Flags设置为Depth only,之后我们新建一个Camera,命名为UICamera0,同样将其Clear Flags设置为Depth only。

        场景摄像机:

        UICamera0:

        此处Camera的Depth越大,该摄像机渲染的画面会显示在越上层,会将Depth比它小的摄像机的渲染画面覆盖。。

2.Culling Mask

        Culling Mask设置的目的是可以使摄像机只渲染选中的Layer对象层。这里我们添加一个Canvas,命名为Canvas0,并向其中添加Image,命名为Background,做为最底层背景图。将Canvas0的Render Mode设置为Screen Space-Camera,并将UICamera0赋给Render Camera。注意此时UICamera0的Projection应设置为Orthographic(正交模式),避免近大远小的现象。

        之后,我们通过添加不同的Layer来让不同的Camera渲染相应的对象层。此处我们使用默认的UI Layer来处理第一部分的背景、UI、粒子特效、UI,添加Model Layer来处理3d模型,添加UI1 Layer来处理第三部分的UI、粒子特效、UI。如下图添加两个Layer:

        

 扩展:下图是默认Layer层的描述

注意:Unity编辑器的预览窗口机制在内部使用了第31层Layer,为了防止冲突,不用使用这一层!

        之后将Main Camera的Culling Mask设置为Model,让其只渲染3d模型,将UICamera0的Culling Mask设置为UI,让其只渲染第一部分的背景、UI、粒子特效、UI。

        

  

        此时,Game窗口显示如下: 

        我们发现,3d模型被Background Image遮挡,这是因为我们还没有设置两个摄像机的Depth,UICamera0(创建时默认为0)的深度大于MainCamera的深度(创建时默认为-1),因此背景会覆盖在3d模型上方,将UICamera0的Depth设置为0,MainCamera设置为1,这样显示就为3d模型在Background Image上层了,如下图:

扩展:例如在FPS游戏中,如果要绘制玩家的枪支而不使其陷入环境中,可以设置一个Depth为0的摄像机来绘制环境,并设置另一个Depth为1的摄像机来单独绘制武器,将武器的Layer设置为一个单独Weapon层,将武器摄像机的Clear Flags设置为Depth Only,Culling Mask设置为只渲染Weapon对象层。这样将在屏幕上保持环境的图形显示,但丢弃相关对象在3d空间中所处位置的所有信息。绘制枪支时,不透明部分将完全覆盖所绘制的任何对象(不论枪支与墙壁的接近程度如何)。

 三、Canvas

1.Sorting Layer

        Sorting Layer的作用主要用于改变Canvas的渲染顺序,在Hierarchy中创建的Canvas,Unity默认自上而下渲染,位置越靠后的Canvas将渲染在靠前位置的Canvas之上,但有时我们需要让位置后靠后的Canvas先进行渲染或者让位置靠前的Canvas后渲染,此时就要用到Sorting Layer。

        我们在Canvas0中添加一个UI0_0和UI0_1的Image,如下图:

        

        此时,我们可以看到UI0_0覆盖住了UI0_1的大部分画面:        

        我们可以通过设置Sorting Layer来解决。添加如下Sorting Layers:

        Sorting Layers中Layer 1设置为UI0_0,主要用于Hierarchy中的UI0_0,Effect用于第一部分夹在两个UI中的粒子特效,UI0_1主要用于Hierarchy中的UI0_1,让其最后进行渲染。我们将向UI0_1添加Canvas组件,并勾选Override Sorting属性,此时会发现多出来Sorting Layer与Order in Layer属性。        

        此时,我们发现UI0_1渲染到了最上层,如下图:        

          这是因为在UI0_1在勾选了Overrides Sorting属性后,Sorting Layer 默认为Defalut,Order in Layer默认为0,而此时Canvas0的Sorting Layer也为Default,Order in Layer为0(UI0_0没有单独添加Canvas,因此其归属于Canvas0,属性也就和Canvas0相同)。它们两个的属性就完全相同了,可是因为UI0_1的Canvas在Hierarchy中的层级比Canvas0的靠后,因此UI0_1便渲染到了最上层。

        回到正文,我们将UI0_1的Sorting Layer设置为UI0_1,就得到需求所要的正确结果了,如下图:

2.Order in Layer

        Order in Layer用于相同Sorting Layer层级的内部渲染顺序,越靠后的越晚渲染,这样配合Sorting Layer可以形成两级排序。当然,配合上多个UICamera就形成了三层排序,但在实际使用中还是应该尽量避免使用过多的Camera。

拓展:UGUI会自动合并批次,原理是它会把一个Canvas下的所有元素合并在一个Mesh里,如果Canvas下的元素很多,任意一个元素发生位置、大小的改变,就需要重新合并所有元素的Mesh。如果元素非常多的话,就可能会造成卡顿。
一个比较好的做法是每个UI界面都设置成一个Canvas。如果这个界面下的元素比较多,可以考虑嵌套多几个Canvas。尤其是会频繁改变位置大小的元素,这样可以降低它们合并Mesh的开销。但是Canvas嵌套太多也不好,Mesh合并是降低了,但是DrawCall又上去了,因为每个Canvas都会单独占用一个DrawCall。

        在此处,我们额外创建一个UICamera1和Canvas1,用作第三部分UI、粒子特效、UI效果的实现,这里我们会采用Order in Layer的方式来实现。将Canvas1与UICamera进行绑定,添加一个UI1的Layer,添加一个UI1的Sorting Layer,进行如下图设置:

 

        在Canvas1中添加Fir0与Fir1两张Image,如下图:    

                                               

                      

        此时Fir0的图像在Fir1图像的后面,我们可以通过向两个Image添加Canvas,并勾选Overrite Sorting属性,之后将它们的Sorting Layer设置于同一层,并用Order in Layer进行内部排序,即可让Fir0显示在Fir1上方,如下图:

 

四、Particle System

1.Sorting LayerID 与Order in Layer

        Particle System的Sorting LayerID与上述作用相同,同样是可在不同Canvas中改变其渲染顺序。而Order in Layer则是相同Sorrting Layer中的内部排序,在此不再赘述,直接看案例。

        在Hierarchy中添加FX_Fire粒子特效,将其拖到UI0_1与UI0_0的结合部,Layer设置为UI,只在UICamera0中进行渲染,打开Particle System中的Renderer,将其Sorting LayerID设置为Effect,这样火焰特效即会在UI0_1与UI0_0中间进行渲染,如下图:

 

        为了与第一部分的背景、UI、粒子特效、UI效果进行对照,我们再往Hierarchy中添加一个命名为Display的Canvas,其创建与设置与Canvas1相似,但是Slider Image使用额外创建的Sorting Layer,如下: 

 

 

 

 

        最后我们需要在Display的Bar与Slider图像中间加入一个粒子特效,形成第三部分的UI、粒子特效、UI效果。向场景中添加FX_Smoke粒子特效,并将位置设置与UI结合处,将其Sorting Layer ID设为Effect1,如下图:

        通过上述操作,最终就得到我们想要的效果啦!


总结

1.渲染排序级别:Camera Depth>Canvas Sorting Layer>Canvas Order in Layer。

2.同时要注意区分Layer与Sorting Layer,在UI中,Layer主要用于Camera的Culling Mask,用于渲染选中的对象层,而Sorting Layer则是可以改变Canvas节点的渲染顺序。而Sorting Layer与Order in Layer的关系是当在同一Sorting Layer中时,Order in Layer负责其内部排序。Sorting Layer与Order in Layer可以组成二级排序,如果再配合上Camera的Depth则可构成三级排序。

3.Particle System的Renderer中也有Sorting LayerID,Order in Layer,其用法与Canvas中一致。

        好啦,以上就是笔者要分享的内容啦!真是万万没想到呀,简简单单的一篇博客竟然花了两天的空余时间来完成,看来UGUI中需要深入了解学习的知识还是有很多的,后续如果有遇到新的、有趣的问题,我也会用博客进行记录的。最后希望这篇博客能够对大家有所帮助!

猜你喜欢

转载自blog.csdn.net/weixin_43057990/article/details/128549279