Unity老游戲復(fù)刻計劃之《超級馬里奧兄弟》(2)
(本文作者Khalil)
大家好我是Khalil。
上篇傳送門:

書接上文。上篇中簡單介紹了第一個可交互場景的做法,感覺路途還十分遙遠(yuǎn)。
不過好在以現(xiàn)在的眼光來看,這類早期的游戲系統(tǒng)不多,大多數(shù)情況下都是在有效復(fù)用。例如上篇中介紹的金幣磚塊是會從頭出現(xiàn)到尾的,而且其他類型的磚塊也可以以它為模板。
以普通的沒有道具的磚塊為例,金幣磚塊在被玩家頂出金幣后會變?yōu)椴豢蓮椘鸬臓顟B(tài),而普通磚塊在小馬里奧狀態(tài)下,只要被頂?shù)骄蜁椘?,只要把金幣磚塊邏輯改一改,貼圖換一換,普通磚塊就制作完成了。
接下來就要制作會遇到的第一個怪物:酷栗寶。
多說一句,這個怪物就算是官方翻譯也不止一種(除了酷栗寶外還有栗寶寶、栗子小子之類的)。不過單純從發(fā)音的角度來看,酷栗寶是最忠實還原的(原名叫クリボー,用中文念著像kulibo),就好比哆啦A夢之于ドラえもん一樣。

酷栗寶做起來很簡單,添加好剛體、碰撞體,然后身體的左右和下方添加三個子物體,用于發(fā)射射線??崂鯇氁獡魵⑼婕揖褪且揽可眢w接觸,但是玩家踩踏怪物的效果又需要碰撞體的支持,所以這時候就需要依靠射線了。射線碰到玩家后玩家會死亡,而玩家踩踏到怪物時,怪物就死亡,并給玩家提供一個向上的力(模仿彈力)。
這時候可能有朋友會問了,為什么不直接用unity中的彈力呢?我之前試過,在unity自帶的物理引擎框架下,玩家要是從不太高的地方落下,那么踩踏怪物幾乎不會產(chǎn)生彈力,但是玩家從高處掉落時踩踏到怪物,就會被彈得非常高——這與游戲本身的效果差別非常大。

最后,讓怪物在生成時就向左移動,碰到障礙物時就變向,這樣一個酷栗寶就完成了。
另外,我想怪物肯定不是在玩家進(jìn)入游戲后就開始生成的,不然如何做到玩家每次進(jìn)入場景怪物都在固定的位置?我的思路是,制作一個怪物生成器,每當(dāng)玩家走到一定位置,生成器就把作為他的子物體的指定的怪物生成出來。與馬老師討論后他認(rèn)同了我的想法:怪物可以一開始就放入固定位置,進(jìn)入游戲后便刪除它們,在玩家到指定位置時再將它們生成。
想法有了就立即開始搞。
我先進(jìn)入原版游戲,仔細(xì)觀察玩家到了哪個位置哪些怪物會生成,然后回到unity中,將怪物放置到相應(yīng)的位置,然后開始寫怪物生成器的腳本。
然而這時候我犯了一個巨大的邏輯錯誤。我沒有用List進(jìn)行存儲,而是將作為子物體的怪物們一一在Start中獲取出來,記錄下它們的位置,然后一一在Update中檢查玩家是否到了應(yīng)該生成它的位置,就比如玩家走過了世界x軸中的-9.3這么一個位置,那么就用預(yù)制體生成第一個怪物。
這樣寫,邏輯是簡單了,但是寫代碼很麻煩。因為每次有怪物的地方,我都要去計算玩家到了什么地方它會生成,還得在Start中去獲取怪物的位置。明明這個“怪物生成器”聽起來就是全自動的,做起來它應(yīng)該也是全自動的才對。
馬老師看了我的做法馬上否決了,他建議將所有怪物和怪物的“生成信息”存入一個List中,將怪物們SetActive(false),使其隱藏,直到玩家靠近怪物到10個單元值的時候,怪物就SetActive(true),在場景中出現(xiàn),以后要生成怪物,只需要將怪物放到怪物生成器下,調(diào)整怪物在場景中的初始位置即可,無需調(diào)整腳本。
實現(xiàn)效果:
游戲未運行時的場景:

?游戲開始運行后的場景:

玩家靠近怪物后:

在吃到第一個金幣,逃過第一個怪物的迫害后,差不多就到下一屏內(nèi)容了。大家知道場景中的第二個道具磚塊彈出的便是能讓玩家變大的蘑菇(官方名“超級蘑菇”,スーパーキノコ)。它的行為如下:會緩慢地從磚塊中升起,待身體完全展現(xiàn)出來后就會向右方移動,玩家觸碰到它時玩家自身就會變大、且蘑菇自身消失。
這個蘑菇向上移動的制作方法其實和磚塊的移動方法接近,讓蘑菇生成后,在移動到指定位置前,逐幀向上移動,然后在達(dá)到指定位置時開始向右移動,要使蘑菇在移動時不受重力和磚塊碰撞體的影響,在到達(dá)指定位置前,它都為Kinematic狀態(tài),到達(dá)后就轉(zhuǎn)變?yōu)镈ynamic狀態(tài),最后在碰到玩家時消失。
那么玩家要怎么切換到變大的狀態(tài)呢?我目前還是使用的最簡單的預(yù)制體方法。我將大馬里奧添加上與小馬里奧幾乎相同的組件后,制成預(yù)制體,在小馬里奧吃到蘑菇后,就將小馬里奧刪除,生成大馬里奧即可。
做到這,我又發(fā)現(xiàn)了新的問題——嚴(yán)格說算是某個feature的延申:
在游玩游戲時,攝像機(jī)會跟隨馬里奧移動,但不能往回卷軸——這其實是早期橫向卷軸游戲的一大feature。而且攝像機(jī)的范圍還會限制馬里奧的移動。而我所說的“新的問題”是:小馬里奧被刪除后,攝像機(jī)并不會跟隨大馬里奧,因為我沒有寫攝像機(jī)的腳本,而是直接使用的VirtualCamera, 在VirtualCamera中,指定跟隨小馬里奧這個物體,小馬里奧消失了,那么他就不會跟隨玩家物體進(jìn)行移動了。
所以我果斷決定將其舍棄(技術(shù)不夠不要緊,氣場要夠),使用主攝像機(jī)。我創(chuàng)建了一個空物體,將主攝像機(jī)作為它的子物體,將攝像機(jī)腳本掛在父物體下。攝像機(jī)腳本中,和VirtualCamera一樣,我定義了一個Target(攝像機(jī)跟隨的目標(biāo)),但是它是可以變化的,在小馬里奧消失后,將target更改為新誕生的大馬里奧,并讓攝像機(jī)跟隨target移動即可。
那么如何讓攝像機(jī)不往回卷軸、且阻擋玩家向后移動呢?很簡單,在攝像機(jī)的左邊界創(chuàng)建一個“空氣墻”,跟隨攝像機(jī)移動,攝像機(jī)不會倒退則它也不會倒退,玩家自然就無法向后移動了。那么如何使攝像機(jī)無法倒退?一個簡易的方法是:用一個Vector3變量originPosition實時獲取攝像機(jī)父物體的當(dāng)前位置(originPostion=transform.position),再用一套非常簡單的邏輯來限制它的移動:若此體想要倒退,即此物體位置的x的值會變小,若這個值小于originPosition的x的值,那么此物體的位置就等于originPosition。
這樣,就可以限制攝像機(jī)和玩家的移動了,做起來很簡單。瞅瞅效果圖:

工程鏈接:https://pan.baidu.com/s/1kR2HzO0_6SQoP9ZoMZDcCw
提取碼:mali
歡迎加入游戲開發(fā)群歡樂攪基:1082025059
對學(xué)習(xí)游戲開發(fā)、游戲制作感興趣的童鞋,歡迎訪問咱們的主頁:http://levelpp.com/