我是如何從零開始手搓一個(gè)獨(dú)立游戲并上架Steam的

1 評(píng)論 2524 瀏覽 4 收藏 38 分鐘

每一個(gè)游戲玩家心中,都有一個(gè)自己做一款游戲的夢(mèng)。費(fèi)勁千辛萬(wàn)苦后,我成功制作了一款獨(dú)立游戲并在2025年1月1日上架了Steam。

本文既是對(duì)這個(gè)過(guò)程的一種紀(jì)念,也是對(duì)游戲制作這個(gè)話題留下一些自己的思考和總結(jié),如果能讓后來(lái)者少踩幾個(gè)坑,就更好了。

我將按時(shí)間線索將整個(gè)游戲制作和發(fā)行過(guò)程展現(xiàn)出來(lái),文章較長(zhǎng),感謝你的耐心閱讀。

一、源起2019

我是一個(gè)80后,在90年代伴隨著電子游戲成長(zhǎng)起來(lái)的一代人,在讀書的時(shí)候曾經(jīng)有一段時(shí)間沉迷游戲,玩三國(guó)志和文明系列玩到深夜。

我父親實(shí)在看不下去了,對(duì)我說(shuō)了一句話:“玩游戲厲害算什么,有本事自己做一個(gè)啊”。當(dāng)時(shí)還小,也沒(méi)有能力制作一款游戲,可能是年少時(shí)的那種不服氣吧,這句話我就一直記在了心里。

后來(lái)參加工作了,和大多數(shù)社畜一樣,每天累得跟狗一樣,回家就只想躺著休息,連打開電腦玩一把游戲的興趣都沒(méi)有了。

2018年下半年,Steam上的獨(dú)立游戲中國(guó)式家長(zhǎng)火熱,我正好也玩到了這款游戲,并向我的朋友推薦了它。

然后在2019年春天,我晚上加班加得心煩意亂,工作堆積如山,一眼瞥見(jiàn)了加班了一小會(huì)兒就想溜的胡大胖同學(xué),我說(shuō): “你陪我加班吧,我做完這點(diǎn)事情,我們就玩暗月來(lái)襲“,然后胡大胖同意了。

暗月來(lái)襲是當(dāng)時(shí)很火的一款DOTA2地圖,我們之前從來(lái)沒(méi)有通關(guān)過(guò),就在那個(gè)晚上,我們打到了歷史最佳記錄-倒數(shù)第二關(guān)。

然后在黎明到來(lái)前,胡大胖說(shuō):“加班其實(shí)是有一定概率猝死的?!?/p>

我說(shuō):“要不我們做一款游戲吧,就叫中國(guó)式加班?!?/p>

胡大胖表示同意,然后我們一起構(gòu)思了這么一個(gè)特別的游戲;當(dāng)時(shí)胡大胖還并不知道,他將是這個(gè)加班游戲的主角原型。

所以在2019年五月,我初始化了這個(gè)游戲項(xiàng)目的Git倉(cāng)庫(kù)。

二、萌新的進(jìn)擊

雖然對(duì)制作游戲一無(wú)所知,但是我知道很多游戲引擎,比如rpgmaker,cocos2d,unity,虛幻3,當(dāng)時(shí)實(shí)在沒(méi)有心思再投入時(shí)間學(xué)習(xí)這些引擎。

所以我就在想,能不能用我現(xiàn)有的技術(shù)棧來(lái)做這個(gè)游戲?

我就決定先用前端(Vue)+Electron先做一個(gè)DEMO出來(lái)。

然后DEMO很快就出來(lái)了,它大概長(zhǎng)這個(gè)樣子:

點(diǎn)擊新建游戲后出現(xiàn)幾個(gè)對(duì)話,就這么簡(jiǎn)單。

懵懂間,我意識(shí)到了自己需要制作一個(gè)游戲腳本引擎系統(tǒng),不過(guò)作為一個(gè)DEMO,我還沒(méi)有把腳本引擎添加進(jìn)來(lái)。

一切似乎都很順利,然后我開始盤算我還需要什么東西才能完成這個(gè)游戲,很明顯,我需要2D美術(shù)資源用來(lái)表達(dá)人物立繪和場(chǎng)景,需要有音效和背景音樂(lè)。

我決定先從最簡(jiǎn)單的音效和背景音樂(lè)開始,音效在網(wǎng)上免費(fèi)可商用的很多,背景音樂(lè)我選擇直接從audiojungle購(gòu)買,總共花了800人民幣左右。

然后是美術(shù)資源。我從淘寶上找了一個(gè)畫手來(lái)繪圖,當(dāng)時(shí)想得很好:一邊制作游戲,一邊按照規(guī)劃輸出美術(shù)資源。

我當(dāng)時(shí)是以200一張的價(jià)格向畫手定制的,我們很快敲定并輸出了基礎(chǔ)的UI圖。

在輸出場(chǎng)景和人物圖時(shí),我和畫手都付出了相當(dāng)大的代價(jià)。

當(dāng)時(shí)我們輸出一張圖需要以下幾個(gè)流程:

  1. 我文字描述想要的場(chǎng)景/人物特色,盡可能地詳細(xì),并配上例圖
  2. 畫師制作線稿
  3. 我和畫師敲定線稿,如果和我的想法有偏差,會(huì)對(duì)線稿進(jìn)行調(diào)整
  4. 畫師細(xì)化線稿并上色
  5. 畫師根據(jù)我的反饋,對(duì)成品進(jìn)行優(yōu)化和調(diào)整

剛開始還不覺(jué)得,但是后來(lái)我發(fā)現(xiàn),這樣出一張圖的成本實(shí)在是太大大大大大大啦!

當(dāng)時(shí)我們做了一些這樣的圖:

然后我意識(shí)到這樣一個(gè)問(wèn)題,我根本沒(méi)有足夠的資源去得到這些我想要的美術(shù)素材,所以在付出了8700元之后,我選擇了將這個(gè)項(xiàng)目封存,不再繼續(xù)。

不管是時(shí)間成本還是金錢成本,都不是當(dāng)時(shí)的我能夠承受得了的。

三、黎明的曙光

就這樣又過(guò)了幾年,我時(shí)不時(shí)還想起這個(gè)游戲項(xiàng)目來(lái),帶著深深地遺憾,因?yàn)槲覐膩?lái)不是一個(gè)喜歡爛尾的人,但是人到中年,也學(xué)會(huì)了接受很多的客觀現(xiàn)實(shí)。

轉(zhuǎn)機(jī)出現(xiàn)在2022年,stable diffusion橫空出世,同年12月,chatgpt正式上線,我很快意識(shí)到,也許我現(xiàn)在有機(jī)會(huì)完成中國(guó)式加班了。

在研究了sd很久之后,我確信這個(gè)東西生成的圖片即便存在這樣或那樣的瑕疵,但卻是我唯一能夠低成本獲得2D美術(shù)資源的方法。

于是我決定重啟中國(guó)式加班項(xiàng)目。

重啟的第一件事,我決定制作一個(gè)路線圖表格,這是這個(gè)表格在游戲最終完成后的樣子:

我決心按照這個(gè)表格嚴(yán)格執(zhí)行,立馬開始了游戲玩法設(shè)定的工作。

在設(shè)計(jì)玩法時(shí),我考慮到了自己的精力有限,所以把整個(gè)游戲的玩法設(shè)定得特別簡(jiǎn)單,心里想著玩法的短板可以用豐富的劇情去補(bǔ)充,游戲類型確定為SLG模擬經(jīng)營(yíng)。

其實(shí)對(duì)于獨(dú)立游戲而言,劇情代表著巨大的工作量,不過(guò)對(duì)于當(dāng)時(shí)的我而言,并沒(méi)有這種認(rèn)知。

我用自學(xué)不到一個(gè)星期的Adobe XD嘗試制作了這樣一個(gè)原型,以下是抽取的幾張?jiān)蛨D片:

這個(gè)原型很粗糙,它的最大的價(jià)值就是把我腦海里這個(gè)游戲的樣子用圖片的形式展現(xiàn)出來(lái),并且我知道后續(xù)原型里這些設(shè)定不會(huì)有特別大的改動(dòng)了。

四、時(shí)代不同了,大人

我還需要徹底解決美術(shù)素材的問(wèn)題,所以我特意購(gòu)買了一臺(tái)電腦,因?yàn)轭A(yù)算有限,顯卡是用的4060Ti。

然后我開始嘗試使用sd進(jìn)行AI出圖,在這個(gè)過(guò)程中,我遇到的最大的問(wèn)題是,如何保持人物/場(chǎng)景風(fēng)格的一致性,想了很多辦法,最終采用的是在prompt前置風(fēng)格描述的方式。

最開始的時(shí)候,我是把出圖prompt用中文描述出來(lái),再用DeepL翻譯為英文,最后在sd里煉丹出圖。

但是這種方式有個(gè)弊端,對(duì)prompt的要求非常高,寫prompt也不是一件容易的事,然后我想了個(gè)辦法,讓Chatgpt去幫我寫sd的prompt,Claude出來(lái)之后我就把Chatgpt換成了Claude。

AI寫的prompt非常詳細(xì),sd也能更好的理解prompt,但是仍有一個(gè)問(wèn)題,就是無(wú)法生成同一場(chǎng)景或人物的細(xì)微變化,比如一個(gè)人在不更換服裝和發(fā)型的情況下,要出一張不同動(dòng)作的圖,這就很難,即便我用了ControlNet去約束,新出來(lái)的圖,在服裝或發(fā)型上,總有些細(xì)微的差別,無(wú)法做到一致性。

所以我干脆放棄了人物立繪的動(dòng)作多樣化,直接一個(gè)人物一張圖用到大結(jié)局,這樣就簡(jiǎn)單多了。

解決了美術(shù)素材的問(wèn)題,我開始從0研發(fā)一個(gè)簡(jiǎn)單的游戲引擎,說(shuō)是引擎,但其實(shí)最核心的部分只有一個(gè),就是游戲事件腳本引擎,因?yàn)檎麄€(gè)游戲都是以事件驅(qū)動(dòng)的。

很快我就構(gòu)建好了事件腳本系統(tǒng),我把事件腳本分為兩部分,一部分是事件條件,一部分是事件內(nèi)容,我把它們都寫入一個(gè)Sqlite數(shù)據(jù)庫(kù)中,Sqlite的數(shù)據(jù)庫(kù)其實(shí)就是一個(gè)文件,也比較簡(jiǎn)單且易于管理。

事件條件主要就是人物的一些屬性和時(shí)間/前置任務(wù)等等,單獨(dú)使用了一張表保存。

事件內(nèi)容要稍微復(fù)雜一些,我基于Markdown設(shè)計(jì)了它的基礎(chǔ)語(yǔ)法,最終看起來(lái)是這樣的:

1. 對(duì)話
新垣結(jié)衣: 今天我?guī)е?*里美醬**一起來(lái)的噢.

2. 場(chǎng)景切換
<帝企鵝大樓3301>
<過(guò)場(chǎng)場(chǎng)景>$ /* 隱藏UI */
<游戲結(jié)束>+ /* 直接切換 */
<> /*空?qǐng)鼍? 延遲事件執(zhí)行1s*/

3. 定義分支
# 相信陌生人
陌生人:你好,我是陌生人.

4. 選項(xiàng)跳轉(zhuǎn)分支
1. 要相信他嗎?@相信陌生人
2. 不相信他!@不相信陌生人
3. (角色屬性.幸運(yùn) > 80) ? 我想賭一把@相信陌生人

5. 場(chǎng)景加載/取消NPC
* NPC1
* NPC2
~ NPC3

6. 跳轉(zhuǎn)分支
(角色屬性.上級(jí)滿意度 < 20) ? @條件跳轉(zhuǎn)某分支
(角色屬性.名字 == “新垣結(jié)衣”) ? @條件跳轉(zhuǎn)某分支
(系統(tǒng)屬性.隨機(jī)數(shù) < 0.7) ? @隨機(jī)跳轉(zhuǎn)某分支 /* 70%概率*/ @直接跳轉(zhuǎn)某分支 7. 畫外音 > 平等地剝削勞動(dòng)力,是資本的首要的人權(quán)。

8. 提示
[**里美醬**對(duì)你的好感度提升了]+
[你受到了暴擊傷害]-

9. 屬性修改
(系統(tǒng)屬性.某角色 = 解鎖)
(角色屬性.精神上限 = $ + 100)
(角色屬性.底層螺絲釘 = 已激活@3天)
(角色屬性.休息日23點(diǎn) = 睡覺(jué)*) /* 帶*號(hào)為鎖定卡牌 */

10. 播放音樂(lè)
{平靜1.mp3}

然后我再根據(jù)事件腳本的語(yǔ)法去實(shí)現(xiàn)整個(gè)游戲引擎,當(dāng)時(shí)為了學(xué)點(diǎn)新東西,放棄了第一個(gè)DEMO時(shí)使用的Vue,轉(zhuǎn)而使用了React。

其實(shí)我對(duì)React一無(wú)所知,但是好在有Github copilot的幫助,很快就上手了

整個(gè)游戲引擎前后耗時(shí)約6個(gè)月,然后我用這個(gè)引擎又做了一個(gè)DEMO版本,以測(cè)試事件腳本引擎能否正確運(yùn)行。

結(jié)果很幸運(yùn),它真的可以運(yùn)行起來(lái)。

五、真正的阻力

然后我興高采烈地開始寫游戲大綱,包括游戲背景大綱和游玩角色大綱。當(dāng)時(shí)計(jì)劃的游玩角色總共有四個(gè),分別是胡圖巴(倔強(qiáng)的韭菜),肖望榮(中年悲歌),孫西里(小目標(biāo)),趙浩(拖延癥患者的夢(mèng)),第四個(gè)角色趙浩其實(shí)就是以我自己為原型設(shè)計(jì)的。

大綱寫好以后我開始按照原定計(jì)劃為每一個(gè)角色劇本寫配套的小說(shuō),第一個(gè)角色胡圖巴的配套小說(shuō)寫了幾萬(wàn)字后,我突然感覺(jué),這東西寫不完了。

人這種生物一旦在付出努力未能實(shí)時(shí)獲得反饋時(shí),就會(huì)變得極其懶惰。

我也是這樣,我就在步子邁大了小說(shuō)完不成了和我再抽點(diǎn)時(shí)間寫寫之間反復(fù)徘徊。

最終進(jìn)度非常緩慢。

后來(lái)有一天我實(shí)在忍不了了,我就想,這個(gè)小說(shuō)真的是有必要的嗎?

我是在做游戲,又不是在寫小說(shuō)。

所以我干脆把整個(gè)小說(shuō)系統(tǒng)在游戲里給去掉了,去掉之后渾身舒坦,游戲研發(fā)進(jìn)度飛速發(fā)展。

六、完成和完美

經(jīng)過(guò)了一段時(shí)間劇情腳本編寫之后,我又開始偷懶了,因?yàn)槲腋杏X(jué)自己的的確確沒(méi)有享受做游戲這種事。

做游戲和玩游戲完全不一樣,做游戲不止很困難,并且你獲取不到玩游戲的那種快樂(lè),也就是在游戲交付測(cè)試之前,你基本得不到什么正向的反饋。

然后我在做加班游戲的時(shí)候開始摸魚

這一摸又是很久,久到我自己都受不了了,我打開手機(jī)寫下了這樣幾段話:

中國(guó)式加班從去年到今年已經(jīng)兩年了還沒(méi)完成,需要進(jìn)行反思和總結(jié),找到加快開發(fā)進(jìn)度的方法。
## 原因
1. 惰性
人總是趨向于做容易的事,容易取得成就感的事,所以把空閑時(shí)間大量花在了看視頻玩游戲上
2. 難以進(jìn)入心流
開發(fā)過(guò)程中無(wú)法全神貫注,并且不享受游戲開發(fā)的過(guò)程,創(chuàng)作和和玩游戲的感覺(jué)完全不一樣,無(wú)法受到實(shí)時(shí)激勵(lì)
3. 沒(méi)有緊迫感,沒(méi)有計(jì)劃
整個(gè)事情沒(méi)有時(shí)間節(jié)點(diǎn)的壓力,現(xiàn)在時(shí)間比較充足,也沒(méi)有經(jīng)濟(jì)上的壓力,就無(wú)法高效地推進(jìn)任務(wù)
## 解決方法
1. 加長(zhǎng)那些簡(jiǎn)單獲取多巴胺的事項(xiàng)的路徑
比如刪除游戲,限制抖音等app的使用時(shí)間,解放碎片時(shí)間,使得專注時(shí)間更長(zhǎng)
2. 設(shè)定截止日期和任務(wù)計(jì)劃
每天回顧這個(gè)計(jì)劃并堅(jiān)定按照計(jì)劃的時(shí)間和工作量去推進(jìn),盡可能的分解大的任務(wù)為小的任務(wù)
3. 讓創(chuàng)作的過(guò)程變得更有趣
讓創(chuàng)作游戲腳本的過(guò)程更簡(jiǎn)單并且更有趣,甚至像玩游戲一樣去做游戲,或者邊做邊玩
4. 將做游戲這個(gè)事放入重要且緊急的象限里
放棄對(duì)部分品質(zhì)和細(xì)節(jié)的追求,尤其是場(chǎng)景圖和人物圖等資源的生成,把做游戲這件事設(shè)定為目前最重要且需要快速完成的事,放棄對(duì)銷售量的預(yù)期,只專心到“完成它”這一件事上,哪怕因?yàn)檫^(guò)于粗糙導(dǎo)致最終玩家評(píng)價(jià)不好,至少這件事我“完成了”,也許有瑕疵,也許壓根就不好玩,但是“完成了”對(duì)我而言就很有意義
5. 使用合作的力量,引入其他人參與,以更多的空間力量去執(zhí)行任務(wù)
6. 把路線圖表格保持打開狀態(tài),隨時(shí)提醒自己,根據(jù)進(jìn)度更新路線圖,預(yù)計(jì)好工期

這樣游戲的研發(fā)進(jìn)度再一次飛速推進(jìn),到了接近胡圖巴的游戲大綱中最后一段主線劇情時(shí),我又陷入了畏難情緒中。

我一想到就算這個(gè)做完了,還有3個(gè)游戲角色要做,我就渾身難受,覺(jué)得根本完不成了。

然后我找胡大胖吐槽,說(shuō)做游戲好難啊,胡大胖說(shuō),那你就做簡(jiǎn)單一點(diǎn)啊,先做出來(lái)再說(shuō)。

我想了想,要怎么才能加快整體的進(jìn)度呢? 要不直接減少可游玩的角色吧。

然后我就把除了胡圖巴之外的其他三個(gè)角色都給刪掉了。

這下進(jìn)度條狂奔,直接到了90%。

然后我開始趕工,只以完全主線劇情為唯一目標(biāo),原本計(jì)劃了很多的分支劇情,不想做就不做了吧。

就這樣游戲主體很快就完成了。

七、AI音樂(lè)

給游戲設(shè)置背景音樂(lè)的時(shí)候,我一開始仍然是使用的幾年前購(gòu)買的音樂(lè)素材包,后來(lái)一想,時(shí)代已經(jīng)變了,為什么不用AI來(lái)生成游戲的背景音樂(lè)呢?

說(shuō)干就干,我注冊(cè)并購(gòu)買了Suno的會(huì)員,花費(fèi)10$,然后生成了樂(lè)器伴奏的純音樂(lè)作為游戲的背景音樂(lè)。

后來(lái)我想,要不要在游戲的主菜單界面放一首人聲的主題曲呢?

我覺(jué)得這個(gè)主意很棒,并且很簡(jiǎn)單,成本又低,因?yàn)镾uno剛好也支持生成人聲的歌曲,于是我開始寫歌詞。

一開始的時(shí)候想讓claude幫我寫一首押韻的歌詞,但是AI生成的歌詞達(dá)不到我預(yù)期的效果。

于是我決定自己寫一首歌,歌名就叫《天命打工人》,最終完成的歌詞如下:

verse 1:
清早鬧鐘又響起
地鐵里面深呼吸
打卡上班很著急
工作已在等著你

chorus:
九九六,九九六
熬夜加班傷身體
零零七,零零七
摸魚才是硬道理
九九六,九九六
咖啡續(xù)命撐到底
零零七,零零七
我要變成萬(wàn)人敵

verse 2:
這個(gè)需求很簡(jiǎn)單
怎么實(shí)現(xiàn)我不管
老板畫餅要吃飽
生活?yuàn)蕵?lè)全扔掉

chorus:
九九六,九九六
熬夜加班傷身體
零零七,零零七
摸魚才是硬道理
九九六,九九六
咖啡續(xù)命撐到底
零零七,零零七
我要變成萬(wàn)人敵

bridge:
打工人,打工魂
打工人打開一張門
打工實(shí)在太費(fèi)神
打工人要做人上人

verse 3:
凌晨四點(diǎn)的夜光
照亮回家的方向
忘了加班的煩惱
生活多一點(diǎn)希望

ending:
九九六,九九六
熬夜加班傷身體
零零七,零零七
摸魚才是硬道理
九九六,九九六
咖啡續(xù)命撐到底
零零七,零零七
我要變成萬(wàn)人敵

當(dāng)我用Suno生成歌曲時(shí),意外出現(xiàn)了,Suno生成的中文人聲歌曲總是有部分吐詞不清楚,而且有一些詞會(huì)怪異地使用粵語(yǔ)的發(fā)音(推測(cè)Suno使用了很多粵語(yǔ)歌曲進(jìn)行訓(xùn)練),不管我怎么調(diào)整都沒(méi)有用,我甚至用帶聲調(diào)的拼音作為歌詞放Suno里生成,也還是不行。

然后我想,外國(guó)的月亮也不圓,我們國(guó)內(nèi)有沒(méi)有同類的AI音樂(lè)網(wǎng)站呢?

欸,還真讓我找到了,就是國(guó)內(nèi)的海綿音樂(lè)(字節(jié)系),我用同樣的歌詞貼進(jìn)海綿音樂(lè)了,不到5分鐘我就得到了發(fā)音清楚的搖滾音樂(lè),雖然海綿音樂(lè)生成的音樂(lè)沒(méi)有Suno那么音色飽滿且充滿細(xì)節(jié),但是勝在發(fā)音清楚,讓人有聽下去的欲望。

如果想聽一聽的,可以打開這個(gè)抖音鏈接試聽:

https://v.douyin.com/iyMKtt8p/

八、多國(guó)語(yǔ)言翻譯

最后要做的是多國(guó)語(yǔ)言翻譯,因?yàn)橐婚_始我就使用了i18n庫(kù),所以這部分工作主要就是翻譯i18n字符串。

我為游戲提供了幾種語(yǔ)言,簡(jiǎn)體中文,繁體中文,英語(yǔ),日語(yǔ)。

我嘗試使用claude去翻譯json字符串,經(jīng)過(guò)一系列嘗試后,使用以下prompt獲得了很好的效果:

以下是一些游戲的i18n對(duì)話文本,將其value翻譯為英文,請(qǐng)不要修改key,翻譯后的內(nèi)容需要全年齡段適用,請(qǐng)一次性翻譯完成,請(qǐng)務(wù)必一次性翻譯完成,文本中的標(biāo)記或其它可以轉(zhuǎn)義的標(biāo)記請(qǐng)對(duì)其進(jìn)行保留,輸出內(nèi)容為json,用inline code的方式輸出

但是手動(dòng)調(diào)用claude去翻譯的工作量實(shí)在是太大了,我就想能不能調(diào)claude 的api呢? 結(jié)果卡在了付費(fèi)這一步,沒(méi)有合適的外卡進(jìn)行支付,我的國(guó)內(nèi)visa卡并不能支付claude的費(fèi)用。

經(jīng)過(guò)一番搜索,我找到了rapi的claude api服務(wù),其實(shí)這個(gè)服務(wù)的提供者也只是轉(zhuǎn)發(fā)了claude的api服務(wù)(不知道這樣是不是違反claude api的tos的),好處是rapi的支付渠道很好,可以接受國(guó)內(nèi)的visa卡付款。

搞定了api,我直接在copilot的幫助下寫了一個(gè)python腳本去批量地使用我研究出的prompt對(duì)i18n文本進(jìn)行翻譯。

這個(gè)腳本在翻譯完后還會(huì)自動(dòng)檢查是否有漏掉沒(méi)有翻譯的i18n key。

然后翻譯工作就簡(jiǎn)簡(jiǎn)單單完成了,前后沒(méi)有超過(guò)半天。

九、安卓移植

這個(gè)時(shí)候我其實(shí)就已經(jīng)想發(fā)布內(nèi)測(cè)版本,把游戲發(fā)給我的朋友們玩了。

但是當(dāng)我表達(dá)出這個(gè)意圖時(shí),他們紛紛表示,坐在電腦前玩游戲太奢侈了,有沒(méi)有手機(jī)版?

好吧,雖然不打算發(fā)行移動(dòng)版本,但還是移植一個(gè)安卓版本吧。

然后我學(xué)習(xí)了Cordova的使用,并打出了一個(gè)apk包。

放手機(jī)上運(yùn)行,直接白屏,想想也對(duì),移植工作可不只是打包apk這么簡(jiǎn)單。

我需要把原來(lái)所有涉及到文件讀取的地方,改造成調(diào)用安卓API。

因此我重新設(shè)計(jì)了Files庫(kù),區(qū)分對(duì)待PC和安卓,游戲中所有涉及到文件的地方統(tǒng)統(tǒng)使用這個(gè)Files庫(kù)。

折騰了兩天之后,游戲終于可以在手機(jī)里運(yùn)行了。

十、朋友圈內(nèi)測(cè)

我興高采烈地發(fā)了一條關(guān)于游戲內(nèi)測(cè)的朋友圈:

第一時(shí)間就發(fā)給了胡大胖,結(jié)果胡大胖說(shuō),運(yùn)行白屏。

我當(dāng)時(shí)的表情是: ????????????

我的第一反應(yīng)是:?在我的機(jī)器上好好的啊

一問(wèn)才知道,他的手機(jī)是安卓11,所以肯定是一些兼容方面的問(wèn)題,安卓11的webview沒(méi)有后面的安卓版本高。

我又花了兩天通過(guò)調(diào)試安卓11的虛擬機(jī)解決了這個(gè)兼容問(wèn)題。

胡大胖對(duì)游戲開始了非常嚴(yán)謹(jǐn)?shù)販y(cè)試,一直到最后我點(diǎn)下游戲發(fā)行的前一刻,他還在廢寢忘食地測(cè)試游戲,一遍一遍地玩已經(jīng)玩過(guò)很多遍地劇情,在此再次對(duì)胡大胖表示感謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝!

在游戲的測(cè)試中,不斷發(fā)現(xiàn)有新的bug,但是改bug并不讓我感到痛苦,所以整個(gè)過(guò)程都很順利。

十一、Steamworks注冊(cè)

在測(cè)試游戲的過(guò)程中,我想起要去注冊(cè)Steamworks去發(fā)行游戲了(其實(shí)這一步應(yīng)該更早的進(jìn)行),趕忙注冊(cè)了一個(gè)Steamworks賬號(hào)。

注冊(cè)賬號(hào)的過(guò)程中,支付了100$用于購(gòu)買發(fā)行坑位,按照Steam的說(shuō)法,當(dāng)游戲銷售額達(dá)到1000$時(shí),這100$會(huì)還給我。

然后是填寫美國(guó)的稅務(wù)表,就按身份證上的信息填寫就可以了。

填寫完,很快steamworks會(huì)提示需要上傳補(bǔ)充信息,其實(shí)就是身份證的正反面和手持身份證的正面照,照做就可以了,我一開始沒(méi)有仔細(xì)看英文的提示,沒(méi)有上傳手持身份證的正面照,稅務(wù)表被打回來(lái)了一次,最后提供了手持身份證正面照就成功了。

這個(gè)稅務(wù)表的審核如果順利的話2-3個(gè)工作日即可完成。

注冊(cè)好steamworks后我做的第一件事,就是給游戲定價(jià)。

因?yàn)槲乙矝](méi)有打算能夠回本,當(dāng)然也不奢望銷量會(huì)爆,所以我想要不就把價(jià)格設(shè)置得低一點(diǎn)吧,回本是不可能回本了,那就國(guó)區(qū)賣9。9人民幣,美區(qū)賣1。99$。

其實(shí)我還可以定得更低一些,但又覺(jué)得那未免也太不尊重自己了,就算了。

十二、Steam商品頁(yè)準(zhǔn)備

接著我開始準(zhǔn)備Steam的商品頁(yè),按照Steamworks里的表單一項(xiàng)項(xiàng)填寫就可以了,雖然這個(gè)商店管理后臺(tái)詭異且充滿了屎山的味道,但還是勉強(qiáng)可以使用。

唯一要注意的是上傳商店圖片素材時(shí)它是根據(jù)圖片尺寸來(lái)自動(dòng)填充到對(duì)應(yīng)的表單位置的,所以圖片的尺寸一定要符合它的要求。

我電腦上沒(méi)有ps,我是直接到Photopea網(wǎng)站上調(diào)整的素材大小。

然后我用剪映制作了一個(gè)極其粗糙的宣傳片,因?yàn)槲矣X(jué)得商店頁(yè)面有個(gè)游玩視頻感官上會(huì)更好一些。

這里因?yàn)槲矣螒蛱峁┝朔斌w/英語(yǔ)/日語(yǔ),游戲商店我也進(jìn)行了繁體/英語(yǔ)/日語(yǔ)的本地化設(shè)置,主要是游戲描述的文本。

全部設(shè)置好后提交商店審核,然后因?yàn)橐恍┬〖?xì)節(jié),審核被打回來(lái)了一次,修改后,重新提交審核就通過(guò)了。

審核通過(guò)后,商店就可以在Steam里搜索并被玩家看到了,這個(gè)時(shí)候Steam會(huì)贈(zèng)送一些曝光,游戲愿望單每天都有增加。

這里前后花了一個(gè)星期的時(shí)間,這里我犯了一個(gè)錯(cuò)誤,商店審核后沒(méi)有立刻點(diǎn)擊商店發(fā)布,導(dǎo)致游戲發(fā)行時(shí)間延后了,因?yàn)橛螒蛘桨l(fā)行時(shí)間必須在商店頁(yè)面發(fā)布兩周以后。

接著是游戲主體的審核,這里其實(shí)并不需要提供游戲的最終版本,而是只需要一個(gè)接近最終版本的游戲版本的就行了,所以即便有bug,也可以提交上去供Steam審核。

第一次審核時(shí)Steam又找了一個(gè)商店頁(yè)面的問(wèn)題打回來(lái)了,并且說(shuō)最好是支持一下steam overlay,就是進(jìn)入游戲后按shift+tab出來(lái)的那個(gè)東西。

我想這應(yīng)該不難吧,把商店的問(wèn)題改好后,就找了steamworks。js庫(kù)去適配steam的api,結(jié)果出來(lái)的效果不行,一按shift+tab界面就卡死了。

后來(lái)在網(wǎng)上一篇文章里找到了原因,是因?yàn)閑lectron渲染的網(wǎng)頁(yè)是不會(huì)實(shí)時(shí)刷新的,這和普通的游戲不一樣,按下shift+tab后steam overlay雖然有出來(lái),但是就消不掉了,我在那篇文章里也找到了對(duì)應(yīng)的workaround:

“`
function initSteamOverLay() {
function fakeGameloopForSteam() {
const canvas = document.getElementById(
“fake-refresh-steam”
)
const styler = canvas
styler.style.width = `100vw`
styler.style.height = `100vh`
const ctx = canvas.getContext(“2d”)
ctx.clearRect(0, 0, 1, 1)
// Not sure if this could work if fully transparent or if setting CSS opacity to 0, I haven’t tried yet
ctx.fillStyle = “rgba(0, 0, 0, 0)”
ctx.fillRect(0, 0, 1, 1)
requestAnimationFrame(fakeGameloopForSteam)
}
const canvas = document.createElement(“canvas”)
canvas.id = “fake-refresh-steam”
canvas.width = 1
canvas.height = 1
const styler = canvas
styler.style.position = “fixed”
styler.style.top = “0px”
styler.style.bottom = “0px”
styler.style.pointerEvents = “none”
styler.style.zIndex = “30000”
document.body.appendChild(canvas)
fakeGameloopForSteam();
}
“`

然后我又提交了一次steam游戲?qū)徍?,這次審核通過(guò)了。

在這個(gè)過(guò)程中,我得到的教訓(xùn)是,其實(shí)可以更早一些注冊(cè)steamworks并發(fā)布商店頁(yè)面,因?yàn)樯痰旰陀螒驅(qū)徍酥辽僖玫?周,而商店發(fā)布后又需要等2周才能點(diǎn)發(fā)行,所以提前2個(gè)月甚至3個(gè)月去做發(fā)行相關(guān)的事情是比較合理的,這樣就不會(huì)出現(xiàn)游戲做完了卻無(wú)法點(diǎn)擊發(fā)行的尷尬場(chǎng)景。

十三、這樣就可以了嗎

游戲做到這一步,我感覺(jué)已經(jīng)差不多了,但是在等待steam審核的時(shí)候,我又寫下了這樣一段話:

“`
從一個(gè)玩家的視角,如何去判斷一個(gè)游戲是否好玩?
我覺(jué)得最重要的是有沒(méi)有在游戲中體會(huì)到樂(lè)趣。
游戲玩家其實(shí)是一個(gè)特別容易討好的人群,他會(huì)因?yàn)橛螒蛑幸恍┚傻脑O(shè)計(jì)捧腹大笑,也會(huì)在看到一些新奇的很小的東西時(shí)感到開心。
并且游戲玩家富有同理心,他們對(duì)游戲的代入感特別強(qiáng),你在游戲里討好他,他心里清清楚楚并且很享受。
作為設(shè)計(jì)者,我們的游戲是對(duì)真實(shí)世界的拙劣的模仿和放大,在其中設(shè)定一些真實(shí)世界不常見(jiàn)甚至是完全不可能的事情。
我們?cè)谠O(shè)計(jì)游戲的時(shí)候,需要迎合受眾的尋求,增加相應(yīng)的機(jī)制去滿足玩家的心理需求,這些機(jī)制可以是以下幾種形式:
1. 獨(dú)一無(wú)二的特殊事件,通常以游戲主線或分支劇情的形式展開
2. 基于隨機(jī)性過(guò)程和結(jié)果重復(fù)的循環(huán)事件,就像是釣魚一樣,你永遠(yuǎn)不知道今天自己會(huì)釣上來(lái)什么
3. 與真實(shí)世界形成反差的任何游戲設(shè)定,現(xiàn)實(shí)中越難得到的,在游戲中越容易得到,所以連歡樂(lè)豆都會(huì)有人喜歡攢
4. 與真實(shí)世界可以形成對(duì)照和代入的罕見(jiàn)事件,游玩過(guò)程中玩家并不具體期待某一件事情,但是永遠(yuǎn)在期待好的事情
5. 玩家需要輕微的挫折,人性都是如此,太容易得到的就不會(huì)珍惜,因此玩家在某個(gè)方面違反了設(shè)計(jì)者設(shè)定的機(jī)制時(shí),便會(huì)在游戲中受到數(shù)值或其它方面上的懲罰
“`

我又根據(jù)這些思考,對(duì)游戲的部分劇情進(jìn)行了補(bǔ)全,尤其是戀愛(ài)事件,因?yàn)槲野l(fā)現(xiàn)胡大胖特別癡迷于和美女們搞好關(guān)系。

這樣,等待發(fā)行的這段時(shí)間就也充分利用起來(lái)了。

十四、最后的測(cè)試與直播

隨著可發(fā)行日期越來(lái)越近,在胡大胖還在瘋狂測(cè)試的同時(shí),我決定錄制一個(gè)游戲的游玩視頻,到時(shí)候進(jìn)行steam循環(huán)直播,因?yàn)槲铱戳藄teamwork的文檔,steam是允許錄播的,前提是你在頁(yè)面里有表明是錄播(Replay)。

在第一次錄制這個(gè)游玩視頻的時(shí)候,中后期我自己又發(fā)現(xiàn)了一個(gè)不可原諒的bug,就是游戲中就職的公司可能會(huì)在發(fā)薪日不發(fā)工資給玩家!

所以只好又匆忙修復(fù)這個(gè)bug,然后我發(fā)現(xiàn),修復(fù)的這個(gè)bug解決了一些游戲中潛在的一些隱性問(wèn)題。

這是一件很值得開心的事,現(xiàn)在就發(fā)現(xiàn)bug,比玩家玩的時(shí)候發(fā)現(xiàn)bug要好,作為一款低成本的劇情向獨(dú)立游戲,我知道玩家并不會(huì)給我第二次機(jī)會(huì),如果因?yàn)閎ug導(dǎo)致主線劇情無(wú)法正常游玩,玩家雖然不至于退款,但也不會(huì)再有興趣打開游戲了。

然后我第二次開始錄制游戲的游玩視頻,這次非常順利,錄制完后我把游戲?qū)崣C(jī)視頻用OBS軟件推流到steam直播,并且循環(huán)播放,很快我的steam商店頁(yè)面就能看到我在直播了。

十五、Steam發(fā)行上線

2025年1月1日零點(diǎn),我終于點(diǎn)下了游戲的發(fā)行按鈕,一切都畫上了句號(hào),也許不圓滿,但我實(shí)現(xiàn)了一個(gè)夢(mèng)想,付出了很多,但是在最后這一刻,我深深地感到了自豪。

游戲首發(fā)第一天就收獲了一條好評(píng),果然愛(ài)玩游戲的都是好人!

十六、最后的最后

原本發(fā)行后,如果沒(méi)有bug需要修復(fù),做一個(gè)獨(dú)立游戲這件事就應(yīng)該畫上句號(hào)了,但我覺(jué)得應(yīng)該把自己這些經(jīng)歷寫出來(lái),給后來(lái)者一個(gè)參考,也是給自己一個(gè)反思的機(jī)會(huì)。

于是見(jiàn)縫插針寫了本文,其中肯定有疏漏或錯(cuò)誤的地方,歡迎各位大俠指正。

最后,祝大家都能做自己喜歡做的事!

作者:hhacker

原文地址:https://hhacker.com/

本文由 @hhacker 授權(quán)發(fā)布于人人都是產(chǎn)品經(jīng)理。未經(jīng)作者許可,禁止轉(zhuǎn)載

題圖來(lái)自Unsplash,基于CC0協(xié)議

該文觀點(diǎn)僅代表作者本人,人人都是產(chǎn)品經(jīng)理平臺(tái)僅提供信息存儲(chǔ)空間服務(wù)

更多精彩內(nèi)容,請(qǐng)關(guān)注人人都是產(chǎn)品經(jīng)理微信公眾號(hào)或下載App
評(píng)論
評(píng)論請(qǐng)登錄
  1. 牛逼

    來(lái)自福建 回復(fù)