返回 登录
4

Unity 开发 2.5D 游戏的精灵层级顺序设置

所谓 2.5D 游戏,就是利用技术手段让 2D 精灵图片呈现 3D 视觉效果。今天这篇文章,将由 2.5D 游戏《A Place for the Unwilling》开发者 Martín Pane,为大家分享在 Unity 5 中实现游戏场景中各精灵层级规划与遮挡的过程。

开发《A Place for the Unwilling》游戏第一部要解决的问题就是让精灵可以围绕其它精灵前后移动,呈现出真实的深度感觉。SpriteRenderer 组件有两个属性,可以改变场景中 Sprite 的渲染顺序。

  • Sorting Layer
    用于设置不同层的 Sprite 渲染顺序
  • Order in Layer
    用于设置在同一层中的 Sprite 渲染顺序

如果想实时改变多个 Sprite 的渲染顺序,就需要修改一些属性以便无论精灵在场景中如何移动,均以正确的顺序渲染。由于“Oder in Layer”属性仅接受整型参数,所以利用 Z 轴似乎是个更好的选择。

Unity 中 Sprite 的渲染优先级如下图,从高到低:

如果两个 Sprite 的“Sorting Layer”和“Order in Layer”均相同,那么在 3D 世界坐标中离相机更近的 Sprite 会被先渲染。

在明白了 Sprite 的渲染顺序后,接下来只要写个简单的脚本更改 Sprite 坐标的 Z 值为与其 Y 值成固定比例即可。但在此之前,先来解释一个重要的小概念,即如何设置精灵位于地面的底部。这里“底部”就是指 3D 世界中对象与地面接触的部分,示例如下:

我们要做的是在改变 Sprite 坐标 Y 值的同时改变其 Z 值,上图在 3D 环境的效果如下图:

理解了以上内容,就可以写脚本了,代码如下:

首先需要设置的是“Floor Height”,该属性决定 Sprite 的下边界在 Y 方向的偏移。 在 3D 世界坐标中,它用于设置 Sprite 在场景中的 Z 深度。 如果一个 Sprite 的底部比其它 Sprite 更高,它将被渲染在其它 Sprite 后面。

然后存储 Sprite 高度与宽度的半值,以便对 Z 坐标进行一些简单的数学运算。在《A Place for the Unwilling》游戏中使用了 30 度的等距切角,但您也可以将 Z 坐标设为与 Y 坐标一致,不影响游戏效果。

这里使用 OnDrawGizmos 方法在当前的地面高度绘制一条线,以便可以在编辑器中设置为最终的精确位置。另外,对于有些游戏运行后永远不会移动的对象,可以使用“if(!Application.isPlaying)”和“#if UNITY_EDITOR”条件在运行时保存计算结果,因为可能会有上百个 Sprite 同时绑定该脚本。

以上设置完成后,就可以在场景中移动 Sprite 并保证渲染顺序正常了,但还有两种情况需要更多的设置。

在处理中心不在中间位置的 Sprite 时,需要将其分为几部分。以下面的建筑为例,由于它的底部是矩形,如果整个建筑仅设置一个 Floor Height 值,那角色将只能沿着它前方的那面行走,并且会遮挡角色!为了解决这个问题,就需要将建筑 Sprite 分为两个部分,并为每一边设置不同的地面,如下图:

另一种情况是将某个 Sprite 作为另一个的子对象时。仍然以建筑为例,如果想为建筑增加窗户或招牌,这些附加物就不能使用与建筑相同的脚本,因为有些窗户可能位于建筑后面或顶部。这个问题很容易解决,只需创建建筑的子对象重置其坐标,并将 Z 值设为 -0.001,然后将所有需要附着在建筑上物体放置于该子对象下,将这些物体的 Z 坐标设为 0,这样就可以与实际建筑保持 0.001 的距离,并且它们离相机更近。

最终 3D 环境下的完整场景如下:

Unity 引擎本身就已经提供了非常灵活的工具来实现这样的功能,下面来看看这种实现方式存在的一些限制,以及一些有助于改进工作流程的扩展方法。

这种实现方式最大的限制就是制作很薄的墙壁时,因为使用该方法必须将 Sprite 切割为多个与墙壁厚度一致的部分,以便场景中的物体可以在墙壁前后移动。示例如下:

对于飞行物来说可能也比较麻烦,但如果注意其摆放的位置就可以避免出现问题。还可以通过修改 Sorting Layer 的值让它们永远位于场景主要对象的前方或后方。

最后分享一下如何扩展这种方式以适用更多的场景。Isometric Colliders: 根据角色在游戏中的移动方式,实现一个小脚本为角色创建一个与游戏场景的图片摆放角度一致的碰撞体。

IsoVector 类:该类包含一些常用的方向向量(N,W,E,S,NE,NW,SE,SW),以及从自定义方向获取向量(反之亦然)的方法,或者获取给定方向的反向向量(例如输入南获取北)等。

本文介绍的内容不一定是最佳的解决方案,但也展现出了很好的学习思路,从最开始想到编写脚本调整 Sprite 的 Z 值来正确渲染一切对象,解决了一开始构建游戏场景的问题。随着继续扩展代码库,也丰富了一些自定义类来加入新功能,同时维护好项目结构。希望这篇文章对正在使用 Unity 开发这种等距游戏的开发者有帮助。


Unite 2017 Shanghai 即将于5月11-13日在上海国际会议中心举行!目前5折个人通票已经开售,三人团购还可享受8折优惠!技术专场内容抢先看!更多信息请访问 Unite 2017 Shanghai 官方网站。

评论