Unity 中渲染顺序的理解以及一些坑点 以及2.5D游戏中的渲染排序解决方案

1.ZTest & ZWrite

ZTest:深度测试,开启后测试结果决定片元是否被舍弃,可配置 
ZWrite:深度写入,开启后决定片元的深度值是否写入深度缓冲,可配置

ZTest可设置的测试规则:

ZTest Less:深度小于当前缓存则通过
ZTest Greater:深度大于当前缓存则通过
ZTest LEqual:深度小于等于当前缓存则通过
ZTest GEqual:深度大于等于当前缓存则通过
ZTest Equal:深度等于当前缓存则通过
ZTest NotEqual:深度不等于当前缓存则通过
ZTest Always:不论如何都通过
注意,ZTest Off等同于ZTest Always,关闭深度测试等于完全通过。

ZWrite配置: 
ZWrite On 深度写入开启 ZWrite Off 深度写入关闭

ZTest和ZWrite发生在逐片元操作过程,处于片元着色后,最终屏幕输出前。ZTest与ZWrite的具体操作流程:

因为ZWrite默认值为On,ZTest默认值为LEqual,所以这很好地解释了为什么在unity中,距离相机近的东西会阻挡住距离相机远的东西。如果我们先绘制一个距离较近的物体,再绘制距离较远的物体,则距离远的物体因为后绘制,会把距离近的物体覆盖掉,这时我们可以通过修改ZWrite和ZTest来改变物体的遮挡关系

所以对于透明物体的渲染,一般要关闭掉ZWrite,比如Unity中用于渲染Sprite的默认SpriteDefault材质的Shader:

加深对ZTest & ZWrite的理解,可以参考这篇文章的测试部分,把各例子理解明白非常有帮助。

https://www.jianshu.com/p/9137ee354dbd

2.Unity渲染顺序

能够影响渲染顺序的因素有:

  • Camera Depth:    相机组件上设置的相机深度,深度越大越靠后渲染。
  • Sorting Layer:     在Tags & Layers设置中可见
  • Order In Layer:    相对于Sorting Layer的子排序,用这个值做比较时只有都在同一层时才有效。
  • RenderQueue:     Shader中对Tags设置的“Queue”。
  • 物体距离相机的距离,ZDepth值

下面是结果:
1、Camera Depth
永远最高。Camera Depth小的一定先进渲染管线。

2、当Sorting Layer和Order In Layer不相同时

  • 当两个材质使用了不同的RenderQueue,且这两个RenderQueue都在[0~2500]或[2501~5000]时,SortingLayer和OrderInLayer的排序生效。
  •  当两个材质使用了不同的RenderQueue,且这两个RenderQueue分别在[0~2500]和[2501~5000]时,则一定会按照RenderQueue绘制,无视SortingLayer、OrderInLayer的排序。

3、当Sorting Layer和Order In Layer相同时

  • RenderQueue不相等:

        RenderQueue小的先进渲染管线。

  •  RenderQueue 相等

        RenderQueue 2500以下,由近到远排序优先 (不透明)

        RenderQueue 2500以上, 由远到近排序优先  (透明)

说明一下:2500是关键值,它是透明跟不透明的分界点,因此我们考虑层级的时候要注意着点:renderqueue > 2500的物体绝对会在renderqueue <= 2500的物体前面,即渲染时renderqueue大的会挡住renderqueue小的,不论它的sortingLayer和sortingOrder怎么设置都是不起作用的。知道了这点,其他的就很好理解了。当两个的RenderQueue都在同一侧时,在SortingLayer高的绝对会在sortingLayer前面,无视renderqueue跟soringOrder,只有在sortingLayer相同的前提下,soringOrder高的会在sortingOrder低的前面,无视renderqueue。当sortingLayer跟sortingOrder相同时,才看renderqueue的高低,高的在前面。

总结下Unity影响渲染顺序各参数的优先级

如果物体的RenderQueue在2500的同一侧:

Camera DepthSorting Layer > Order In Layer > RenderQueue > 距离相机的距离

如果物体的RenderQueue在2500的不同侧:

Camera DepthRenderQueue > Sorting Layer > Order In Layer > 距离相机的距离

3.Unity中的一个坑

PropertiesValue渲染队列描述说明
Background1000This render queue is rendered before any others.这个队列通常被最先渲染(比如 天空盒)。
Geometry2000Opaque geometry uses this queue.这是默认的渲染队列。它被用于绝大多数对象。不透明几何体使用该队列。
AlphaTest2450Alpha tested geometry uses this queue.需要开启透明度测试的物体。Unity5以后从Geometry队列中拆出来,因为在所有不透明物体渲染完之后再渲染会比较高效。
GeometryLast2500Last render queue that is considered “opaque”.所有Geometry和AlphaTest队列的物体渲染完后
Transparent3000This render queue is rendered after Geometry and AlphaTest, in back-to-front order.所有Geometry和AlphaTest队列的物体渲染完后,再按照从后往前的顺序进行渲染,任何使用了透明度混合的物体都应该使用该队列(例如玻璃和粒子效果)
Overlay4000This render queue is meant for overlay effects.该队列用于实现一些叠加效果,适合最后渲染的物体(如镜头光晕)。

从Unity文档中这个图我们可以看出来,Background理应最先被渲染,Unity中的skybox 应该属于这个renderqueue,但是当你实际使用的时候,怪事发生了:

从FrameDebugger中可以看到,对于不透明物体的渲染,skybox是在opaque的最后渲染,从而减少OverDraw。这尼玛不跟RenderQueue写的1000冲突么?!Google一顿操作,结果是这样:

 

 

总结来说就是:Unity关于Skybox部分的文档好久没有更新了,目前Skybox应该是RenderQueue 值为2500.5时渲染,在Opaque和AlphaTest之后,Transparent之前。

Unity这个文档证明了这个说法:https://docs.unity3d.com/Manual/GraphicsCommandBuffers.html?_ga=2.53580588.563516390.1589165101-117244140.1588818896

 

4. 2.5D游戏渲染排序解决方案

上边总结了Unity中渲染顺序的相关知识,那利用这些知识,可以实现2D游戏中景深以及排序的问题,初步总结了几种方案:

1.Order In Layer 

通过设置Order In Layer 为不同的值来进行排序,缺点是需要自定义一套标准来决定物体的Order In Layer值 

下边这个插件用的是这个原理

https://assetstore.unity.com/packages/tools/sprite-management/isometric-toolkit-33032

2.用Shader自定义修改ZDepth

通过自己设置Shader中的ZDepth来达到排序的目的,也就是说Sprite在场景中的Z值都一样,通过制定一套标准,来人为定义物体的ZDepth值 

下边这个插件用的是这个原理

https://assetstore.unity.com/packages/templates/systems/2-5d-isometric-engine-106321

3.利用Z轴,实际就是ZDepth

在场景中把各个Sprite摆放位置根据前后关系设置Z轴位置,这样2D游戏也可以拥有ZDepth的信息,从而可以正确渲染 

4.修改UnityProject 的设置

 改为Y轴为排序轴,这种方法不用考虑Z轴,完全根据Sprite的y轴大小设置,非常简便。我是用的这种方式,暂时的缺点是无法根据sprite大小精确控制排序。

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Unity是一款流行的游戏开发引擎,能够开发各种类型的游戏,包括2.5D游戏。下面将简要介绍Unity开发2.5D游戏的教程。 首先,你需要安装Unity软件,并创建一个新项目。在项目,你可以使用Unity的工具和资源来构建你的游戏。 其次,你需要选择一个适合的2.5D游戏场景。2.5D游戏是指使用2D的背景和角色,但是具有3D的效果和深度感。你可以选择一个平面或者地图作为游戏场景,并添加合适的纹理和贴图来增加细节和美观度。 接下来,你需要创建游戏的角色和物体。你可以使用Unity的2D工具来绘制和设计你的角色和物体,也可以从Asset Store下载和导入已有的角色和物体资源。 然后,你需要为角色和物体添加适当的动画和交互。Unity提供了强大的动画制作工具,通过添加关键帧和动画控制器来创建角色的移动、跳跃和攻击等动作。你还可以使用Unity的C#脚本语言编写代码来实现交互逻辑,例如控制角色的移动和碰撞检测等。 最后,你需要为你的游戏添加声音效果和UI界面。Unity提供了丰富的音效资源和UI工具,可以让你为游戏增添音乐、音效和用户界面等元素,提升游戏的沉浸感和用户体验。 通过以上步骤,你可以完成一个简单的2.5D游戏的开发。当然,你还可以根据自己的需求和创意进一步扩展和完善你的游戏,例如添加关卡和敌人、设计游戏规则和目标等。祝你开发一款成功的2.5D游戏
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值