等距,手机游戏中的z索引及其优化


哈Ha! 最近,我们推出了我们的游戏 ,我们准备了很长时间,在此过程中,积累了许多有趣的主题,值得与社区分享。 这个主题不仅会引起iOS和其他移动开发人员的兴趣,还将引起所有对各种图形事物如何在幕后工作以及所有2D策略爱好者的兴趣,而我本人也是第三个十年。

今天,我们将讨论诸如等距表面上的z索引这样的重要主题的细微差别(是的,并不是所有事情都像某些明智的想法那样简单)。 奇怪的是,在3D世界中,我们具有三个坐标-x,y,z,它们完全确定了物体在空间中的位置。 确定对象与相机的接近度的任务也在那里,但完全由OpenGL承担。 开发人员只能使用会影响性能的高级参数(例如z缓冲区深度)进行操作,但是您可以将OpenGL视为黑匣子-它具有足够的信息。

在我们的“伪3D”世界中观察到了完全不同的情况-每个对象只有(x,y)-子画面的坐标和大小。 程序员在编写引擎时面临的首要任务是确定哪些对象应在我们的虚拟“相机”之前彼此重叠。

剧情简介


SpriteKit坐标(其中(0; 0)是“世界”的中心,Y上升)在这种情况下,我们一点都不感兴趣,因为 它们对我们等距的“世界”没有任何意义,所以让我们保留一下吧-我们有一个钻石形状的领域,例如《帝国时代》。



坐标为(0; 0)的图块位于菱形的左上角,横坐标X分别为“向下”和“右侧”,即 越靠近观察者,纵坐标Y“向上”和“向右”增加,即 随着您接近观察者而减少。

此外,铁轨应位于火车“下方”,烟囱冒出的烟气应位于火车“上方”。 但是,我们现在不会为“存在的层次”而烦恼-显然,没有什么可以阻止我们按照相同的规则制作任意数量的等距“切片”。 我们假设在一个图块中始终只有一个对象-为清楚起见,没有必要再做更多操作。



考虑上面的两列火车。 显然,从观察者的角度来看,轿厢应位于火车“下方”,即 它们的z索引应较小。 同时,“上层”列车应与相邻层“重叠”,“更远”。 仅靠坐标(x; y),我们可以为每个图块构造一个z索引图吗?

显然,是的,使用下面的公式(伪代码一点快):

zIndex = pos.x * field.size.width - pos.y 

因此,我们保证随着纵坐标的增长,对象移开(-pos.y),并且随着横坐标的增加,对象趋近(pos.x),重要的是,任何具有横坐标(例如44)的对象都将故意“靠近” “比具有横坐标43的任何对象都要多。要在此处添加”分层”(请记住,火车下方的铁轨,烟囱上方冒烟),只需在该层添加一些恒定的”高度”即可:

 zIndex = layerZIndex + pos.x * field.size.width - pos.y 

就是这样,您可以结束本文,并赞扬自己在10年级学习的立体学基础知识,并开始游戏逻辑。 不行吗 如果只有! 我会写一些显而易见的事情! (很明显,几天被压垮了,这)

我们只是进入有趣的部分,继续前进。

表现斗争


每个人都至少运行了一个SpriteKit(或椰子,或任何其他引擎)的测试项目,看到了神奇的数字-fps和节点。



显然,fps是每秒的帧数,节点是节点数,主要是精灵。 但实际上,大多数fps并非由节点数设置,而是由另一个参数设置,默认情况下不会显示,但也可以用一行显示-重画的绘制数。



如您现在所见,在同一场景中,节点数约为6000,渲染数约为120。这是最小缩放(相机尽可能靠近曲面),即1:1。

现在,将相机移至最大距离(在我们的游戏中为2.5:1)



我们仅将缩放比例更改了2.5倍(在此示例中,绘制的对象远非所有对象),并且在节点数不变的情况下,绘制次数增加了5-6倍!

当然,渲染数量比抽象节点数量对fps的影响更大。 SpriteKit只是不会绘制未落入视口(进入摄影机)的节点。 到目前为止,我发现的唯一例外是粒子发射器,无论它们是否可见,始终会绘制它们。

现在让我们谈谈这个“绘图”抽奖的含义。 视频卡具有所有节点“层”,并由其z索引引导。 它从最低到最高一次又一次地遍及整个画面。 这样的渲染周期数是绘制。

现在您了解了,如果您用自己的z索引绘制每个微小的对象(并且我们有一个大的地图,大约为6000 x 3000),这将破坏任何手机的性能。

在旧5s和5s上最好看到问题,但是iPhone 10的存在不能保证任何事情-如果使用错误的方法,则可以放弃任何强大的硬件。 在我们的游戏中,基石之一是极其清晰。 在最接近的缩放比例下,一对一的精灵对应于视网膜像素。 我必须说,在大多数手机游戏中,分辨率要低几个数量级,因此要求不是很高,但是我们定性地做到了这一点,就我们自己而言……

因此,您必须掌握窍门。

  • 通常,与播放器不交互且在X坐标处于同一级别的所有对象都可以合并为一个精灵。 对于视频卡,绘制一个大精灵比绘制10个小精灵容易得多。 因此,道路之间的林间小道是由几棵树组成的整体精灵。 不重叠路径的树木和其他树木通常会缝在地图上。 顺便说一句,在Alpha中,几百年历史的橡树正好生长在火车的铁轨下或火车的交通信号灯下,因此存在许多错误,因此请仔细测试您的游戏,以免引起用户的兴趣。
  • 具有一个z索引的对象是按照它们在视频卡上出现的顺序绘制的。 即 在“关闭”对象之前添加“远处”对象,它们会正确掉落,但不会增加图形卡渲染的数量。

所有这些使您可以减少绘制次数,即使在旧iPhone上也可以固定fps。 我不得不严格限制它们的某些效果,但是Apple至今一年都没有发布它们的更新-会抱怨!

高程


好吧,一切就绪,引擎已经准备就绪,您可以开始一些有趣的事情了吗? 有人可以,但这对我们来说还为时过早。 毕竟,火车应该漂亮地离开隧道,并且这里的一切并不像看上去那样简单。



火车的位置应比隧道的“远”壁“高”,比隧道的屋顶和其后的山脉“低”。 毕竟,当地图如此多层次且高程发生变化时,它真是太美了-同样,我们不是在胡说八道,而是我们自己喜欢的东西!

但是回到细节-为此,地图被“裁剪”如下。



隧道的内壁和左侧的其他所有位置都较低,



隧道的顶部以及流入的山脉。 在这里,没有任何程序生成的z索引会有所帮助,只有严格的白俄罗斯语硬编码。

细心的habrayuzer在游戏的屏幕截图中注意到,在隧道附近,树木被“修剪”得整整齐齐,露出了原始的沙滩。 这种看似缺陷来自根本不可能以2D方式实现这种树木种植。 离开隧道的火车必须刻意“重叠”在重叠的树木上方,并用它们自己覆盖。 但是,这些相同的树木应该与隧道的顶部重叠,列车应该在隧道的顶部下车! 而且屋顶应该比火车高,所以一圈,我们有一个逻辑上的矛盾...

出于类似的原因,由于图形引擎的不完善,在诸如Duke Nukem和Doom2之类的旧游戏中,建筑物的高度和楼层没有太大差异。

这就是为什么树木不在隧道附近生长的原因。

我希望这很有趣, 这里住玩具(可以免费玩) ,该系列的下一篇文章将讲述美丽逼真的2D水,不要错过!

附注:顺便说一句,可以在youtube上以正常质量观看吸引人们注意的视频。

PPS到目前为止,该游戏仅在独联体,加拿大和爱尔兰可用,如果有人想从其他国家/地区浏览,请发送带有appleId的个人电子邮件-我将其添加到TestFlight

Source: https://habr.com/ru/post/zh-CN415051/


All Articles