游戏开发入门
引子
經常有網友問我:我很喜歡玩游戲,可以從事游戲開發嗎?開發游戲需要哪些技能?一款游戲的開發需要哪些人員參與?諸如此類的問題比比皆是。作者以10年游戲行業的從業經驗做背書,為打算入坑游戲開發的朋友們答疑解惑。
開發團隊構成
首先要明確的一個概念就是網絡游戲(或者叫在線游戲)其實也是一種互聯網產品,因此,游戲的開發團隊也就具有互聯網產品開發團隊的基本特征。比如,技術上分前后端,有產品經理,有美工等等。早期我在開發社交游戲的時候,團隊組成和其他非游戲產品的團隊幾乎沒有區別,因為這種需要嵌入在網頁中的游戲和做一個功能性網頁需要的人力和技術棧很類似。之后的十多年,網絡游戲的復雜性和規模也越來越接近于大型的單機游戲,所以團隊形式也從之前類互聯網產品團隊演變成為了制作人體制。
制作人體制
制作人簡單來說就是全面掌握游戲設計、開發和運營的總負責人。你可以認為這個角色就是電影行業的導演+制片人。制作人體制,就是以制作人為核心打造的滿足游戲開發的職能組織結構。在制作人體制下不同職能的員工都要匯報給制作人(這一點和互聯網產品團隊的匯報路線有所不同。比如我是開發人員,應該匯報給技術線的負責人例如技術總監,而不是產品的負責人)。
我們用一個圖例來說明一下制作人體制下的團隊層級關系。
?
?
團隊職能劃分
首先你需要知道:一個游戲的最小核心職能成員只有3個:策劃,美術,程序。因為游戲開發的幾乎全部實體產出都是由這3個成員完成的。換句話說,組建一個最小的游戲開發團隊只需要3個人。甚至說,有同時具備以上技能于一身的人的話,他1個人就行。這樣的案例并不是沒有,比如大名鼎鼎的《Minecraft》,或者是我非常喜歡的夫妻檔開發的《Battle Heart》,以及許多在taptap上很成功的獨立游戲。
?
?
策劃(Designer)
策劃其實就是產品經理,主要工作是設計游戲的背景、故事情節,功能模塊等,并一一文檔化。其中,內容(系統)策劃一般做功能設計、故事情節等,類似電影制作里的編劇;而數值策劃是游戲這種互聯網產品特有的一種職能,游戲中有大量的數據化的工作,比如經濟系統,角色成長系統,都需要有一定數學功底的人進行設計。其設計結果的合理性決定了游戲的一個要素:平衡性。平衡性對游戲的品質和生命周期都有很大影響。星際爭霸能暢銷20年,和其完美的平衡性有很大關系。有些游戲還設置了關卡策劃,比如三消類游戲,不再贅述。
不客氣的講,策劃誰都能做,因為這個工種是一個幾乎不需要特定專業技能的工種(最多需要會Excel、Word)。一個有經驗的游戲玩家,且善于總結和思考,就能夠根據自身經驗給出一個基本設計。但是話說回來,要想成為一個優秀的策劃,難度非常大,對人員素質也有很高要求:創造性,合理性,完整性,平衡性,其工作內容是思維的產物,且極難量化。毫不夸張的說,一個游戲的成功與否,和策劃團隊的能力有最直接的關系。
我個人認為國內游戲行業優秀的策劃人員非常少,這也就是我們很少能看到令人驚艷的國產作品的原因。
策劃人員通常是美術和程序共同的敵人,需求變更會導致其他人做無用功或者無休止的加班。一個功能自己都沒想明白就讓程序去開發,改來改去成了家常便飯。所以不合格的策劃特別不受碼農的待見。
美術(Artist)
美術主要的工作是對游戲內容進行包裝和藝術化。根據游戲類型的不同,一般分為原畫、2D、3D、動畫等。原畫美術主要負責過場畫面,為3D提供原型,角色設計等。一個游戲推向市場時各種炫酷的海報等都是來源于原畫。2D主要負責界面的總體風格和布局設計,游戲中道具、武器等部件的繪制。3D顧名思義,就是做3D場景、角色。動畫一般是做游戲中需要的動態效果、特效,屬于錦上添花,比如技能釋放時的動畫,角色戰斗中的動態等等。
在早期,功能比較單一的小游戲或者社交游戲,團隊里通常沒有固定的美術人員,而是由統一的美術部門進行支持。比如互聯網公司的美工需要負責頁面的設計,游戲部門有需要就調派美工進行支持。對復雜的游戲來說,美術的工作量是非常大的,而其產出又是階段性的,完成后不需要維護,所以養一個龐大的美術團隊成本上不劃算。因此,美術外包是業界比較流行的做法。也有美術團隊作為獨立部門存在的情況,會同時負責多個游戲,進組干活,完成后再去其他組。
美術是促成游戲成功的另一個主要因素。優秀的美術風格甚至有扭轉乾坤的能力。比如我之前參與開發的卡牌游戲《靈異陰陽錄》,有大量的忠實玩家是為了收集畫師的作品而持續的進行時間和金錢的投入,使得游戲的生命周期也得以延長。
美術人員只和前端程序有交集,和后端程序完全沒交集,沒有利益沖突,通常情況下都比較融洽。
程序(Programmer)
碼農大家都很熟悉了?,F在絕大部分游戲都要聯網,所以有前后端之分。前端主要負責頁面端、App端的展示邏輯,或者是和展現相關的物理特性處理邏輯,如尋路、碰撞、同步插值計算等等。后端主要負責業務邏輯,但其實無非是對數據進行操作和讀寫而已。有些邏輯的責任方并不明顯,可以選擇寫在前端或者后端,一般要根據性能、實現難度等情況去判斷,保證合理性。
我個人認為,程序的好壞,不能決定游戲的成功,只能決定游戲的失敗。代碼質量的區別,只有性能、健壯性、擴展性的區別,在功能覆蓋點上是一致的。游戲上線初期用戶量很小,程序質量的好壞很難被檢驗,用戶完全不知道程序寫的是優雅高尚還是狗屎一坨,因為他不能直觀的看到。而一旦游戲成功了,DAU全面飆升,程序的重要性才逐漸顯現出來。爛代碼會導致大量的bug、并發能力弱、游戲響應慢等問題,這些因素一旦超過一個閾值,就會讓游戲走向失敗,或者加快用戶流失率,縮短游戲的生命周期。一個很好的例子就是《我叫MT》在恰當的時間點推出而大獲成功,而后才暴露出服務端代碼在大用戶量時并發處理上的問題,CEO本人居然在微博上告誡玩家不要在高峰時期登錄。不去鞭策團隊優化性能,而建議玩家改變游戲行為,實在讓人貽笑大方。
程序員是整個團隊中最苦逼的一群人,班加的最多,黑鍋背的也最多,出了問題也是第一個要出來解決的。前端碼農通常比后端好一點,游戲打包完成就沒什么事了,而上線之后后端的噩夢才剛剛開始。你在地鐵上,公交上,馬路上,席地而坐處理線上問題的一定是后端碼農。盡管后端沒法決定游戲成功,但一不小心就能毀掉一個游戲甚至是整個公司,工作風險極大,需要有強大的心理素質。
支持部門
支持部門的工作職能相對獨立,有可能是由多個團隊共享的,比如QA,可以為公司多個游戲開發團隊進行測試工作,而不僅僅服務于某個團隊。支持部門也會根據游戲的復雜程度和團隊規模做一些裁剪。不能說這些職能可有可無,但相對比較靈活。
項目經理(Project Manager):項目經理不管人,管項目,比如進度、成本、質量、各組之間協調等等。不是必須存在,有些公司或團隊省略了這個角色,由制作人兼任。
音樂音效(Audio):這部分其實也是游戲實體的一部分,好的音效錦上添花的作用很明顯。一般都是外包。比較大的公司有自己的音效師在各團隊間共享。
測試工程師(QA):測試常駐開發團隊的情況有,但比較少,除非是公司就只有一個游戲項目。游戲和其他的互聯網產品不同,很難進行完善的自動化測試,大量的功能點需要人肉測試,比如跑地圖。另外,因為游戲產品存在大量功能交錯和耦合的特點,單個功能點正常的情況下,組合后就容易出現問題。QA是游戲質量保障最重要的環節,我很難想象沒有完善測試的游戲在玩家手中會是個什么樣子。前陣子騰訊倉促上線的吃雞游戲就因為bug太多不得不回爐重造,這種例子在以前單機和主機游戲上也時有發生。QA也是比較苦逼的一個工種,每個release前基本上都是連軸轉,夜里報bug,白天碼農來修,難兄難弟。
運營(LiveOps):運營活動是讓游戲利益最大化的重要手段。沒有合理的運營活動,游戲在收入上會停滯不前。頁游時期有這樣一種運營人員,俗稱托,假裝是個大R玩家,在游戲初期領跑,等當前服的生態和用戶穩定后立即退出。我在做頁游運營支持的時候就干過這樣的事。運營人員主要的工作是設計活動內容,拉新或者老用戶召回等。通常節假日的活動都是收入的高點。而合理的運營行為也是保證游戲留存、降低流失、延長生命周期的重要手段。
另外,數據分析的相關工作一般也劃入LiveOps,他們主要是根據已有的BI數據,分析和給出各個指標,比如DAU、首日、7日、30的留存,收入,充值、道具消耗等等,對運營工作和決策提供參考。
運維(TechOps):很多小公司是沒有運維的,反正就是服務器、工具維護,后端碼農就兼職干了。國外游戲公司一般會細分出來,讓后端更focus在業務邏輯開發上。
市場(BD):BD的作用也不能小視,談渠道,談植入廣告,有時候抓住機會就能拯救一個團隊。
開發流程和工具
開發流程
這里要講的開發流程不是指搭建開發環境、寫代碼、提交代碼的這個過程,而是指整個團隊如何從0開始開發一款游戲需要經歷哪些階段。嚴格講這其實算是軟件工程方法學的范疇。我們不可能把各種方法學鋪開來一一介紹,那樣恐怕開個專欄都不夠。這里只聚焦在適合游戲開發的軟件工程過程。
推薦一種我認為非常適合中大型游戲開發的方法:裁剪過的Scrum(對Scrum還不了解的讀者可以閱讀官方文檔)。為什么是裁剪過的?因為游戲這種產品對變更和故障的響應速度要求很高,很多時候需要跳過各種繁文瑣節,快速處理問題。盡管Scrum本身就是敏捷開發方法,但有時候依然不夠快,需要裁剪。
我們先從宏觀上了解一下一個游戲從無到有的產生過程。
?
?
一開始,制作人會給出一個愿景,定義需要做一個什么類型的游戲,大概的設計思路是什么。這就好比電影導演說想拍一個電影,它主要的故事梗概是什么,風格是什么。接著,策劃團隊領會了領導精神,開始細化游戲的需求,并文檔化。技術團隊根據游戲的類型等信息,可以開始技術棧的準備。比如需要做MMO類型的游戲,那就需要前后端有長連接的通訊方式,并以此來選擇和搭建開發框架。前端根據需要選擇2d還是3d的引擎。美術團隊也可以準備原畫了,定義整體UI風格、角色等,3D建模工作也可以開始。
準備工作搞定后,進入具體開發階段。程序員、美術根據需求文檔進行開發、聯調、集成等。同時測試團隊也可以介入,編寫測試用例,demo開發出來后進行簡單的測試。測試通過并且bug修復后開發工作算告一段落,可以進行打包和部署并發布。新版本上線后運營團隊收集BI數據進行決策分析,上線運營活動、道具、功能等等。
注意,除立項和前期的準備工作外,整個開發周期都是一個迭代過程,每次階段性發布都有這樣的迭代。
接下來我們了解一下,Scrum是如何運行的,以及如何針對游戲項目進行裁剪。
?
?
在Scrum方法中,會把所有的需求細化成一個個的backlog,并形成一個總的產品backlog,其實就是任務列表。然后根據需求的優先級,在Planing(就是安排當前階段做什么事的會議)中把這些任務劃分到各個Sprint(開發迭代周期,時間根據情況長短不一,一般是1-2個月)。接著開發團隊就可以根據sprint backlog領取任務開始工作。通常每天都有一個daily meeting,每個人講述自己昨天干了什么今天要干什么,遇到了什么問題,需要什么資源等等。一個Sprint結束時會有一次review,同時還會有一個Retrospective(說白了就是批評與自我批評,表揚與自我表揚,逼逼這個開發周期那些地方做的好,哪些做的不好)。最后增量的發布這一迭代周期的產品,進入下一個迭代周期。
根據團隊、項目大小的不同,甚至是人員特性的不同,每個公司都有自己特有的開發流程,完全教條的遵從某種方法學是不可取的,通常都要根據自身情況進行裁剪。
游戲這種需要快速響應變化的2C產品,應盡可能的壓縮事務性工作和流程性工作,專注在產品開發本身才是最重要的。
首先,游戲團隊不需要遵從Scrum的團隊角色構成。游戲開發人員的職能分工相當明確,PO、Master這樣的角色沒有太大必要。策劃專注在需求的細化和準確度上,及時和開發團隊溝通即可。其次,減少事務性的工作。task的建立、分配等工作可以交由項目經理并由Lead協助完成;daily meeting可以降低頻度,但一周必須至少有一次。程序員不需要編寫詳細設計文檔(也要分情況而定,復雜的功能模塊做詳細一些的設計很有必要),描述清楚思路,確定設計方案,定義清楚接口就可以。Review是很有必要的一個環節,整個團隊坐在一起檢驗完成情況,需求實現是否偏差、是否有明顯bug等等。而Retro環節可以只involve 各team的lead參加,匯總問題即可。
另一個需要注意的是,游戲產品每次迭代更新都需要看到較明顯的變化,這就意味著sprint不能設置的過短。否則一是產品變化不明顯發布的意義不大且增加更新風險,二是周期縮短后事務性工作會占用更多時間。通常建議一個迭代周期以6-8周比較合適。
這部分推薦的開發流程并不是唯一標準,只是筆者經過多年的積累和實踐后,認為比較科學、操作性強、行之有效且能很好的把控進度和質量的一種方法。上面已經解釋過,方法千變萬化,只有適合自己團隊的才是最合理的選擇。感興趣的讀者可以去下載一份Valve公司(沒錯,就是那個大名鼎鼎的開發半條命的公司,也是Steam平臺所屬的公司)的新員工手冊,了解一下Valve的開發流程,相信一定會給你耳目一新的感覺。
工具
使用工具可以幫助你高效的完成工作,這里推薦和scrum流程完美匹配的JIRA,以及幾個輔助開發和部署的工具。
JIRA & WIKI
JIRA幾乎成了敏捷開發的標配工具,你的公司不使用JIRA進行項目管理你都不好意思和人打招呼。無論是任務分配、項目追蹤還是Bug匯報,都和Scrum結合的天衣無縫。加上Confluence做wiki,基本上軟件開發周期中需要追蹤和文檔化的東西都齊活了。
?
?
Git/SVN
代碼管理必備,現在是個碼農就沒有不會用Git的。Git基本上已經一統天下了,列出SVN的原因是游戲項目中的美術資源,甚至是一些大項目的前端代碼,因為占用空間太大的原因并不適合用Git去管理,SVN更加適合。
另外推薦一款Git的可視化工具Sourcetree,用它做命令行的輔助,很多使用場景下簡單又高效。
Jenkins
Jenkins也已經成DevOps的標配了,CI/CD的重要集成工具。使用它可以高效的完成代碼的打包部署工作。
?
?
Sonar
sonar是一個代碼質量管理工具,能幫助你消除代碼中的缺陷和壞味道,保證代碼質量并幫你建立良好的編碼習慣。
?
?
Gmail & Gtalk & Google Doc
Google的這三個套件并不是必須的,完全可以找到對應的替代品。但當你基于它們進行團隊的溝通和信息交流時,你會發現十分的好用,特別是對游戲開發團隊。無論郵件,內部的IM,PPT、Word文檔的共享,一個鏈接就能搞定一切,省去了傳來傳去且版本變化后不一致的問題。墻裂推薦這套工具作為公司的信息交互平臺,當然前提是需要科學上網。
程序開發人員技能樹
前端開發(Frontend)
也叫客戶端開發。隨著10多年網絡(在線)游戲的變遷,前端技術棧的變化相對后端要更大一些。最早我們做社交游戲的時候是用Flash嵌入在網頁中,開發人員主要使用的語言和工具是ActionScript、Flash Air。而頁面部分需要掌握HTML、CSS、JavaScript等技術。頁游要看載體,大部分還是Flash,一些Mud類的游戲只需要JavaScript做處理就夠了。
手游的前端技術就大為不同了。對于2D游戲來說,cocos2d是主要的開發工具。嚴格講它是一個游戲引擎,以及圍繞它構建的一整套開發環境和工具,并不局限于某種語言。通常使用C++進行iPhone版本的開發,使用Java開發Android版本。
隨著3D游戲的普及,Unity3D成為主流引擎替代了cocos的位置。Unity的功能非常強大,幾乎可以發布全平臺的游戲,也就是所謂的開發一次,發布多次。我參與的一個3D項目就是用Unity同時打包出iPhone和Android版本。U3d主流開發語言是C#。作為一個后端開發,我不得不吐槽幾句。Unity確實強大,但啟動緩慢,占用內存極大,內嵌的代碼編輯器Mono Developer用起來那叫一個蹩腳,不說了,滿滿的都是淚。
除了這些專屬于前端的技術外,計算機基礎知識也非常重要,比如算法、設計模式。前端需要和后端進行通訊,網絡及協議相關的知識要很熟悉,比如HTTP、socket、web socket、RPC等。另外,部分數據可能需要存儲在客戶端本地,文件存儲的知識也是必須的。前端開發的一大難點要屬性能優化了,手游在各個渠道發布的時候通常會對安裝包的大小做限制,這就需要你在游戲加載、資源質量上做文章;而游戲過程中幀數高低、效果的渲染導致的CPU占用率問題也是主要要面對的性能問題。
?
?
后端開發(Backend)
后端又叫服務器端。網絡游戲的大部分業務邏輯都是在后端完成,但實際上游戲的成敗和后端的關系比較小,因為它離用戶最遠,幾乎對用戶透明。一個看不見摸不著的東西自然不會對用戶的評判有影響。好的服務器端就是讓用戶感覺不到它的存在,好像在玩一個單機游戲一樣,沒有網絡延遲,沒有卡頓。什么時候服務器端變得不透明了,讓用戶感覺到了,就是需要優化的時候了。
既然要完成大部分的業務邏輯,首先需要學會一門功能比較完善的綜合性語言。在業界主流的后端開發語言是C++和Java。使用C++是因為它高效的網絡處理能力和性能。使用Java是因為它的綜合實力和低門檻(和C++比)。我個人更偏向于Java作為后端語言,一是生態圈更加成熟完善(Spring可能是所有語言的框架中最完善最流行的,而各種大數據工具也多是基于Java平臺);二是相對純粹的面向對象能力進行建模也更加容易;三是Netty這樣的網絡框架也能彌補性能上的不足,使開發人員聚焦于業務。C++太過強大不易掌控,一旦使用不當反而會出現性能問題,對開發人員的要求也更高。除此之外,游戲圈也不乏有其他語言作為后端開發的語言,常見的有PHP、Node.js、Golang等。
既然是服務器端開發,就要和服務器打交道,Linux系統知識、命令、shell這些東西是必備的技能。它能使你的開發工作更加高效和流暢,是語言外最重要的輔助技能。網絡和協議也是必須要掌握的,前后端如何通訊是一大主 題,需要根據游戲特性選擇合理的通訊方式。一個比較復雜的游戲,一般長短鏈接是都要具備的,協議方面使用gRPC(protobuf)、Thrift是不錯的選擇,即高效又簡潔。也有自己定義二進制協議的,但維護起來相對麻煩。
除語言外,另一個重要的技能就是持久層知識。本質上,前端的工作就是展示數據,后端的工作就是讀寫數據。幾乎所有的所謂業務邏輯,無非就是讀出數據攢一個前端需要的扔過去,或者把用戶行為產生的數據保存下來。后端是數據的持有者,如何高效的讀寫數據就成為后端開發中的重點和難點。所以,對持久層的理解深度就決定了一個后端開發人員水平的高度。首先,要對使用的主要存儲有深入的了解,避免出現使用上的低級錯誤或性能問題。其次,要學會對不同的業務場景使用不同的存儲媒介,合理的存儲能極大的簡化開發難度。比如排行榜這種業務直接使用Redis的zset會比你自己實現高效的多。
后端是數據的生產者,很多數據的消費方都依賴于它,比如BI。掌握一定的大數據處理工具能讓你的技術棧更全面。
第三個重要的技能就是應用服務器本身了。后端程序通常都是以webserver為容器部署的,所以你需要對常用的容器非常了解,比如Nginx、Tomcat、Apache等。另外云服務器的相關使用也需要掌握,現在基本上鮮有部署在實體機房的應用,PaaS平臺是主流。和國內的云服務提供商相比,AWS有很多自己特有的服務,需要一定的學習曲線。隨著Kubernetes的普及,docker容器的知識也是后端人員需要掌握的。
最后說說架構設計能力。一方面是設計模式在功能模塊中的使用。游戲的業務場景中有大量可以使用設計模式的地方,用好模式可以事半功倍。另一方面是系統架構的設計。網絡游戲必然是一個分布式系統,分布式系統的特性和問題游戲都一樣存在。比如彈性設計、性能設計、服務治理、監控等等。這方面的內容是一個巨大的課題就不展開講了。一個后端開發工程師要想過渡到架構師就必須具有架構設計的能力。
總結一下后端開發人員的技能樹:
- 精通一門綜合性語言,最好是面向對象語言;
- 持久層知識,深入了解常見的存儲系統,比如mysql、mongodb、redis等,學會用合理的存儲系統組合降低業務開發復雜度;
- 服務器相關的知識,包括linux系統及命令、webserver、云服務器、容器等;
- 系統架構的設計能力,分布式系統、微服務等。
?
?
服務器端架構選型
根據游戲的類型、需求不同,服務器端架構也會不同。我個人認為一個比較完善的服務器端架構需要具備下面的功能:
- 網絡通訊及協議:確定游戲使用HTTP短連接還是Socket長連接和前端交互,協議數據格式使用二進制還是JSON;
- 共享數據同步:通過引入分布式緩存等機制實現世界Boss這類功能;
- 通知推送(發布、訂閱)能力:任務系統、消息系統等功能需要推送更新;
- 消息隊列:通過它實現數據的異步處理能力;
- 定時任務系統:每日任務刷新、日更排行榜、獎勵、CD重置等,游戲中大量功能需要定時系統去觸發;
- 邏輯分區;根據時區、地區、用戶屬性等進行分服、合服的能力;
- 后臺管理:包括玩家信息查詢、運營管理、策劃數據管理、發布維護等等;
- 大數據處理:用戶行為會產生大量的BI數據,用來進行決策和運營活動,大數據處理能力必不可少。包括日志采集、收集匯總,報表等;
- 灰度發布、A/B Test:游戲中為驗證某功能的好壞常常需要進行灰度發布,系統應具有這樣的能力;
作為2C的互聯網產品,游戲有幾個非常重要的特點需要考慮到:
- 可伸縮性:整個系統是彈性的,可伸縮的,且最好能做到自動化。高峰時增加服務器,低谷時減少服務器(AWS的auto scaling可實現這種能力);
- 安全性:其一是游戲本身的安全性,即防外掛防作弊,玩家觸發的數據都要經過后端驗證,且設置警戒線,超過警戒線的數據必然是作弊行為;其二是數據安全性,存儲的數據應該有備份,且能夠快速恢復;
- 性能:高并發情況下容易出現性能瓶頸,而游戲通常的瓶頸都在持久層。分庫分表、讀寫分離、多級緩存等是解決持久層性能的主要手段。當然,大前提是代碼不能寫的太爛,否則神仙都救不了。
下面介紹幾種不同劃分方式下的架構模型。
按通訊方式劃分
短連接通訊
即通過HTTP進行前后端的通訊。前端發送請求,后端把response結果返回給前端。這種模式其實和大部分互聯網產品沒有本質區別,通訊層比較輕量級,一個邏輯上的webserver就可以搞定,易于維護和擴展。基本上可以滿足弱聯網游戲的需求。比如社交游戲、部分頁游、非實時對戰的卡牌游戲等。
短連接的情況下前端獲取數據都需要用拉(pull)的方式,所以無法將消息主動從服務器推送(push)給客戶端。服務器和客戶端之間也無法維持狀態。所以,對實時性要求高的游戲,就必須要用長連接的方式了。
長連接通訊
即服務器和客戶端維持一個連接不中斷。通常底層的通訊協議是socket。實時性要求高的游戲都必須用長連接進行通訊,因為前后端需要實時的進行數據交互,數據即可以從前端拉取,也可以從后端推送。比如MMO類型的游戲,或者是有實時對戰功能的游戲,比如爐石傳說、皇室戰爭;再或者有數據推送的需求,比如全服的廣播等。
看上去長連接的能力更強,但也有缺點。因為服務器要和客戶端一直保持連接,對系統資源的消耗更大。一臺標準配置的服務器能支撐5000-10000左右的連接就算很不錯了;用戶量越大,服務器集群規模遠大于短連接架構,成本也越大。另外技術實現上也相對復雜,處理不當比較容易出現性能問題。
混合型
一個完善的架構會同時具有長短連接的通訊能力,在對應的場景下使用合適的通訊方式。
值得一提的是,有一些功能是2種連接都可以實現的。比如每日任務,即可以通過長連接的方式主動推送刷新任務到前端;也可以使用短連接方式,當用戶進入任務系統界面時發送HTTP請求獲取任務列表。這樣的例子有很多,使用哪種方式需要考慮實現成本。
按網絡模式劃分
全球同服
顧名思義,游戲只有一個公共的入口,所有進入游戲的玩家都在同一個服,或者說都可以看到、交互。這在早期社交游戲時代是非常普遍的,比如Zynga的CityVille,你就只能通過Facebook這一個入口進入,所有的玩家都可見或產生交互。
隨著不同的平臺、網絡環境的增多,全球同服的概念被弱化了,比如Android和iOS平臺下數據是不互通的,再比如中國版本和國際版本也不能互通(原因你懂)。但這種情況本質上也依然算是同服。
分區分服
分區(zone)一般指的是按照一定屬性對數據進行邏輯分離,最常見的就是地區分區,比如暴雪的游戲爐石、星際爭霸II,分了臺服、國服、美服等;或者根據網絡運營商分區,比如電信區、網通區等等。
?
?
典型的分服起源于頁游時期,同一套游戲程序,不斷的部署到新開的服中,服務器之間獨立,數據也不互通。通常的策略是一個服的生態較為穩定了,收入也飽和了,沒有多少新增就開新服。在同一個渠道的一組服通常服務器物理上也在一起,和分區的部署不一定相同(分區模式要根據地區選擇最優的網絡節點)。
?
?
和全球同服的模式相比,分區分服模式下各個區、服的數據都是隔離的,不可見的,你是一區的老大,我是二區的老大,互不影響。這也就促成了一種所謂“洗用戶”的賺錢方式:一服玩家差不多了,開新服,繼續拉新賺一波,循環往復,這就是為什么能看到很多頁游有上百個服的原因。
舉例:一個微服務游戲架構
游戲的業務模塊和技術模塊相對容易分離,非常適合微服務架構。早在微服務流行前,游戲業界的后端架構已經有了模塊化的實踐,比如分了登錄、游戲服務、場景服務、網關服務、聊天服務等等。下面是我繪制的,并且個人認為比較完整、合理的服務端游戲架構。
?
?
- 通訊層:用來和客戶端進行通訊,支撐長短連接,長連接使用gRPC方式;
- 業務層:具體的游戲業務邏輯層,每一個模塊都是一個服務,在微服務架構中以獨立的進程或者集群方式存在。這里列舉了一些常用的公共業務,比如登錄服務,用戶系統,獎勵系統,排行榜、戰斗系統等等。
- 中間層:也可以叫基礎服務層,為實現業務模塊提供必要的技術層面的支持。比如HTTP server,socket框架,分區系統,搜索引擎,消息隊列,后臺任務,定時任務等等;
- 持久層:具體的數據存儲,包括本地、分布式緩存,數據庫(可以是關系型或NoSQL),CDN等;
- 支撐系統:為整個架構系統提供公共的支持服務,比如負載均衡、訪問控制、配置管理、日志、統計、監控服務等。
經驗分享
上線流程
前端代碼打包后就發布到各個渠道了,沒有太多后續工作。這里要講的是后端代碼的上線流程。一個比較合理的上線流程應該包括本地環境、開發環境、測試環境、預演環境和生產環境這幾個階段。
?
?
- 本地環境(Local):程序員自己的本地開發環境,主要完成功能的開發和單元測試;
- 開發環境(Development):通常是給前后端集成、聯調使用的,本地環境并不穩定,需要有這樣一個中立的環境進行集成,或者是demo演示;
- 測試環境(Testing/QA):Dev環境主要的使用者是前后端程序員,在集成過程中很可能頻繁改動,所以如果測試人員使用Dev機器進行測試的話,很有可能影響測試的準確率。比如本來是正常的功能后端重啟的服務而QA并不知情,就出現了一個不存在的bug。所以對于一個有正規測試流程的團隊來說,測試環境很有必要。如果是很小規模的團隊或者是小的游戲,測試環境也可以和Dev環境合并;
- 預演環境(Staging):一個在架構上和線上環境完全一致的環境,唯一的不同就是集群規模、機器性能、數據量等。線上的架構都是分布式的,而Dev這樣的環境因為便捷性的考慮都是一個all in one的模式,很多在分布式系統中存在的問題沒法在Dev環境下測試出來。Staging是上線流程中最后的一環,相當于守門員,不可或缺。
- 線上環境(Producation):最終的生成環境,交付給用戶使用。
保證上線流程的完整性非常重要,它能以一個漸進的方式逐步提高代碼質量直到交付階段,是保證游戲盡可能不出現問題的重要手段。
代碼安全
代碼安全一方面是物理上的安全,即代碼是否會被泄漏,被人copy走。這方面每個公司都有自己的做法,比如機器沒有外網環境,不能使用U盤等(我個人非常唾棄這種缺乏信任的做法)。這里主要講邏輯上的安全,即團隊協同開發模式下代碼在進行merge時不會丟失、被覆蓋、被刪除的問題。
借助Git的分支管理能力可以最大限度的保證代碼合并的安全性。下面是我比較推薦的一種分支管理方式。
?
?
首先,我們有一個master主線分支,每個開發周期開始,從它checkout出dev分支;負責不同功能模塊的程序員基于dev分支再打出自己的feature分支進行開發;有需要集成和依賴時merge回dev分支;整個開發周期的開發任務結束并準備上線時,從dev分支打出release分支,此分支即為線上環境運行的代碼,并merge回master。如果遇到了bug需要臨時修復,就從master拉出一個hotfix分支,更新后再merge回master。
通過這樣一個科學的分支管理方法,基本上就可以避免代碼merge上的絕大部分問題。
數據安全
數據可以說是互聯網產品最寶貴的資產,特別是用戶產生的數據(UGC)。拋開黑客攻擊這種問題不談,我們只講如何避免操作失誤造成的數據丟失問題。
給大家講一個真實的例子。2010年左右我還在某SNS網站做社交游戲,我們當時有一款品質非常好的農場類游戲,幾千萬用戶,百萬級別的DAU,各方面數據都很穩定。有一次有個新來不久的同事為了做一些驗證測試,打算把自己線上的用戶金幣數進行調整,于是他在mysql終端中寫下了這樣的代碼:
update user set money = 10000;不知道是疏忽了還是當時迷糊了,在沒有加where條件的情況下就回車執行了。對于一個千萬量級的表來說這樣的更新操作是很慢的,由于經驗不足他也沒有對半天都沒響應的情況深究,轉頭去忙別的事。最終的結果,所有的玩家金幣被更新成了一樣的數量,游戲的經濟系統和生態完全崩潰。更倒霉的是數據庫的備份是按周而不是按天,只能回滾到一周前的數據。對于這種數據級的游戲,一周時間在數據上的gap是巨大的。整個團隊沒合眼花了三天兩夜通過log等各種方式進行數據修復,但結果并不理想。從此之后這款游戲的各項數據指標一路下滑,提早的結束了生命周期。
這樣嚴重的事故告訴我們,需要在以下幾個方面建立完善的制度和流程:
- 權限管理:服務器和數據庫的訪問權限需要層層設置,逐步收斂到最終負責人;
- 數據庫操作:避免對線上數據的直接操作,如需要可使用從庫(slave)替代;重要的寫操作需要有人review;
- 備份機制:備份的間隔在容許的范圍內盡可能短,主從兩臺是不夠的,master的誤操作也會被同步到slave,還需要單獨的backup做增量備份(這一點可以參考mongoDB的3臺為一組的shard結構);
- 日志系統:完善日志,對關鍵數據的變更進行記錄(change history),保證數據可追蹤。
線上環境更新與維護
這部分簡單介紹一下游戲的更新、新代碼部署上線的問題。早期實體服務器沒什么特別,老老實實一臺臺的更新。云服務器下就有了更多選擇,主要有2種:
- 滾動式更新:和實體機時代類似,在當前的實例上進行更新操作,通常要依靠腳本進行。這種方式沒有實例切換的風險,實例相對穩定;但如果是熱更新的話需要新老代碼的兼容,保證請求的冪等性。否則的話要么需要停服維護,要么就沒法使用這種方式。
- 替換式更新:即完全啟動一套新的實例,運行新的代碼,集群建立完成后通過負載均衡進行網絡切換,把流量打到新的集群,完成更新后老集群再terminate掉。這種方式需要先準備好一套新的實例,新實例的穩定性也需要多關注。相對滾動更新來說不容易出錯或遺漏,也不用考慮兼容的問題。
另外需要注意的是,熱更新,即不停服情況下,一定要注意服務的上下兼容問題;如果是停服更新,避免生硬的強行把用戶踢下線,應盡可能做的友好,提前通知,快要停服前進行重復間隔性通知。
故障處理
軟件系統出現故障是難免的,本篇最后再介紹一下如何處理故障。
系統恢復的幾個方法
- 重啟:重啟一般不能根本性的解決問題,但有些情況下確實可以作為一個緩沖之計,為修復爭取時間。
- 回滾:包括代碼和數據層面的回滾??焖?、簡單,解決新上線問題的備用方案,但缺點是會給人帶來比較大的挫敗感。
- 降級:暫停出問題的模塊,停止服務并告知用戶。我們在LOZ項目中就使用了降級來保證模塊可以switch off,效果不錯。
- 緊急更新: 大多數正規公司都有繁瑣的上線流程。而緊急更新需要勇氣和魄力,還需要有強大的自動化部署工具做支持。我個人非常支持這種打破常規的hotfix,這是把事故影響范圍降低到最小的最快方法。所謂特殊情況特殊對待,和破壞流程的hotfix可能帶來的潛在風險相比,不更新是否會導致產品生命周期結束甚至公司蒙受巨大損失?兩相權益取其輕。
降低或消除故障的方法
- 故障演練:這個不多說了,去搜索一下Netflix的Chaos Monkey你就知道有多牛逼,以及你自己的公司有多low逼。
- 灰度發布:指先小范圍的發布,等穩定后再逐步擴大更新范圍,減少受影響用戶的范圍,降低更新風險。有一種是分地區分布,還有一種是AB Test,根據用戶屬性對不同的用戶執行不同的更新策略甚至是不同的業務邏輯。比如要上線一個新道具,對尾號單雙數的用戶使用不同的價格策略,通過收集到的BI數據分析哪種定價更加合理。這在游戲行業非常常用。
出現故障是需要復盤的,不能解決完了就完了,要對故障進行分析總結。一般的復盤步驟如下:
- 找出問題的根源(Root cause),分析出現原因;
- 總結故障解決步驟,并文檔化;
- 提出改進策略,避免同類問題再次發生。
最后說一下故障的懲罰機制。懲罰和故障本身是沒有任何因果關系的,對責任人的懲罰也許根本無法彌補公司受到的損失,帶來的后果則是大范圍的恐慌情緒,進而影響員工的積極性。做事就會犯錯,為了不受罰,那我干脆不做事打醬油好了。如果員工都抱著這種心態,恐怕公司也沒有存活下去的希望了。所以,對于開發人員,故障并不可怕,只要積極面對,避免同樣的錯誤發生,通過故障不斷學習成長才是最重要的。
結語
我們通過一個漫長的篇幅,從游戲的開發團隊構成講起,介紹了開發流程,游戲開發人員所需要的技術知識體系;接著介紹了游戲的服務器端架構的選型,并用一個示例說明;最后一部分是作者10多年游戲行業開發的一些經驗分享。相信看到這里,你對游戲開發已經有了一個初步的理解和認識。歡迎隨時和我進一步溝通交流,祝想入坑游戲行業的工程師們都能開發出自己喜歡的游戲!
總結
- 上一篇: xss测试工具xsstrike(基于py
- 下一篇: 音频测试方法(tiny)