大型多人在線遊戲的開發中,如何做到每個玩家動作的實時同步的?

譬如魔獸世界,眾多玩家的在線行為同步是如何做到的?


對於不同類型的遊戲有不同的網路同步方案。

對於動畫和gameplay相關非常大的情況,比如FPS遊戲,需要同步的就是位置和旋轉,還有就是玩家狀態,比如死亡,當前拿著的武器等,動作通常由狀態和事件推算出來,比如速度和朝向一致就播放向前走的動畫,死亡就播放死亡動畫。

對於動畫對於gameplay沒那麼重要的,比如MMO,通常動畫是由技能或者法術系統來驅動。這裡需要同步的各種技能或者法術施放的事件。

對於動畫對於gameplay至關重要的情況,比如格鬥遊戲(火影手游),就要採用更為嚴格的同步策略,需要保證在每個客戶端上運行的結果是一致的,包括Blend和transition,這類遊戲大部分採用了一種叫做幀同步的策略。

對於不同的遊戲需要綜合考慮gameplay,網路帶寬,防作弊等因素來選用不同的同步方案,或者混合使用。

一些有用的鏈接

Source Multiplayer Networking

Game Networking Techniques, Explained with Pong

What is the best way to send an animation over a network?

Fast-Paced Multiplayer (Part I): Introduction


謝邀。

某客戶端產生輸入,本地計算角色即將進入的狀態。如果有客戶端預測,可能本地先執行。新狀態發送給伺服器,伺服器接受後根據玩家角色所處情況判斷該狀態是否能夠執行,能夠則同步給其他客戶端,不能則駁回。此時如果客戶端有預測,接到駁回消息可以:

1、無視,看到結果是做了動作沒有實際效果;

2、回滾,看到結果是動作做了一半跳回了原來狀態;

c/s結構的大體這樣。根據遊戲類型有很多,比如lobby base的,完全p2p的又是另外的方案了。

另外實現細節也很多,並沒有上述這麼簡單。


蟹妖

客戶端發消息給伺服器,伺服器再將消息同步給所有需要同步的客戶端,客戶端調用本地資源,讓玩家看見同步的圖像。大概就是這樣。


之前看過一篇講wow伺服器架構分析的文章,大概說說我對多人聯機遊戲技術實現的理解。

多人聯機網路通訊方式主要是兩種,一種是p2p,點對點傳輸。這種類似於打區域網聯機的遊戲,不需要一個伺服器,每個客戶端負責自身的數據,通過網路把自己的數據發給其他客戶端。這麼做容易作弊,因為數據是在各自客戶端的內存里的。如果被修改,其他客戶端是不知道的,所以通常只會存在於主機遊戲中。例如最近很火的馬里奧賽車8,怪物獵人xx等等。

另一種自然是伺服器和客戶端交互。

最早網遊也是把數據放在本機,伺服器只負責路由數據。後來發現外掛太多,而且沒法預防,所以改成數據放在伺服器上,客戶端只能負責傳輸操作指令。所有上傳的指令都需要伺服器進行一次check,合法指令才會被執行,然後返回操作結果。但這樣也有問題,如果返回結果數據量過大,對網路壓力很大,造成延遲高。

所以現在通常做法是,客戶端計算一次操作結果,發給伺服器端校驗,伺服器也會進行同樣的操作,把操作結果與客戶端做對比。一致也保留客戶端操作,不一致退回操作。

客戶端鏈接上伺服器後,會保持一個長鏈接,維持一個心跳。這樣保證了數據可以及時同步更新。但通常,像mmo這樣的遊戲,玩家可見範圍是有限的。所以客戶端會把玩家坐標發給伺服器,伺服器再根據坐標計算可見範圍,把可見範圍內的數據發給客戶端。

網路通訊中所有數據都是加密且帶有時間戳的,增加安全性。

沒有參與過優化,所以只能說說大概設計思路。對於格鬥遊戲,moba遊戲這種對延遲要求極高的遊戲,應該還會需要很多優化。需要各位大神補充。


大型MMO這類遊戲,暫時是沒辦法做到每個玩家動作實時同步的,伺服器能力有限,所以用的C/S狀態同步,同步的是某個範圍內的狀態,你看到的別人都是延遲,並且是某個狀態下的近似表現,你看到別人做了個詭異動作,他50%肯定沒做過!

多人競技如Moba、FTG,是可以做到每個玩家動作實時同步,用的Lockstep,同步的是操作,你看到別人做了個詭異動作,他百分百做過!做了可能是動畫BUG,沒做一定是同步BUG!

而且大型MMO裡面,這麼多人同步也是分情況分策略的

  1. 非核心Gameplay,比如大部分人類在UI上的莫名舉動,抽個概率0.000001的寶箱什麼的:),這種大部分情況下都不用同步
  2. 核心Gameplay,這些包括移動,戰鬥,換裝備等所有遊戲場景中的活動。伺服器首先沒法做到一個伺服器一個人動,就同步給所有玩家,同時客戶端也沒辦法一個場景中顯示所有玩家(3K,30K?),所以一個角色狀態變化,伺服器只會通知場景中一定範圍內的玩家。這裡還涉及到延遲如何處理,狀態有差距,該選用什麼策略,平滑還是修正?所以服務一般都會對某類客戶端上報的狀態數據有一定容忍
  3. 多人副本,這種人數不多的情況下,甚至可以考慮Lockstep,融合C/S狀態同步,只為了更好的戰鬥體驗,當然客戶端伺服器的複雜度也因為要兼容兩套同步方案而變得複雜

網路遊戲狀態同步一般分為三種

  1. Lockstep(幀同步)
  2. Snapshot synchronization(快照同步)
  3. State synchronization(狀態同步)

結論是,大部分多人在線遊戲都實用的最後一種狀態同步。

幀同步

在遊戲的每個幀同步用戶事件,經伺服器廣播之後,在每個客戶端模擬狀態變更

由於只同步用戶事件,所以網路傳輸的數據塊比較小,同步又比較及時,非常適合格鬥遊戲這種需要做精確模擬的遊戲。而且由於只同步事件而非狀態,所以網路傳輸的數據和遊戲里的對象數量無關,比較適合於包含較多遊戲單位的遊戲,比如及時策略遊戲。

對於單個用戶,由於網路傳輸往往不穩定,往往影響模擬的穩定,從而導致渲染時的跳動(jitter)。為了處理這個問題,往往會引入事件的buffer來平滑網路傳輸。但是這又影響了模擬的及時性。而且由於不存在狀態,所以對於需要斷線重連時,往往由於客戶端需要重新完成之前所有模擬,所以重連時間較長。

對於多個用戶,由於為了保證所有人同步,往往需要等待最慢的客戶端,從而使整個遊戲非常容易受到單個用戶的網路延遲的影響。而且只同步事件,往往比較難以防範欺詐。

當然最麻煩的問題還是要保證客戶端模擬的一致性,於是這個模式有時候又叫 Deterministic Lockstep。包括使用一樣的隨機種子所偽隨機運算,不使用浮點數運算等。

通常使用這種策略的都是區域網遊戲。

帝國時代,王者榮耀,還有知名的DOOM,都用的是這種策略。

快照同步

這是在C/S模式中最簡單的同步策略。客戶端將事件發送給服務端,服務端完成模擬之後定期將所有狀態的快照同步給客戶端。

由於所有的模擬都在服務端,這種策略最容易用於防止欺騙。而且在這種模式下,所有的客戶端都可以看做是伺服器狀態的一個 terminal,所以實現起來也最容易。最好的一方面就是不受到單個用戶的網路抖動的影響,但是網路比較快的用戶往往就有比較大的優勢。

由於要同步所有遊戲對象的狀態,所以網路傳輸的數據包往往較大,無法實現比較實時的同步。為了應對數據包過大,往往會要求使用一些壓縮的編碼方法,比如 Delta Encoding。為了應對不及時,就需要對snapshot進行 Interpolation 和 Extrapolation。差值時為了保證遊戲中運動平滑,會使用比較複雜的差值演算法,但是往往還是往往容易顯得不自然。

通常使用這種策略的都是遊戲狀態比較小,對實時性要求不高的遊戲。

不少基於HTTP協議的遊戲,都是採用這種策略。

狀態同步

這個是最容易想到也最難實現的策略。客戶端和服務端都模擬狀態變更,客戶端將事件發送給伺服器後,在本地預測狀態變更。伺服器受到狀態後,在伺服器上也做同樣的模擬,然後將變化的狀態傳回給客戶端。對於沒有變化的對象,客戶端保持原有狀態(運動或者靜止),對於變化了的對象,客戶端以伺服器的返回為準。由於伺服器的狀態返回往往有延遲,所以客戶端會在收到新狀態之後,重放同步點之後的事件。

好處就是,無論是傳遞的數據內容、大小,還是同步的頻率都是可以調整的,所以可以在模擬的精細和模擬的效率之間找到一個較好的平衡,而且由於在客戶端也進行模擬,往往用戶收到的反饋也更及時,體驗也更好。

不過由於要將伺服器端和客戶端運行一樣的模擬,所以也存在雙端同步的問題。

最後,其實以上協議,只是讓玩家的狀態實現同步。而影響實時性的最大關鍵在於網路,所以為了接近實時,需要盡量降低網路延遲,包括降低傳輸數據量,使用UDP來避免TCP的重傳問題等。此外為了而讓玩家的動作感覺起來像是實時同步,往往要靠本地的Extrapolation。


推薦閱讀:

最近感覺玩遊戲越來越沒有意思了,有什麼好玩的遊戲推薦一下嗎?網遊、單機、手游都可以
有什麼高品質的頁游?
如何評價《絕地求生:大逃殺》玩家網吧開掛被打的事件?
有哪些遊戲的「死亡懲罰」設計得十分巧妙?
《暗黑破壞神 3》煉獄中有哪些遊戲體驗?

TAG:網路遊戲 | 遊戲設計 | 遊戲開發 |