地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案

遊資網發表於2019-05-27
5月10日至5月12日,Unity全球開發者大會Unite Shanghai 2019在上海召開,期間諸多技術專家來到現場為開發者分享主題多元的技術演講以及行業趨勢分析。

騰訊雲網際網路行業架構師餘多,在大會期間進行了“遊戲架構和雲服務的耦合前瞻——匹配對戰和連續大世界”主題演講,分享了雲端計算將對遊戲帶來哪些改變,透過對匹配對戰類遊戲解決方案和連續大世界類遊戲架構的剖析,展望雲端計算時代遊戲的未來。

以下為演講內容整理:

大家好,今天來這裡和大家一起做一個前瞻性的探討,關於遊戲架構和雲服務的耦合。今天的主要內容會由兩個遊戲架構組成,一個是匹配對戰類遊戲架構,這個我會講的簡單一點。另外一個是連續大世界的遊戲解決方案,這個方案我們會一步一步的拆分出來。

首先,我們快速回顧一遍遊戲和科技發展的關係。我個人接觸遊戲是從街機、家用遊戲機開始,那時候大家都在自己的電腦上、街機房裡用手柄玩遊戲。隨著科技的發展,個人電腦走進了生活,滑鼠帶來了操作方式的轉變,RTS遊戲開始崛起,滑鼠幫助RTS遊戲進入了大家的生活。接著,網際網路進入了我們的生活,網路遊戲出現,大家玩遊戲的方式也發生了變化,從之前在家裡自己玩遊戲或者和小夥伴玩遊戲,變成了在網際網路上和陌生人、新朋友一起玩遊戲。

再往後,智慧手機的普及和4G網路的開啟,帶來了手機遊戲的黃金時代。很多休閒遊戲APP出現在我們的手機上,並且漸漸變得越來越複雜,遊戲性也越來越好。隨後,AR、VR和LBS技術方案的成熟,給我們帶來更新的遊戲體驗。

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


我們可以看到,隨著科技的發展,遊戲的創造力會不斷釋放出來,遊戲的體驗和形式也不斷髮生翻天覆地的變化。那麼,當雲端計算時代到來,雲端計算能夠為遊戲帶來怎樣的變化,能夠為遊戲體驗帶來怎樣的提升?這是我們今天初步探討的一個點。

我們就兩個遊戲架構進行探討,首先是匹配對戰的遊戲。

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


這是一個粗略且常見的匹配對戰型別遊戲的伺服器架構,由資料儲存、戰鬥服務叢集和戰場外服務叢集構成。常見的負載問題和玩家體驗問題,主要出現在戰鬥服務叢集和玩家匹配服務兩個部分。我把戰鬥服務和匹配服務標紅了,這是我們今天需要討論的,能否最佳化的重點地方。

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


我們首先看痛點,下面這個圖是某遊戲在一天中,它的玩家活躍情況。我們可以看到,在凌晨五點鐘左右的時候,基本上沒有人玩遊戲了,整個伺服器是空置的。12點到1點左右有個小高峰,晚上10點11點,是遊戲負載最高的時候。

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


遊戲過程中,業務規模通常呈週期性大規模波動。玩家高峰時期的伺服器負載問題令我們困擾,非高峰時又是算力閒置造成浪費。

研究雲服務提供的解決方案已經具備一定的可用性了,容器服務,比如說騰訊的TKE,秒級啟動,彈性伸縮。我們可以在一天內按照小時根據我們的業務負載,動態的調整我們的叢集實際數量,我們可以從圖中看到,這樣做下來的話,在一天中,和按需部署相比、按峰值需求相比,我們可以節省一半左右的數量。也可以透過雲服務提供靈活部署的能力,給遊戲的爆發性增長打下很好的算力提供基礎。這是已經具備可用性的東西,是彈性伸縮的部分,大家感興趣的話,可以再瞭解一下容器技術。

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


另外一個痛點,延遲問題。通常一局對戰的網路質量取決於與伺服器連線最差的那個玩家。有很多因素,通常是從遊戲公平性考慮,我們不能過度懲罰網路連線度比較慢的玩家。還有同步架構的模式,我們如果選擇幀同步方案,這個方案原理使得我們要等待連線最差的玩家把操作同步給其他玩家之後,才能把遊戲時間線繼續下去。

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


在這種情況下,如何才能進一步最佳化,讓參加一局對戰的所有玩家都更好的網路連線呢?我們考慮對匹配模組動手,匹配模組在傳統架構中是一個純業務模組,純粹的遊戲業務模組。在運維過程中,不會動到它。而我們考慮的另外一個資訊是,玩家和我們的各個戰鬥服務叢集之間的連線情況,這一塊是一個相對偏雲服務的資料,和我們的傳統業務模組之間有著比較大的隔離。

如果我們把原本隔離較遠的業務和資料耦合起來的話,我們會帶來怎樣的改變呢?舉個例子,圖中有6個玩家,已經初步經過了匹配。

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


我們的匹配系統透過他們的等級、戰鬥力或者近期勝率進行綜合判斷,覺得這幾個玩家可以匹配在一起。同時,把他們分配到兩場戰鬥中去,每場戰鬥三個人。我們在上海和廣東節點都各部署了一批戰鬥叢集,這時候按照傳統的業務,6個玩家就實際分配了。

但是每個玩家到每個戰鬥叢集的網路連線質量是不一致的,如果我們把這個資訊在原本匹配完成的階段,再進一步耦合進入我們的匹配邏輯,做進一步的最佳化,那我們可以根據圖上的情況,為玩家做一個最佳化的分組。按照這樣的分組,兩組三個人的話,每個玩家都可以獲得相對優秀的網路連線體驗。

這塊講的就是在我們的匹配模組中,如果我們耦合一些由雲服務這邊提供的網路資訊的話,我們有進一步最佳化玩家體驗的空間。

結合我們前面剛講過的彈性伸縮的問題,我們再來進行一個具有前瞻性的探討,有沒有可能把這兩者結合起來?是否可以根據已經匹配成功的玩家的綜合網路情況,選擇合適的雲服務節點,注意我說的是雲服務節點,而不是我們預先部署好的戰鬥叢集。這兩者的差距就是選擇範圍的差距。像我們騰訊在各個地區有很多可用區,這些可用區,我們是否可以不預先鋪設戰鬥叢集呢?

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


我們在匹配完成之後,根據玩家的網路情況,選擇合適的雲服務節點,快速啟動戰鬥服例項提供服務,戰鬥結算後,回收例項。就像下圖這樣,我們並不預先鋪設戰鬥叢集,玩家匹配成功之後,根據玩家的綜合情況,我們選擇最合適的雲可用區,在可用區了,透過技術,進行戰鬥服務的秒級部署。這樣可以進一步在有需要的地區,在網路情況最合適的地區,為玩家提供臨時的戰鬥服務。服務結束後,我們還可以把例項回收掉。

這樣的簡單型架構,我個人相信隨著行業的進一步成熟,我們技術的演進,是必然會被實現的。

這裡我們簡單講了一下匹配對戰這種遊戲架構型別下我們的雲服務可以進階提供哪些東西。接下來我們講一下連續大世界的架構,這是一個分散式計算的故事,首先我們瞭解一下連續大世界的需求。

如何提供給大家一個豐富精緻而又連續的大世界?這是我們今天探討的點。

假設在某MMO遊戲裡,模擬一個與地球表面尺寸相當的物理沙盒世界。有兩個關鍵因素,首先與地球表面尺寸相當,然後有物理沙盒的元素存在,說明單位面積內的算力要求非常的高。在傳統的MMO架構裡,我們最有可能怎樣做呢?我們可能會用一個場景伺服器叢集去不連續的描述這個世界,由不同的場景伺服器負責的場景,模擬玩家在這樣的世界中游玩的過程。

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


假設在遊戲中舉行一重大世界範圍賽事,環世界火箭車拉力賽,參賽的玩家同時駕駛火箭車沿赤道環世界一週。玩家A最終獲得了勝利,憑藉他高超的遊戲技巧,和頂級的個人電腦、網路配置,在整個比賽中行駛了10W公里。

我們想一下第二名追逐第一名的場景,兩輛火箭車追逐,忽然前車從穿梭門消失了,後車也緊跟過去,然後顯示了載入介面。我們連線另外一個伺服器,完成後,第二名進入到新的場景,開始在新的場景繼續追逐他,這樣尷尬的體驗肯定不是我們想提供給玩家的。造成這樣問題的原因是,在模擬大場景時,如果有物理、AI等算力的高需求時,需要的計算量遠超單臺物理機所能提供的。

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


黑石2.0裸金屬,80核384G,可以解決大部分的大世界需求。但是我們今天討論的可能是需要一百臺黑石才能解決計算的規模。

我們在設計一個方案的時候,第一步是設立方案的目標。

首先,要支援複雜計算,物理、AI、風或者火焰。然後,我們的世界要超大,這兩者加起來就決定了一點,即我們的算力需求是遠遠超過單臺裝置或者若干臺裝置所能提供的。並且我們要求場景體驗是無縫連續的,我們不希望玩家感受到這個世界是被割裂的,我們不希望玩家在區域之間切換的時候會載入,或者感覺到明顯的卡頓。

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


這個體驗分兩部分,一個是服務端這邊訪問不同場景的伺服器,另一個是客戶端的動態載入。客戶端的動態載入早在十幾年前就已經很好的實現了。今天主要討論的是服務端這塊的架構。再追加一個需求,我們希望這個世界在擴充套件的時候是不需要停機維護的。

這個需求其實很好理解,我們建立一個很大規模虛擬世界的時候,通常不是一蹴而就的,我們會先開發好一些區域開放給玩家,然後不斷迭代,開放新的區域給玩家。在這個過程中,我們希望新區域的開發和開放,不對舊區域造成影響。我們希望世界擴充套件不需停機維護。

基於這些需求來設計我們的方案,首先,我們在虛擬一個世界的時候,我們先要描述它。換句話說,在我們的記憶體中保管狀態。我們先要確定保管哪些資料,要做一個簡單的對實體概念的定義。遊戲世界中所有會產生狀態變化的物體或虛擬物體,我們把它定義為一個實體的概念,一個我們自己定義的概念。這樣的話,所有我們需要儲存的記憶體資料,簡單來講,就是這個世界上所有實體的集合。

因為我們的世界很豐富,而且很大,所以所有的實體資料會是一個很大的尺寸,超出了單臺物理裝置的效能瓶頸,我們需要一個分散式的架構保管實體。

這是非常簡易的分散式架構示意圖。

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


分散式叢集,主要由若干個實體保管者和一個叢集管理者構成。對叢集裡某個實體的訪問,比如我要訪問叢集裡某個實體,我們先會詢問叢集管理者在哪裡,叢集管理者說在保管管理者2。只要叢集管理者還承的住,那我們的數量就可以任意擴張,以達到我們對這個實體高數量的需求。

我們這裡有個前提,就是我們的叢集管理者沒有崩。實際上在遊戲具體應用場景裡,遊戲實體在遊戲過程中,是頻繁發生大規模的狀態改變,在這樣頻繁的訪問情況下。如果每次資料訪問都透過叢集管理者問一下的話,它很快就撐不住了,這個架構負載是非常有限的。我們這裡首先要做一個簡單的大面上的最佳化,確保我們的效能在需求的數量級範圍之內。

我怎麼做呢?可以針對我們保管的資料特性採取措施,我們保管的資料是實體,是世界中的實體。世界中的實體有怎樣的構成特性呢?大家可以想一下Unity裡的每個object都有怎樣的公共元件?transform。所以每個實體,不管他是虛擬物體還是真實存在的物體,在這個世界中都有它自己的方位。

同時,遊戲中的各種事物,無論是物理還是AI,對這些實體的訪問都具備什麼特性呢?空間連續性。我們基於資料訪問的空間連續性,我們選擇以XZ平面座標為索引。空間連續性我解釋一下,打比方說剛體物理碰撞的事物來講,一個剛體能碰撞了,能碰撞到其他剛體,很顯然是能跟他接觸的剛體。如果換作AI例子裡面呢?一個AI巡路的時候,他需要讀取的資料一定是在AI個體的視野範圍內,不可能讀地球對面另外一個實體的資料。這樣,資料訪問的連續性引導下,我們以XZ平面的矩形為基礎,進行資料的儲存。

我們把這塊區域切分成了5個矩形,這5個矩形分別存在在三個實體管理者裡面。

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


當我們去訪問藍色矩形裡的一個實體時,我們先詢問實體管理者這個實體在哪兒,完成這次訪問之後,下一次訪問極有可能還是在藍色矩形之內,我們就不需要再訪問叢集管理者。下一個訪問實地,可能超過了3號藍色矩形邊界的話,也極有可能就在他鄰居的矩形之內,我們知道邊界方向在哪邊,這也就是我們為什麼以矩形為基礎進行資料儲存的同時,記錄邊界資訊。這些操作之下,我們會大大減少對叢集管理者的訪問,也就擴充了我們分散式架構的資料容量,基本上滿足我們的需求。

這時候我們解決了資料的保管,我們還要做一些什麼事呢?首先,因為我們是基於實體的位置做保管,實體的位置會在遊戲中進行改變,我們要做一個實體在保管者之間移動,這是架構的需要。當一個實體從一個矩形移動到另外一個矩形的時候,我們需要他在實體保管者間的遷移,這需要在比較短的時間,比如說在一幀之內進行遷移,這樣不會對玩家體驗造成傷害。

我們還需要做什麼?我們要做保管者保管範圍的擴所。舉一個具體的例子,我們這邊有三個實體保管者,我們要針對1號保管者所在的物理機器做一個升級,暫時下線。我們怎麼做?

首先看1號保管者管著的兩個矩形小一點的矩形已經沒有任何實體了,非常好操作,我們可以在比較短的時間把這個小矩形劃分到2號管理者的保管範圍之內,2號保管者可能把這個矩形和自己保管的矩形合併一下。1號保管者還有一個大矩形,裡面有若干實體,實體比較多的時候,我們無法在短的時間內完成資料的遷移。

我們可以把這個矩形與我們需求內的時間片,從這個大矩形中切一片小矩形下來,持續這樣做,直到我們把1號實體保管者所有的負載遷移完畢,就可以做硬體升級了。再啟動上來,逆轉剛才的過程,把自己需要承擔的負載再承擔起來。我們做完這件事之後,就實現了這個叢集的彈性收縮,同時還有這個叢集的負載均衡。

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


這個世界被我們保管起來了,我們剩下的事就是讓這個世界動起來,建設世界執行規則。首先我們對世界執行規則進行縱向切分,比如說物理碰撞、AI、火焰和風,根據計算特性的縱向切分。然後我們針對每個切分出來的功能,每個切分出來的規則,單獨建立一個事物叢集,對實體保管者叢集裡儲存的實體資料進行讀寫。

可以看到圖中是一個大的集合,這個集合裡是若干個縱向切分出來的模擬,他們分別組成模擬器分散式叢集。

這個叢集裡,每個叢集的組成方式和之前我們說的實體保管叢集類似。我們都是透過方塊、矩形進行一個邊界的管理。這裡拿物理的模擬器舉個例子,這裡的邊界管理是和實體的儲存編輯管理有區別的。簡單來講,我們需要一個雙重邊界,一個寫邊界和讀邊界。寫邊界的操作就和實體的主動管理是一致的,就是管者把整個場景切分成若干個互不重複的矩形,交給不同的物理模擬器管理。讀邊界需要比矩形的寫邊界更加大一圈,這樣保證他們協同工作。

怎麼工作呢?舉個例子。這個區域有兩個物理模擬器協同工作,他們各負責了上下一個矩形,那麼中間的虛線是他們寫邊界的分界線,兩條實線分別是他們讀邊界的分界線。我們可以看到他們的讀邊界互相有一定的重合範圍。這時,我們在物理模擬器1所負責的場景內,靠近邊界的地方有一顆樹,是一個剛體。這個剛體對於物理1來講,物理1用了這棵樹的讀許可權和寫許可權,而物理2只擁有讀許可權。這時候一輛車開過來撞到這顆樹,碰撞發生的時候,這個車的許可權和樹相反,物理2擁有這輛車的讀寫許可權,而物理1只有讀許可權。

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


這是怎麼發生的呢?首先站在物理1的角度,物理1具有樹和車兩者的讀取許可權,換句話說,他有完整的碰撞現場。物理1可以得出一個結論,樹被撞倒,車停下來。但是物理1無法讓車停下來,只能讓樹倒下。物理2與物理1相反,物理2也知道,也有完整的碰撞現場,知道樹應該倒下,車應該停下來。但是物理2只能讓車停下來,不能讓樹倒下,那就各做各的事嘛。

簡單講,每個模擬器在自己的讀邊界內會擁有一個完整碰撞現場的資料,能夠推匯出一致的碰撞結果。同時他們做寫入操作的時候,只做寫許可權那部分的事情。這樣使我們的若干模擬器以叢集的方式在一起工作,而叢集的方式,優點我們討論過,可以實現負載平衡的,最重要的一點可以跨越不同的物理裝置。

換個例子,在AI的情況下,和物理情況會有什麼不同呢?大面上講只有一點不同,我們對於讀許可權的邊界,要比寫許可權邊界大多少?在剛體碰撞的例子裡面,讀許可權的邊界,大概只需要比寫許可權大多少的距離呢?這個距離只要略大於我們世界中最大的剛體尺寸,差不多效果不錯了。對於AI來講,多出的距離,可能會是一個實體的最大視野範圍,這可能看具體的情況,怎樣的邏輯才能順利的進行。

我們搭建這樣一個關於執行規則的模擬器叢集大結合之後,還剩下一件事,就是玩家的操作。事實上,玩家對世界的影響其實也是一種特殊規則的模擬器叢集,想象一下,和物理叢集一樣,我們創造一個接受全世界各地玩家的操作,並且處理相關事務的一個模擬器叢集。裡面每個模擬器會負載一定量的玩家連線,包括對玩家的操作,去對這個世界上的實體進行讀寫。他和其他模擬器叢集的唯一區別,就是它會讀取玩家的操作,作為自己規則模擬計算的一部分。

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


簡單分成這兩步,第一步把世界描述出來,第二步建立一個叢集把世界執行起來,這樣一個連續大世界就被我們運作出來了。我們看一下完整的架構圖,由幾個叢集構成,首先是我們建立的實體保管者分散式叢集,支援序列化、邊界管理和彈性擴縮。然後由一個大的規則模擬器叢集組成的世界規則執行的集合,這個集合首先做了一個縱向切分,然後做相關讀寫許可權管理,做了邊界讀寫控制,同時裡面每個叢集也都支援彈性擴縮。同時,在玩家行為模擬這邊,運作方式是和世界規則模擬器這邊非常類似的,唯一的區別只是它會接受玩家的操作作為自己規則計算的一部分。

按照這個架構,我們可以滿足我們之前定下來的四條標準,能夠超越單個物理裝置的運算瓶頸。我們期待在玩家可以接受的使用者體驗下,讓他們感覺到整個世界是連續的,而且這個世界可以動態擴充套件。這就是關於連續大世界的解決方案。

地球那麼大的開放世界遊戲怎麼做?騰訊雲高階架構師為開發者設計了一套方案


講一點個人的感想,我個人做遊戲十幾年,客戶端、服務端,包括製作人都做過。雲端計算時代來講,我個人最深的一點感受,集中在三個字:分散式,把我們的程式碼寫成分散式的形式,利用雲去部署我們的分散式程式碼,幫助它脫離硬體的效能,以及硬體的故障束縛。

來源:遊戲葡萄

相關文章