1. 程式人生 > >Cxihu田樹東的遊戲開發部落格

Cxihu田樹東的遊戲開發部落格

幀同步在網上可以搜的資料比較少,關於遊戲的更是沒有,不過,實現的原理也比較簡單,最近幾天就寫了份關於幀同步的文件,當作給同事掃掃盲,順便也在這裡發發,可以給其他人蔘考參考

    --競技類網路遊戲設計方案

一、        前言

 幀同步,根據wiki百科的定義是,一種對同步源進行畫素級同步顯示的處理技術,對於網路上的多個接入者,一個訊號將會通過主機同步傳送給其他人,並同步顯示在各個終端上。同步訊號可以是每幀的畫素資料,也可以是影響資料變化的關鍵事件資訊。

幀同步在網路遊戲中的應用,設計上有異於傳統的mmorpg遊戲,因為可以承載更大量的後臺計算,實現類單機的效果,所以可應用在類似射擊類、飛機類中實現彈幕計算或者格鬥類的高精度打擊體驗

本文將主要介紹下幀同步與傳統mmorpg設計框架的異同點以及相關的幾個設計方案,最後,深入展開對其中一種實現方案的分析,而相關的反外掛和斷線重連機制等技術難點暫不在本文討論。

二、        幀同步在遊戲中的應用

網路遊戲中,遊戲服務的架構大致可以分為2種模式,分別是cs模式和p2p模式

cs模式框架如圖1(c為客戶, GSS為遊戲狀態伺服器)

         


                                   圖1

圖1,遊戲狀態伺服器(GSS)單獨部署,負責對網路上各個接入者提供服務,當GSS狀態發生變化時,將狀態同步傳送給各個接收者。

p2p模式框架如圖2(c為客戶,GSS為遊戲狀態伺服器):

         



                                   圖2

圖2中,遊戲狀態伺服器存在於各個客戶主機上,遊戲狀態的改變直接來自於各個客戶端的輸入。

以上2個服務框架中,cs模式,由於GSS伺服器只有一個,遊戲狀態能保證絕對一致,但GSS可能同時服務上萬個玩家,由於機器效能以及網路頻寬等硬體資源限制,伺服器對大部分情況都無法進行非常嚴格的檢查和處理;p2p模式相對於cs模式,同時連線的玩家有限,所以可以進行比較精細的運算,可實現類似射擊類、飛機類的彈幕計算或者格鬥類的高精度打擊體驗,但是,由於端到端的通訊方式,隨著同時接入使用者的增加,通訊量呈指數級增長,所以,其對同時接入的數量上會限制得比較嚴格,適合少量同屏的競技類等遊戲。

p2p模式中,由於存在多份的GSS,如何保證各個GSS一致也需要特殊考慮,       幀同步演算法在遊戲中的應用,主要就是為了解決p2p模式下的GSS一致性問題。實現原理是將遊戲處理細化為幀,對於每幀,在同樣的執行環境中,保證同樣的輸入的情況下,將得到同樣的輸出結果。

                          

                                                     圖3

圖3中,初始狀態都為1,序列幀第二幀時,輸入加1操作,則狀態變為2,第三幀時無輸入,狀態不變,第四幀時,輸入加1操作,狀態變為3.對於同個執行環境的各個客戶端來說,相同的輸入狀況下,將得到相關的輸出結果,如圖4效果。

                  


                                                                       圖4

通常,為了使用者的輸入能及時的響應以及遊戲狀態的過度能夠平滑,會將GSS設定為20到30幀以上。並且,由於客戶端機器效能或者設定的差異,GSS的狀態無法與遊戲渲染幀實現一一對應,所以,GSS與表現層必須做到完全的分離,否則將因為某些細小的誤差被放大最終導致遊戲出現完全不同的結果。

                           


                                          圖5

圖5,非確定的渲染層的輸出,完全由GSS來驅動,GSS保證幀數的穩定,即使出現網路延遲,也必須在確保收到該幀的所有輸入後才執行該幀的處理。

實現方案上,大致可以分出3種,分別是無主機結構、有主機結構、伺服器主機結構

u  無主機結構

圖2的拓撲結構中,所有GSS功能對等,該方案需要進行特殊的對幀處理,確保所有客戶端都已經同步並且收到所有的輸入。但是,由於網路上的各個客戶端完全對等,一旦某個使用者網路狀況出現延遲或者中斷等異常,將影響其他使用者的操作體驗,所以該方案簡單公平但體驗容易受限

u  有主機結構

                                    


                                                    圖6

圖6,在各個客戶端中隨機選擇一個的GSS作為主機,同時負責對幀控制及輸入輸出管理,其他GSS僅跟GSS主機通訊,GSS之間互相不通訊。該方案的好處是,遊戲的體驗只受主機與本機的網路與本機器狀況的影響,其他GSS出現的任何故障都不會影響其他人,當GSS主機完全失去聯絡時,其他GSS也可以重新仲裁得出新的GSS主機來,但該結構主機在客戶端,容易給外掛有可乘之機,對輸入對幀等能進行特殊處理,最終導致遊戲喪失公平性。此方案能保證玩家體驗,但安全性較低

u  伺服器主機結構

伺服器主機結構,是將圖6的結構中的GSS主機的的對幀控制及輸入輸出管理功能放在伺服器上,降低GSS客戶端的客觀影響,保證了大部分玩家的體驗,且其中有玩家作弊,也能馬上檢測到,保證遊戲的公平性,但結構上已脫離p2p設計,通訊流量隨使用者增加,負額指數級增長。該方案安全性高,保證玩家體驗,但對服務負載有一定的要求。

u  其他

融合有/無主機與伺服器主機的結構。伺服器主機結構的特點在於控制權在服務端,在有狀態的網路遊戲中,可以有效防止遊戲資料修改、遊戲加速等外掛,在服務端硬體資源方面,可以增加有/無主機結構減輕負擔,大部分功能用有/無主機結構處理,關鍵操作由伺服器主機結構處理等,讓GSS主機與伺服器主機協同服務

三、        伺服器主機結構設計

伺服器主機結構的特點如上所述,這裡再深入展開對該結構的分析與設計。

         伺服器設計

         


                                                             圖7

伺服器主要是起到控制作用,進行客戶端的對幀控制和輸入輸出管理。如圖7,伺服器每幀都發驅動幀驅動客戶端執行幀處理,當客戶端有輸入被伺服器接收到,則伺服器當前幀內將輸入同步輸出給各個客戶端.

網路上由於客戶端的狀況多種多樣,客戶端幀數可能跟不上伺服器,如圖8所示,如果客戶端出現掉幀情況,則在收到驅動幀後需要加速執行,以追上其他客戶端的速度,避免掉幀的使用者一直在對過去的事件進行響應。

遊戲應該優先保證正常使用者的體驗,所以當有玩家出現卡幀情況的時候,不應選擇暫停其他玩家,而是讓他慢慢的追趕上來,設計上,伺服器即可以採用客戶端的正常速度,按幀驅動客戶端,但當網路都出現突發狀況的時候,如圖9,通訊異常時,2個客戶端都對幀數2缺失,如果伺服器照常執行,到恢復網路狀況時,會出現情況是,每個客戶端都卡了幾幀之後,加速拉了幾幀。所以,針對這種情況,增加客戶端的對幀操作,即客戶端執行第1幀時,跟伺服器說可以播放第二幀了,然後伺服器開始驅動第二幀動作,考慮網路延遲情況,可以提前對幀第n幀的,效果如圖9,左邊客戶端第二個對幀操作使伺服器開始推動第二幀進行,而右邊客戶端的第二個對幀動作其實不起任何作用

                          


                                                                       圖8

                          


                                                                      圖9

虛擬碼

 程式碼不貼了

客戶端設計

                          


                                                             圖10

客戶端設計由兩部分組成,分別是GSS模組和渲染模組。

GSS模組包含物品系統、角色系統、AI系統、場景系統還有其他相關係統等,同時,輸入輸出和幀數控制也一起整合在GSS模組中。GSS中各系統功能分別是:

         物品系統:       遊戲物品以及物品的效果

         角色系統:       角色包括玩家角色、npc及apc等

         ai系統:          驅動apc行動的控制模組

         場景系統:     場景物件、地圖、尋路等

         其他系統:      其他類似技能、狀態等系統

         輸入輸出模組:       監聽玩家輸入,將玩家輸入上報伺服器,同時監聽伺服器輸入,綁定當前幀輸出

         幀數控制模組:      監聽伺服器驅動幀,驅動執行每幀處理

GSS模組中各個系統的執行,由幀數驅動,不引入其他時間線。有如物品持續時間、狀態持續時間等都以幀數作為唯一的時間軸。幀與幀之間的播放頻率,則由伺服器統一控制,但由於網路抖動等影響,幀的頻率並不是太穩定,為避免播放抖動,幀數控制器需要進行一定的平滑處理。

                  


                                                     圖11

客戶端的渲染層,由GSS模組驅動,為減少模組間的耦合,GSS模組使用事件通知機制驅動渲染層表現。具體細分事件型別如圖12(具體專案具體事件拆解)

由於渲染層與GSS只做到事務級的同步,而GSS與渲染層的播放速率有可能不同,則為保證較好的表現效果,GSS的邏輯幀需要與渲染層的渲染幀做固定比率的繫結,譬如圖13的1:2,當GSS邏輯幀數不變的情況下,渲染幀掉幀時,能經過換算得到當前邏輯幀對應的渲染幀數,出現GSS幀數暫停時,則邏輯幀也跟著一起暫停

                  


                                                             圖13

邏輯幀與渲染幀繫結演算法(虛擬碼)

         程式碼不貼了

其中  OnUpdate由引擎在每幀呼叫,GetNewestFrame獲得邏輯幀通知過來的最新幀,這樣,保證了邏輯幀中關鍵幀進行傷害計算時,渲染幀不會脫幀嚴重。

四、        反外掛與斷線重連

         稍等後續文章

對於一個遊戲來講,戰鬥就是靈魂,如果戰鬥做不到極致,其他方面做的再好也是徒勞,這幾年,也參與了很多遊戲的開發,其中有很多遊戲是從決策到死掉全程參與,深有感慨。從端游到頁遊 從頁遊再到手遊 每一個新市場機會出現的時候,都是從閉著眼睛就能賺錢到大部分賺不到錢過度,對遊戲的開發技術都要求也是越來越高,只不過每個市場到成熟的時間都被大大縮短了。對於戰鬥來講很多都是策劃腦補的跟實際做出來的完全不是一回事,很多原因都是戰鬥方案選型就是錯誤的。

  從程式角度來講,我把戰鬥從兩個維度分類:

  1、從操作方式上分為回合操作、即時操作。

  2、從互動方式上分為 離線戰鬥 聯網戰鬥,這個地方需要說明一下,有些遊戲雖然也能進攻別人,例如COC 但是因為戰鬥的時候,另外一個人是不可以操作的,類似於這樣的戰鬥也可以稱為離線戰鬥。

  基本上所有的戰鬥都是以上兩種方式在某種程度的組合而已,例如夢幻西遊可以認為是聯網戰鬥、回合操作型別。

  最近比較火的全民超神,王者榮耀,屬於 (聯網戰鬥|離線戰鬥)即時操作型別。

  最新網易出的功夫熊貓 屬於 (聯網戰鬥|離線戰鬥)即時操作型別,相對於dota類的全民超神、王者榮耀,他對延遲要求的更高了。

  如果在立項初期,專案計劃時候不確定遊戲的操作型別,以及網路要求,做得後期要想調整的話,改動是致命的,假設按照之前時空獵人的方式實現的純離線戰鬥及時遊戲,最多也只能做做離線PVP,如果想增加聯網PVP的功能的話,對於程式來講幾乎需要重寫戰鬥。

  隨著移動遊戲市場越來越成熟,對於戰鬥的要求也在提高,原來做一款ARPG,只有單機玩法就足夠了,不需要開發實時PVP,但是現在市面上的ARPG不僅可以聯網PVP,甚至可以聯網組隊PVE了,所以我感覺如果現在再去做遊戲的話,只是一個單機玩法,或者是離線PVP玩法已經遠遠不能滿足現代玩家的口味了。

  我認為現在戰鬥系統需要滿足一下幾點。

  1、一定要有離線PVE玩法,或者離線PVP玩法,可以在讓玩家在網路不好的時候消遣,節省流量。(全民超神、王者榮耀在5V5匹配時候都有一定機率匹配到離線戰鬥,這個時候是不耗流量的,其他人全是AI控制的)

  2、一定要有線上PVP,線上PVE,能夠讓玩家在網路比較好的時候,實時競技。增加可玩性。

  3、戰鬥中,盡最大程度節省玩家的流量,例如全民超神這款遊戲,一場30分鐘的戰鬥基本上要消耗掉20M的流量,而且此類遊戲大部分是玩的聯網戰鬥,基本上在非wifi情況下沒法玩。

  4、需要有戰鬥回放機制,可以讓策劃設計離線玩法的時候更自由,例如COC,戰鬥回放基本變成了它遊戲的一部分。

  5、防作弊,如果有離線玩法的話,一定有機制對離線玩法的結果進行驗證,要不然等你遊戲真火了,你就知道錯了。

  6、實現難度相對較低。

  對於聯網遊戲來講,同步的方式主要分為兩種,狀態同步、幀同步。

  1、狀態同步:顧名思義,是指的將其他玩家的狀態行為同步的方式,一幫情況下AI邏輯,技能邏輯,戰鬥計算都由伺服器運算,只是將運算的結果同步給客戶端,客戶端只需要接受伺服器傳過來的狀態變化,然後更新自己本地的動作狀態、Buff狀態,位置等就可以了,但是為了給玩家好的體驗,減少同步的資料量,客戶端也會做很多的本地運算,減少伺服器同步的頻率以及資料量。

  2、 幀同步:RTS遊戲常採用的一種同步技術 ,上一種狀態同步方式資料量會隨著需要同步的單位數量增長,對於RTS遊戲來講動不動就是幾百個的單位可以被操作,如果這些都需要同步的話,資料量是不能被接受的,所以幀同步不同步狀態,只同步操作,每個客戶端接受到操作以後,通過運算可以達到一致的狀態(通過隨機種子保證所有客戶端隨機序列一致),這樣的情況下就算單位再多,他的同步量也不會隨之增加。

  下面我們從以上的5個方面對各自實現方式進行描述:


  總結一下:

  1、對於回合制戰鬥來講,其實選用哪種方式實現不是特別重要了,因為本身實現難度不是很高,採用狀態同步也能實現離線戰鬥驗證。所以採用幀同步的必要性不是很大。

  2、對於單位比較多的RTS遊戲一定是幀同步,對於COC來講,他雖然是離線遊戲,但是他在一樣輸入的情況下是能得到一樣結果的,所以也可以認為他是用幀同步方式實現的戰鬥系統。

  3、對於對操作要求比較高的,例如MOBA類遊戲有碰撞(玩家、怪物可以互相卡位)、物理邏輯,純物理類即時可玩休閒遊戲,幀同步實現起來比較順暢,(有開源的Dphysics 2D物理系統可用 它是Determisti的)。

  4、對於戰鬥時大地圖MMORPG的,一個地圖內會有成千上百的玩家,不是小房間性質的遊戲,只能使用狀態同步,只同步自己視野的狀態。    

  5、幀同步有個缺點,不能避免玩家採用作弊工具開圖。