地球那么大的开放世界游戏怎么做?腾讯云高级架构师为开发者设计了一套方案
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來講,多出的距離,可能會是一個實體的最大視野范圍,這可能看具體的情況,怎樣的邏輯才能順利的進行。
我們搭建這樣一個關于運行規則的模擬器集群大結合之后,還剩下一件事,就是玩家的操作。事實上,玩家對世界的影響其實也是一種特殊規則的模擬器集群,想象一下,和物理集群一樣,我們創造一個接受全世界各地玩家的操作,并且處理相關事務的一個模擬器集群。里面每個模擬器會負載一定量的玩家連接,包括對玩家的操作,去對這個世界上的實體進行讀寫。他和其他模擬器集群的唯一區別,就是它會讀取玩家的操作,作為自己規則模擬計算的一部分。
?
簡單分成這兩步,第一步把世界描述出來,第二步建立一個集群把世界運行起來,這樣一個連續大世界就被我們運作出來了。我們看一下完整的架構圖,由幾個集群構成,首先是我們創建的實體保管者分布式集群,支持序列化、邊界管理和彈性擴縮。然后由一個大的規則模擬器集群組成的世界規則運行的集合,這個集合首先做了一個縱向切分,然后做相關讀寫權限管理,做了邊界讀寫控制,同時里面每個集群也都支持彈性擴縮。同時,在玩家行為模擬這邊,運作方式是和世界規則模擬器這邊非常類似的,唯一的區別只是它會接受玩家的操作作為自己規則計算的一部分。
按照這個架構,我們可以滿足我們之前定下來的四條標準,能夠超越單個物理設備的運算瓶頸。我們期待在玩家可以接受的用戶體驗下,讓他們感覺到整個世界是連續的,而且這個世界可以動態擴展。這就是關于連續大世界的解決方案。
?
講一點個人的感想,我個人做游戲十幾年,客戶端、服務端,包括制作人都做過。云計算時代來講,我個人最深的一點感受,集中在三個字:分布式,把我們的代碼寫成分布式的形式,利用云去部署我們的分布式代碼,幫助它脫離硬件的性能,以及硬件的故障束縛。
總結
以上是生活随笔為你收集整理的地球那么大的开放世界游戏怎么做?腾讯云高级架构师为开发者设计了一套方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 平台游戏中走与跳的实现
- 下一篇: 面向对象的程序设计在游戏开发中使用(一)