欢迎光临散文网 会员登陆 & 注册

Unity老游戏复刻计划之《超级马里奥兄弟》(2)

2022-11-13 11:25 作者:皮皮关做游戏  | 我要投稿

(本文作者Khalil)

大家好我是Khalil。

上篇传送门:

书接上文。上篇中简单介绍了第一个可交互场景的做法,感觉路途还十分遥远。

不过好在以现在的眼光来看,这类早期的游戏系统不多,大多数情况下都是在有效复用。例如上篇中介绍的金币砖块是会从头出现到尾的,而且其他类型的砖块也可以以它为模板。

以普通的没有道具的砖块为例,金币砖块在被玩家顶出金币后会变为不可弹起的状态,而普通砖块在小马里奥状态下,只要被顶到就会弹起,只要把金币砖块逻辑改一改,贴图换一换,普通砖块就制作完成了。

接下来就要制作会遇到的第一个怪物:酷栗宝。

多说一句,这个怪物就算是官方翻译也不止一种(除了酷栗宝外还有栗宝宝、栗子小子之类的)。不过单纯从发音的角度来看,酷栗宝是最忠实还原的(原名叫クリボー,用中文念着像kulibo),就好比哆啦A梦之于ドラえもん一样。

酷栗宝原始外观和近期外观的对比。可以看出原始版本是没有牙齿的,但“皱着的眉毛表明其威胁性”则是在一开始就确立了的


酷栗宝做起来很简单,添加好刚体、碰撞体,然后身体的左右和下方添加三个子物体,用于发射射线。酷栗宝要击杀玩家就是依靠身体接触,但是玩家踩踏怪物的效果又需要碰撞体的支持,所以这时候就需要依靠射线了。射线碰到玩家后玩家会死亡,而玩家踩踏到怪物时,怪物就死亡,并给玩家提供一个向上的力(模仿弹力)。

这时候可能有朋友会问了,为什么不直接用unity中的弹力呢?我之前试过,在unity自带的物理引擎框架下,玩家要是从不太高的地方落下,那么踩踏怪物几乎不会产生弹力,但是玩家从高处掉落时踩踏到怪物,就会被弹得非常高——这与游戏本身的效果差别非常大。

良好的操作性(包括行走、疾跑、跳跃)是马里奥系列官方引以为傲的特征


最后,让怪物在生成时就向左移动,碰到障碍物时就变向,这样一个酷栗宝就完成了。

另外,我想怪物肯定不是在玩家进入游戏后就开始生成的,不然如何做到玩家每次进入场景怪物都在固定的位置?我的思路是,制作一个怪物生成器,每当玩家走到一定位置,生成器就把作为他的子物体的指定的怪物生成出来。与马老师讨论后他认同了我的想法:怪物可以一开始就放入固定位置,进入游戏后便删除它们,在玩家到指定位置时再将它们生成。

想法有了就立即开始搞。

我先进入原版游戏,仔细观察玩家到了哪个位置哪些怪物会生成,然后回到unity中,将怪物放置到相应的位置,然后开始写怪物生成器的脚本。

然而这时候我犯了一个巨大的逻辑错误。我没有用List进行存储,而是将作为子物体的怪物们一一在Start中获取出来,记录下它们的位置,然后一一在Update中检查玩家是否到了应该生成它的位置,就比如玩家走过了世界x轴中的-9.3这么一个位置,那么就用预制体生成第一个怪物。

这样写,逻辑是简单了,但是写代码很麻烦。因为每次有怪物的地方,我都要去计算玩家到了什么地方它会生成,还得在Start中去获取怪物的位置。明明这个“怪物生成器”听起来就是全自动的,做起来它应该也是全自动的才对。

马老师看了我的做法马上否决了,他建议将所有怪物和怪物的“生成信息”存入一个List中,将怪物们SetActive(false),使其隐藏,直到玩家靠近怪物到10个单元值的时候,怪物就SetActive(true),在场景中出现,以后要生成怪物,只需要将怪物放到怪物生成器下,调整怪物在场景中的初始位置即可,无需调整脚本。

实现效果:

游戏未运行时的场景:


 游戏开始运行后的场景:


玩家靠近怪物后:


在吃到第一个金币,逃过第一个怪物的迫害后,差不多就到下一屏内容了。大家知道场景中的第二个道具砖块弹出的便是能让玩家变大的蘑菇(官方名“超级蘑菇”,スーパーキノコ)。它的行为如下:会缓慢地从砖块中升起,待身体完全展现出来后就会向右方移动,玩家触碰到它时玩家自身就会变大、且蘑菇自身消失。

这个蘑菇向上移动的制作方法其实和砖块的移动方法接近,让蘑菇生成后,在移动到指定位置前,逐帧向上移动,然后在达到指定位置时开始向右移动,要使蘑菇在移动时不受重力和砖块碰撞体的影响,在到达指定位置前,它都为Kinematic状态,到达后就转变为Dynamic状态,最后在碰到玩家时消失。

那么玩家要怎么切换到变大的状态呢?我目前还是使用的最简单的预制体方法。我将大马里奥添加上与小马里奥几乎相同的组件后,制成预制体,在小马里奥吃到蘑菇后,就将小马里奥删除,生成大马里奥即可。

做到这,我又发现了新的问题——严格说算是某个feature的延申:

在游玩游戏时,摄像机会跟随马里奥移动,但不能往回卷轴——这其实是早期横向卷轴游戏的一大feature。而且摄像机的范围还会限制马里奥的移动。而我所说的“新的问题”是:小马里奥被删除后,摄像机并不会跟随大马里奥,因为我没有写摄像机的脚本,而是直接使用的VirtualCamera, 在VirtualCamera中,指定跟随小马里奥这个物体,小马里奥消失了,那么他就不会跟随玩家物体进行移动了。

所以我果断决定将其舍弃(技术不够不要紧,气场要够),使用主摄像机。我创建了一个空物体,将主摄像机作为它的子物体,将摄像机脚本挂在父物体下。摄像机脚本中,和VirtualCamera一样,我定义了一个Target(摄像机跟随的目标),但是它是可以变化的,在小马里奥消失后,将target更改为新诞生的大马里奥,并让摄像机跟随target移动即可。

那么如何让摄像机不往回卷轴、且阻挡玩家向后移动呢?很简单,在摄像机的左边界创建一个“空气墙”,跟随摄像机移动,摄像机不会倒退则它也不会倒退,玩家自然就无法向后移动了。那么如何使摄像机无法倒退?一个简易的方法是:用一个Vector3变量originPosition实时获取摄像机父物体的当前位置(originPostion=transform.position),再用一套非常简单的逻辑来限制它的移动:若此体想要倒退,即此物体位置的x的值会变小,若这个值小于originPosition的x的值,那么此物体的位置就等于originPosition。

这样,就可以限制摄像机和玩家的移动了,做起来很简单。瞅瞅效果图:


工程链接:https://pan.baidu.com/s/1kR2HzO0_6SQoP9ZoMZDcCw

提取码:mali

欢迎加入游戏开发群欢乐搅基:1082025059

对学习游戏开发、游戏制作感兴趣的童鞋,欢迎访问咱们的主页:http://levelpp.com/


Unity老游戏复刻计划之《超级马里奥兄弟》(2)的评论 (共 条)

分享到微博请遵守国家法律