王者榮耀聊聊游戲的幀同步

      網友投稿 1048 2022-05-29

      這是王者榮耀技術分析系列第二篇,有興趣請持續關注我的blog和公眾號。

      1、像《王者榮耀》一樣紅過

      2、從《王者榮耀》來聊聊游戲的幀同步

      3、游戲服務器的架構演進

      農藥自從上線以來,依靠著強大的產品力以及騰訊的運營能力,在游戲市場上表現可謂是風生水起,根據第三方的調研數據顯示,《王者榮耀》滲透率達到22.3%,用戶規模達到2.01億人,每日的日活躍用戶(DAU)均值為5412.8萬人。 如此可觀的數據,令人十分欽佩。

      當然了,作為技術人,更愿意從技術上了解去一些王者榮耀的實現原理和架構方式,從中找到新的知識領域,擴展自己的知識邊界,豐富自己的專業技能。借助這個游戲,這一篇我們來聊一聊王者榮耀的技術實現以及同步方式,更多的從MOBA(多人在線戰術競爭游戲)方向來解析推理王者的實現方案,如若有分析的不盡的方向,歡迎一起探討改進。以下是主要講解的幾個重點:

      服務器架構

      通信方式

      從王者榮耀聊聊游戲的幀同步

      同步方案

      技能同步

      斷線重連

      一、服務器架構

      不難發現,王者榮耀的服務器采用房間模式,每個玩家登陸以后,然后進入大廳,進行匹配游戲。匹配完成之后,把一起對戰的玩家放到一個房間內進行對戰。

      房間類玩法和MMORPG有很大的不同,在于其在線廣播單元的不確定性和廣播數量很小,而且需要匹配一臺房間服務器讓少數人進入一個服務器。

      這一類游戲最重要的是其“游戲大廳”的承載量,每個“游戲房間”受邏輯所限,需要維持和廣播的玩家數據是有限的,但是“游戲大廳”需要維持相當高的在線用戶數,所以一般來說,這種游戲還是需要做“分服”的。而“游戲大廳”里面最有挑戰性的任務,就是“自動匹配”玩家進入一個“游戲房間”,這需要對所有在線玩家做搜索和過濾,以及為了更好的體驗,會對玩家進行分地區進行匹配,以方便獲得更快速的同步。

      一般的方式是玩家先登錄“大廳服務器”,然后選擇組隊游戲的功能,服務器會通知參與的所有游戲客戶端,新開一條連接到房間服務器上,這樣所有參與的用戶就能在房間服務器里進行游戲交互了。

      二、通信方式

      說到通信方式,一般會有http和socket 兩種方式,但http底層也是采用socket,只是每次通信完成以后都會斷開,這種方式對于需要頻繁交互的雙方來說,顯得效率太低了,所以一般實時要求高的游戲都是采用socket方式來通信。

      可是sokect通信,又分為兩種:TCP vs UDP,具體是采用那種socket類型,需要具體來看游戲游戲類型。以下是兩種類型的優劣:

      從上面的對比中,我們可以會發現,關于socket,我們想做的事情,tcp都幫我們做了,我們只需要建立鏈接,然后像讀寫文件一樣讀寫就可以了。而udp需要我們自己設計一切。看到這一切,你可能第一感覺就是采用tcp而非udp,那么真實情況是如此么?基于游戲的業務以及場景不同,我可以明確的告訴你,王者榮耀是采用udp的,包括騰訊多數長鏈接手游都是采用udp,這是為何?

      1、tcp保證數據可靠性是有代價的

      tcp能夠保證數據包的可靠性和有序,這一切都幫你封裝好了。TCP發送一個數據包,等待一段時間,直到檢測到數據包丟失了,如果沒有接收到它的ACK,接下來就重新發送丟失的數據包到目標計算機。重復的數據包將被丟棄在接收端,亂序的數據包將被重新排序。以此來保證數據包的可靠性和有序性。

      但為了保證可靠和有序,就要保證TCP無論什么情況,只要數據包出錯,就必須等待數據包的重發。這是什么意思吶,就是說,即使最新的數據已經到達,但還是不能訪問這些數據包,新到的數據會被放在一個隊列中,需要等待丟失的包重新發過來之后,所有數據沒有丟失才可以訪問。

      如此,如果遇到網絡環境太差或者不穩定,比如說國內的移動網絡,或者是遭遇到了網絡阻塞,出現一個數據包丟失,所有事情都需要停下來等待這個數據包重發。客戶端會出現等待接收數據,玩家操作會出現卡頓以及響應不及時的現象。

      2、udp的可靠性—DIY手動組裝

      從上面我們可以知道udp主要在可靠性上主要是不能保證數據包的順序,比如第100個收到的數據包并不一定是第100個發出的數據包,同時也無法保證不丟包,期間有一個包丟失,udp本是也不會去校檢。如果這兩個問題解決了,udp的大部分可靠性問題也就解決了。

      具體的方案我們這一篇就不在細說,大體上是如此來解決:

      1、為每個數據包增加序列號,每發一次包,增加本地序號。

      2、每個數據包增加一段位域,用來容納多個確認符。確認字符多少個,跟進應用的發包速率來覺得,速率越高,確認字符的數量也相應越多。

      3、每次收到包,把收到的包上序列號變為確認字符,發送包的時候帶上這些確認字符。

      4、如果從確認字符里面發現某個數據包有丟失,把它留給應用程序來編寫一個包含丟失數據的新的數據包,必要的話,這個包還會用一個新的序列號發送。

      5、針對多次收到同一包的時候可以放棄它

      三、同步方案

      游戲中常見的同步方案,有狀態同步和幀同步,一般大型的MMOARPG都是采用的是狀態同步,比如魔獸世界,狀態同步采用C/S架構,所有的狀態由服務器來控制,安全性比較高,但是流量比較大。幀同步采用的是囚徒模式,所有c端強制采用一個邏輯幀率,從而保證輸出一致,其特點是流量小,安全性比較差。

      王者榮耀采用的就是幀同步,那么具體幀同步是什么,如何實現的,我們從兩個地方來分解:

      1、幀率

      什么是幀率,可能沒有做過client同學并不是很清楚這個術語,我們從一個小李子來講解一下。我記得小時候有一種小人書,快速翻看就可以看到漫畫上的人物會動起來。如下面這種:

      超過1M上傳不刪了,我也無奈

      由于人類眼睛的特殊生理結構,如果所看畫面之幀率高于每秒約10-12幀的時候,就會認為是連貫的, 此現象稱之為視覺暫留。這也就是為什么電影膠片是一格一格拍攝出來,然后快速播放的,就像上圖快速翻小人書一樣。

      游戲中的所有動畫也是采用這種方式來渲染,只不過幀率是有GPU來控制,你所看到的畫面都是有都是有GPU一幀幀渲染的,比如30幀/s,你所看到的畫面就比較流暢了。而幀率越高你所看到的越流暢。

      2、Lockstep—幀同步

      幀同步可以說是通過幀率延伸過來的,你可以把一個游戲看成一個巨大的狀態機,所有的參與者都采用同一個邏輯幀率來不斷的向前推進。

      我們看如下2個圖:

      圖中是A、B、C三個玩家的時間軸,這個時間軸不是電腦上的本地時間,而是A、B、C聯機時定義的一個時間軸。虛線分隔出來時間片稱為turn,可以理解成一幀。箭頭表示該玩家將自己的操作指令廣播給其他玩家。

      我們把一盤游戲看成一個大型的狀態機,因為大家玩的是同一款的游戲,因此F是相同的,初始狀態S0也是相同的。在第一個turn結束時,所有玩家都接收到了完全一樣的輸入I,注意這里的I不是一個值,而是包含了當前游戲中所有玩家的操作指令集合。t1時刻所有玩家的電腦自行計算結果。由于F、S0和I是固定的,所以每個玩家電腦上計算出的下一個狀態S1一定是相同的。

      所以通過上面我們可以知道:

      1、我們把游戲的前進分為一幀幀,這里的幀和游戲的渲染幀率并不是一個,只是借鑒了幀的概念,自定義的幀,我們稱為turn。游戲的過程就是每一個turn不斷向前推進,每一個玩家的turn推進速度一致。

      2、每一幀只有當服務器集齊了所有玩家的操作指令,也就是輸入確定了之后,才可以進行計算,進入下一個turn,否則就要等待最慢的玩家。之后再廣播給所有的玩家。如此才能保證幀一致。

      3、Lockstep的游戲是嚴格按照turn向前推進的,如果有人延遲比較高,其他玩家必須等待該玩家跟上之后再繼續計算,不存在某個玩家領先或落后其他玩家若干個turn的情況。使用Lockstep同步機制的游戲中,每個玩家的延遲都等于延遲最高的那個人。

      4、由于大家的turn一致,以及輸入固定,所以每一步所有客戶端的計算結果都一致的。

      我們來看看具體的執行流程:

      上圖中我們可以明顯看到,這種囚徒模式的幀同步,在第二幀的時候,因為玩家1有延遲,而導致第二幀的同步時間發生延遲,從而導致所有玩家都在等待,出現卡頓現象。

      四、樂觀鎖&斷線重連

      囚徒模式的幀同步,有一個致命的缺陷就是,若聯網的玩家有一個網速慢了,勢必會影響其他玩家的體驗,因為服務器要等待所有輸入達到之后再同步到所有的c端。另外如果中途有人掉線了,游戲就會無法繼續或者掉線玩家無法重連,因為在嚴格的幀同步的情況下,中途加入游戲是從技術上來講是非常困難的。因為你重新進來之后,你的初始狀態和大家不一致,而且你的狀態信息都是丟失狀態的,比如,你的等級,隨機種子,角色的屬性信息等。 比如玩過早期的冰封王座都知道,一旦掉線基本這局就廢了,需要重開,至于為何沒有卡頓的現象,因為那時都是解決方案都是采用局域網的方式,所以基本是沒有延遲問題的。

      后期為了解決這個問題,如今包括王者榮耀,服務器會保存玩家當場游戲的游戲指令以及狀態信息,在玩家斷線重連的時候,能夠恢復到斷線前的狀態。不過這個還是無法解決幀同步的問題,因為嚴格的幀同步,是要等到所有玩家都輸入之后,再去通知廣播client更新,如果A服務器一直沒有輸入同步過來,大家是要等著的,那么如何解決這個問題?

      采用“定時不等待”的樂觀方式在每次Interval時鐘發生時固定將操作廣播給所有用戶,不依賴具體每個玩家是否有操作更新。如此幀率的時鐘在由服務器控制,當客戶端有操作的時候及時的發送服務器,然后服務端每秒鐘20-50次向所有客戶端發送更新消息。如下圖:

      上圖中,我們看到服務器不會再等到搜集完所有用戶輸入再進行下一幀,而是按照固定頻率來同步玩家的輸入信息到每一個c端,如果有玩家網絡延遲,服務器的幀步進是不會等待的,比如上圖中,在第二幀的時候,玩家A的網速慢,那么他這個時候,會被網速快的玩家給秒了(其他游戲也差不多)。但是網速慢的玩家不會卡到快的玩家,只會感覺自己操作延遲而已。

      五、技能同步

      游戲中有很多是和概率相關的,比如說技能的傷害有一定概率的暴擊傷害或者折光被擊等。按照幀同步的話,基于相同的輸入,每個玩家的client都是獨立計算傷害的,那么如何保證所有電腦的暴擊傷害一致那。這個時候就需要用到偽隨機了。

      大部分編程語言內置庫里的隨機數都是利用線性同余發生器產生的,如果不指定隨機種子(Random Seed),默認以當前系統時間戳作為隨機種子。一旦指定了隨機種子,那么產生的隨機數序列就是確定的。就是說兩臺電腦采用相同的隨機種子,第N次隨機的結果是一致的。

      所以在游戲開始前,服務器為每個玩家分配一個隨機種子,然后同步給client,如此每個client在計算每個角色的技能時候,就能保證傷害是一致的。這也是多數幀同步游戲采用的方案,包括王者榮耀。

      5G游戲 UDP

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:內存數據庫究竟是如何發揮內存優勢的?
      下一篇:十二大云安全威脅
      相關文章
      亚洲国产综合无码一区二区二三区 | 亚洲女人被黑人巨大进入| 激情内射亚洲一区二区三区爱妻| 久久亚洲美女精品国产精品| 亚洲国产精华液网站w| 亚洲精品无码永久在线观看你懂的| 国产日产亚洲系列最新| 在线A亚洲老鸭窝天堂| 中文字幕亚洲无线码a| 亚洲无线码在线一区观看| 国产亚洲精品资在线| 亚洲中文字幕无码爆乳AV| 亚洲中文字幕久久精品无码APP| 亚洲精品乱码久久久久久蜜桃不卡| 亚洲男人的天堂www| 久久精品国产亚洲AV果冻传媒| 亚洲国产精品婷婷久久| 久久丫精品国产亚洲av| 亚洲沟沟美女亚洲沟沟| 亚洲国产成AV人天堂无码| 99久久婷婷国产综合亚洲| 亚洲七久久之综合七久久| 亚洲一区二区无码偷拍| 久久亚洲中文无码咪咪爱| 亚洲国产精品成人| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 亚洲精品国产自在久久| 久久久久久久亚洲精品| 亚洲男人的天堂www| 亚洲欧洲日韩国产综合在线二区| 久久亚洲精精品中文字幕| 亚洲国语在线视频手机在线| 亚洲五月丁香综合视频| 亚洲精品无码你懂的| 亚洲成A人片在线观看无码3D| 亚洲av再在线观看 | 亚洲日本视频在线观看| 中国亚洲呦女专区| 久久亚洲精品11p| 亚洲五月午夜免费在线视频| 亚洲AV成人精品网站在线播放 |