游門弄斧41——LudumDare41總結
上周(應該說是上上周了)和幾個小夥伴一起參加了一個GameJam(在幾天時間內根據指定的主體快速製作一款小遊戲的活動)Ludum Dare 41,由於是第一次參加GameJam,感觸頗深,其中有很多和遊戲設計、遊戲開發方面相關的體驗,覺得可以記下來,還真好是游門弄斧第41篇,感覺很有緣。
由於是回憶性質的記錄,行文邏輯可能會欠佳,見諒。
最後的成品鏈接:https://ldjam.com/events/ludum-dare/41/fast-food,歡迎圍觀。
主題
Ludum Dare 41的主題是「Combine 2
Incompatible Genres」——「組合2個不兼容的流派」。說實話看到這個主題時我們最開始是比較懵逼的,就像當時討論區里有人提到的「如果2個流派真的不兼容,那麼它們是沒有辦法被組合的」。
不過擴展開想,「不兼容」這個詞的意思是很寬泛的,應該將思路放在將2個差異性很大的玩法、風格結合在一起上,只要體現出「正常情況下這2者不會同時出現」即可。
然後就開始頭腦風暴,首先把能做的遊戲類型都羅列出來。考慮到我們幾個人經驗都不多,想從簡單的入手而且沒人會捯飭shader,於是確定做2D。
2D中斃掉了一些肯定做不了的,比如劇本量比較大的遊戲類型比如文字冒險,因為沒人會寫劇本,尤其是還得用英文寫;比如音游,沒人做過類似工作不知道坑有多深。
最後從能做的東西里開始想怎麼組合,最好還能避開一些很容易想到不容易出彩,比如回合制的即時戰鬥遊戲/即時戰鬥的回合制遊戲,都是很常見的遊戲類型,沒想出什麼在「組合」上體現出新意的點子,想到的點子都是在即時戰鬥或回合戰鬥本身上進行創新。
最後拿出了5個備選方案
1是結合2個不兼容的主題:老人和運動,做一個老年人運動會的遊戲,包括老人坐在輪椅上賽跑、拿著拐杖競走等等
2是用泡泡龍的思路玩俄羅斯方塊,即將泡泡龍遊戲中畫面下方發射的泡泡替換為俄羅斯方塊里的方塊,通過牆壁的反彈在畫面上方組合形成滿行從而消除
3是三消/連連看+平台跳躍,在初始滿屏幕不同顏色的方塊上使用三消或連連看的形式消除一些方塊,使得左下的小人能夠通過跳躍、攀爬等方式到達右上的位置
4是打磚塊+飛行射擊,飛機發射的子彈是會反彈的,飛船需要接住反彈回的子彈再次彈出去以保證能在最短時間內清版
5是競速+模擬餐廳,用賽車遊戲的思路收集跑道上的食材並完成菜品製作的過程
實際上每個方案都有其優劣勢,對優劣勢進行了一番討論+投票後,最後選擇了競速+模擬餐廳的方案。
設計功能
大體的方向定了就要設計具體遊戲中的遊戲目標、玩法功能和預期難點。
最初提出這個方案的同學的想法是通過在賽道上設計一些做菜的材料、工具和障礙,讓賽車——也就是盤子——按照順序拿取材料、加工材料、避開障礙,最後通過終點。
預期是將做菜的部分設計得帶有一定的解謎要素和2D動作類遊戲的操作要素,比如如何在傳送帶上接住定時落下的沙拉同時避開鐵鎚等等。
但後來我們討論了一下覺得賽車本身是需要一定的快速的元素的,周圍環境一直變動,而這種2D動作解謎的過程是一個慢速的過程,是長時間待在一個小範圍內,這2者合一起會顯得十分割裂,即先在一個場景下完成解謎,然後迅速開車衝到下一個場景,本質上還是2個單獨的遊戲。
另外解謎的關卡設計和開發難度不低,但是很容易就被玩通了,感覺很虧。而且解謎的部分介紹起來挺複雜的,要告訴玩家能做什麼不能做什麼,通常的解謎遊戲是靠循序漸進的關卡逐漸豐富解謎中的元素,我們的小遊戲沒有這個時間。
於是決定要簡化「做菜」里涉及到的步驟,在「動」的狀態下進行做菜,於是想到用做三明治、漢堡的思路,在賽道上收集食材,然後組合到一起就成了菜品。
但是有了新的問題,賽車遊戲的樂趣很大程度上在於PVP的部分,和其他玩家競速,如果僅僅是在賽道上收集食材,那麼最多也就是一個考驗車技的事情,可能並不好玩。而且另一方面模擬餐廳的遊戲的核心是食材和時間的規劃,即不斷有新的訂單到來同時訂單有時間限制,但是玩家做菜的速度是受限的,玩家需要規劃好同一時間不同的廚具、員工幹什麼事情從而滿足訂單的內容和時間需求。
賽車遊戲里時間需求很好體現,於是問題就是如何體現對食材的規劃和與他人競速的樂趣。本來如果是聯機遊戲可以讓好幾個玩家一起在賽道上跑,互相爭搶食材,但是考慮到這個活動最後需要互評,如果強制多人遊戲很多單人作者沒法玩,不可取。
有同學想到一個點子,說我們一次放3道菜的材料到跑道上,玩家跑一圈做完一道菜之後,跑第二圈時出現一輛第一圈的「幽靈車」,玩家需要在避開自己第一圈的幽靈的情況下收集第二道菜的食材,這樣間接產生競速和爭搶的效果。我們想了想覺得可行,然後就這麼定了。
於是最後確定的遊戲目標是分3次在賽道上根據要求的順序拾取食材,同時注意減少碰撞和用時,預期難點除了賽車遊戲本身的駕駛難度外,還有如何在前1-2圈規劃好路線和食材拾取順序,避免後面1-2圈被之前的自己過分擋路和碰撞,因此需要一定的背板和預判記憶的能力。
幽靈車功能
因為我們一共3個程序,因此我們把遊戲分成3塊:
關卡管理為核心的主菜單
賽車駕駛為核心的控制
幽靈車記錄和重現
我是3個程序里unity經驗最少的一個人,於是我提出自己做幽靈車記錄和重現,因為萬一做不出來還能直接把這個功能給砍了,不耽誤總體進度,畢竟我們的第一要務是「做一個能玩的遊戲」,做出來是第一位,功能夠不夠豐富是其次的。
最開始想到就是每一幀記錄賽車的位置、速度、方向這些信息,然後下一圈復現,雖然記錄量有點大,但是一圈時間最多也就1分鐘,3600幀,感覺還行,就先寫了試了一下,然後發現不行,幽靈車的運動一點都不平滑,一直在抖。
回想了一下之前依稀看過的一篇分析unity里update和fixedupdate函數的區別的文章,感覺這個跟2圈裡實際幀之間的時間差有關。
於是改成了當玩家操作有變化時記錄當前的車輛信息和操作信息,在第二圈裡復現玩家的操作。這樣運動上是平滑了,就是部分狀態拐點(撞牆、撞障礙)的時候會有出現閃現的情況,也就是復現出的車輛位置和記錄的位置有偏差。
現在想來,第一種方法卡頓的原因不一定是因為幀之間的時間差,即使是時間差其實也有方法可以解決,但是考慮到這種逐幀記錄信息的方式太過於愚蠢和佔用存儲空間了,後來也沒有再試過看能不能改進。
而第二種方法後來通過加入一些在定時、特定條件下強制記錄車輛信息並復現的機制基本解決了閃現的問題。
寫這部分功能的經歷現在反思起來有2點問題
1是其實前面說的這一部分寫、改的過程並不是連續的,最開始很粗糙地實現完整個錄像功能後就和寫賽車操控的同學合了一次代碼,然後就開始幫著寫賽車操控和關卡機制相關的東西了,後續改動都是在完成其他部分功能的測試中發現然後回頭去改的。
但其中很多問題理論上是能在我這部分功能的獨立測試里就能發現的,但我當時並沒有怎麼詳細測試就去合代碼了
2是寫這部分功能的時候模塊化、解耦合做得不好,應該說是遊戲控制這塊的設計沒有提前考慮清楚。因為對賽車的控制包括玩家駕駛時通過玩家的操作控制賽車RaceCar,和在幽靈車模式下通過記錄中玩家的操作控制賽車AutoCar,但這2種控制的區別僅僅是輸入來源不同,控制機理是一樣的,因此相關功能函數是可以復用的。
實際上在最後的設計中,讀取玩家的操作全部由AutoCar進行,由AutoCar向RaceCar提供當前賽車的具體控制行為,在玩家控制模式下AutoCar提供的就是玩家的當前輸入,在幽靈車模式下AutoCar提供的就是記錄中玩家現在的輸入。
這樣RaceCar只需要實現通過輸入控制車怎麼開就行了,不需要知道目前賽車處於真人模式還是幽靈車模式。
RaceCar里的控制信息都是從AutoCar的ControlNow結構體里讀出來的,現在想來應該直接讀出整個結構體的內容,不應該這麼反覆讀。
分工合作
寫完幽靈車功能的初稿之後我就開始去幫忙寫賽車控制、物品拾取等等功能,但這一塊的分工合作其實做得非常差。
現在想來,因為我們沒有一個真正的總體策劃和設計的角色(3個程序2個美術,而且沒有誰作為拍板定方案的人),最開始僅僅確定了大致的玩法(賽車、拾取食材),但是一些細節設定比如一圈怎麼算結束?食材是否刷新?障礙物有哪些等等並沒有設計清楚就開始寫了。於是這些設定都是後來邊寫邊想的,也就是我和寫賽車控制的同學2個人在想,很多地方考慮得很不充分。
例如他在寫拾取食材的功能時覺得食材只要撿起來就行,對順序沒要求,但是這樣要判斷當前拾取的這個材料是否存在與目標列表裡、顯示在UI界面里「已拾取」部分的第幾位需要一系列判斷,特別麻煩。後來和我商量時我說我們應該對玩家的拾取順序有要求,這樣玩家只需要關注自己「下一個要的」是什麼就夠了,一下出現好幾個物體時單一的目標會比較好判斷。
現在反思的話,即使是這種小遊戲,很多細節的設計也需要提前想好,形成文檔,這既涉及到細節的合理性,比如我提出的只關注下一個的設計也有很大的問題;同時這對於分工合作寫代碼的場合下是十分重要的。
而且設計遊戲遠不止想一個點子這麼簡單,一份詳細的設計書需要包括方方面面的細節設定,而這些設定都需要仔細推敲。例如我們這個遊戲里最開始設計的是素材在全賽道隨機刷新,因為我希望玩家是以保持速度為主要目標,根據「下一個材料」來選擇撿材料還是繞過材料。但是後來根據玩家的反饋來看這種全圖刷新對操作要求太高了,需要時刻保持緊張的精神和精細的操作,否則很容易就會錯過或者撿錯。於是後來改成了在特定位置並排刷3-4個材料對應每一道菜里當前位置需要的材料,玩家只需要撿起屬於自己菜里的那一個就行。
看似簡單實則不簡單
最開始選擇賽車遊戲是因為我們覺得賽車遊戲好做,但是實際上在做完最基本的賽車控制、拾取功能,整個遊戲處於「最基本的能玩」狀態下後,我發現賽車遊戲水也很深。
首先鏡頭的跟隨就是個大坑。
2D俯視角的鏡頭跟隨要不要轉動方向讓車輛始終「向上開」?
如果鏡頭方向不跟隨車的朝向轉動,那麼當車向下開時,對玩家來說車的左右就是顛倒的,很容易轉錯方向,尤其是我們這遊戲里涉及到很多撿東西和避開障礙的元素,需要非常快速的反應,很容易出錯。
但是如果跟隨車的方向轉動,那麼鏡頭又會特別晃,因為賽車遊戲中頻繁的左右小幅度晃動調整方向的情況很常見,比如感覺自己有點偏左,於是先稍微右轉一點然後立刻回正。但是這種晃動會讓人有些發暈。
本來理想的方式是,讓鏡頭朝向賽道的前方而不是朝向車面朝的方向,但是當時實在是沒想到什麼好的方式實現。
另一個大坑就是漂移。
最開始沒打算加入漂移的功能的,但是遊戲整體做完之後發現如果沒有漂移,那麼純粹用方向鍵四平八穩地開車太無聊了,過彎只能減速,體驗賊差,所以還是決定要做漂移。
但是漂移怎麼實現?當時已經沒時間去看網上別人提供的代碼了,只能自己快速弄一個出來。
最開始的版本是當按shift時減速+快速轉向,是個非常簡陋的實現方式,僅僅能解決拐急彎時只能慢慢減速然後慢慢轉向過彎的問題,但是和一般賽車遊戲里的漂移差得太遠了。
賽車遊戲里的漂移至少得有「賽車前進方向和賽車朝向不同」這一點,雖然通過加入一個額外的賽車屬性(在之前朝向的基礎上加一個運動方向的屬性)能夠解決這個問題,但是按住shift後賽車朝向和運動方向分別怎麼轉動(肯定是一快一慢,但是快多少?慢多少?)?漂移狀態下車怎麼減速?運動方向向賽車朝向的恢復速度多快?按下shift進入漂移狀態後shift繼續按住和立刻鬆開有什麼區別?
這裡面設計到很多細節設計以及參數的問題,最後調試了挺長時間,感覺並沒有獲得太好的認同。
主要是作為寫代碼和調試的人,我已經很熟悉自己寫出的漂移功能了,因此我玩起來6得1B,但是其他人,尤其是剛上手只是隨便試玩一下沒想要好好練習的玩家會覺得難得1B。但是即使我讓周圍的人試玩了一下他們表示難或者不像他們玩的遊戲里的漂移手感之後,他們沒法告訴我到底哪裡不一樣、應該怎麼改。
因此在我體驗不出問題在哪裡、別人分析不出問題在哪裡的情況下,我也不知道怎麼改了。
美術和音樂
毫無疑問到目前為止我們這個遊戲最大的亮點就是美術和音樂,幾乎每個評論都贊了美術和音樂,真心感謝2位美術大佬的大腿。
我作為一個程序肯定是比較受傷的,尤其還是負責被「噴」的功能部分的程序。但是這也告訴我們,就像我們指責這是個看臉的世界一樣,遊戲也是有「臉」的,美術和音樂就是臉,好的美術和音樂對玩家第一印象的影響巨大。
而那些自以為牛逼哄哄的細節設定在沒有好看的臉的情況下沒人願意去細細品,除了真·硬核玩家。
總結
我覺得自己在這次GameJam里算是收穫頗豐,主要不是我謙虛,我只是想來打個醬油,結果莫名其妙就成了主程序,收穫能不大么。
整個過程也讓自己更加深刻地體會了一把做遊戲的不容易,有很多問題如果不是自己親自參與去做一個遊戲是根本意識不到的,例如全局的設計、各模塊的介面設計、遊戲細節推敲等等。
因此推薦那些想做遊戲、設計遊戲的朋友,與其臨淵羨魚不如退而結網,只有把自己腦子裡的腦洞落實到紙面上、代碼里,才能正確評估自己的腦洞到底值幾何。
推薦閱讀:
※好的遊戲開發培訓課程有什麼亮點
※一道技術美術的面試題
※如何打造細緻的2D捏臉系統
※GMS2官方教程系列4/8——瓷片&鏡頭
※BGE:在3D軟體里做遊戲 (1)