Unite 2017 | 從《鬧鬧天宮》看MOBA遊戲裏的網絡同步技術

http://mp.weixin.qq.com/s/0v0EU79Q6rFafrh8ptlmhw
html


在Unite 2017 Shanghai案例分享專場,來自藍港互動《鬧鬧天宮》項目組的主程序陳實爲你們分享了MOBA遊戲裏的網絡同步技術,總結了使用Unity開發MOBA類型遊戲在網絡同步上可能遇到的問題,以及如何規避這些問題的寶貴經驗。本文就爲你們帶來這次分享的技術要點。
數組




MOBA類遊戲的網絡同步有三大特色,也能夠理解爲MOBA遊戲對網絡同步的三大要求,即實時性、流暢性以及遊戲公平性。知足這些網絡同步要求經常使用的技術方案有兩種:狀態同步與幀同步。下面就分別針對這兩種經常使用方案及其對應的實際案例,來分析兩種方案對於各類網絡環境的表現。並着重分享《鬧鬧天宮》項目選用幀同步方案進行開發的過程當中,所遇到的一些難點與挑戰。安全


下面附上本次主題分享的現場視頻:服務器



狀態同步網絡

狀態同步,即同步玩家的狀態信息,例如位置、屬性以及其它玩法相關數據等。一般在此種方案下,遊戲主邏輯會放在服務端進行計算,客戶端僅用做顯示。而通訊須要的網絡流量大小,取決於玩法設計中須要同步的實體數量。
數據結構



狀態同步結構圖架構


對於像《星際爭霸》這類RTS遊戲來講,這種同步方案就不太適用,由於玩家能夠操做的小兵數量可能上百個,狀態同步會佔用大量流量。狀態同步須要客戶端接收玩家輸入後,上傳到服務端進行數據處理,而後將狀態信息傳回客戶端進行展現。函數


幀同步性能

幀同步僅同步玩家指令,不一樣步狀態,遊戲邏輯一般會在客戶端分別計算。網絡流量大小取決於指令大小以及同步幀率。像《星際爭霸》這類遊戲即便須要同步的單位增長到兩三百,所需的網絡流量也不會有明顯增長。而幀同步的技術重點及難點在於如何保證全部客戶端的計算結果一致。
優化


幀同步結構圖


幀同步大體的結構爲,客戶端將輸入發送給服務端,而後服務器以統一的幀率將各個客戶端的輸入轉發給其它客戶端,各個客戶端收到全部輸入後在本地統一進行計算。


優缺點比較



狀態同步

聯繫方式

錄像文件大小

一等獎

138XXXX9572

流量消耗

一等獎

138XXXX9572

開發調試難度

一等獎

138XXXX9572

安全性

138XXXX9572

可否離線戰鬥

額外開發

138XXXX9572

網絡卡頓時表現

額外開發

見下文


一般採用幀同步的開發和調試難度相比狀態同步會高一些,由於狀態同步僅需維護好服務端的一份邏輯,而幀同步較難保證全部客戶端的一致性。從安全性來講,狀態同步相比幀同步會更加安全,幀同步在客戶端進行計算會面臨被Hack的問題。對於運行在手機網絡環境下相當重要的離線戰鬥功能,採用幀同步機制無需額外開發,而狀態同步則須要單首創建離線戰鬥的邏輯。


幀同步方案下的錄像文件更小,由於幀同步僅需保存指令。若是使用狀態同步,這個文件相對會很大,在儲存與傳輸上難度都較高。


狀態同步一般須要消耗更大的網絡流量,由於可能須要同步的數據量很大。在網絡卡頓的狀況下,狀態同步方案會出現角色閃現的問題,由於狀態同步一般會在本地進行一些預計算,可能會與最終服務端的計算結果不一致,重置客戶端計算結果時就會發生閃現的問題,能夠額外作一些處理來避免閃現。而幀同步方案在網絡環境不理想時,會出現一些動做和輸入的延時。


案例分析

目前採用狀態同步方案的遊戲有你們熟知的《Dota 2》、《守望先鋒》及《全民超神》。採用幀同步方案的有《Dota》、《風暴英雄》及《王者榮耀》。通用的兩種方案都有各自的優缺點與適用狀況,建議你們根據實際項目需求選擇最合適的方案。而《鬧鬧天宮》遊戲採起了幀同步的方案,下面就結合《鬧鬧天宮》的開發經驗,爲你們分享幀同步方案的重難點。



Dota遊戲截圖


幀同步方案的重難點主要在於三個方面:保證肯定性、流暢性以及針對外掛的處理。保證肯定性即確保全部客戶端的計算結果一致,這也是幀同步方案最大的難點。首先,要注意確保客戶端的核心邏輯和同步幀率一致。另外,對於須要使用隨機數的地方,保證初始化種子同步,且全部客戶端的隨機數調用次數一致。還需考慮到變量初始化、基準判斷數據以及數據結構遍歷順序等可能會致使客戶端不一樣步的問題。


其次是流暢性,影響遊戲流暢性的因素有二,網絡延遲與畫面卡頓。網絡延遲會致使玩家輸入與反饋之間的延遲,畫面卡頓則說明遊戲性能存在問題。對於實時性要求較高的MOBA類遊戲,推薦使用UDP,而後手動處理丟包與順序問題。對於畫面卡頓,要將顯示與邏輯分離,保證即使在底層邏輯上物體是抖動的,在客戶端顯示上也能看到物體流暢移動。


最後討論針對外掛的處理,外掛一般會修改遊戲屬性,若是使用幀同步,就須要檢測本地數據是否有修改,或者將本地數據進行Hash運算後傳到服務端進行校驗。若是服務端沒有該邏輯,也能夠將其它客戶端的數據發送到服務端比較兩個客戶端數據是否不一致,從而判斷是否某個客戶端出現了異常。幀同步除了同步指令外,也能夠選擇性地同步一些關鍵數據,來避免出現客戶端數據被修改的問題。


結語

關於《鬧鬧天宮》的網絡同步經驗就爲你們分享到這裏,相信其中分享的內容對於非MOBA類的其它遊戲也會有幫助。咱們還會繼續分享一些Made with Unity遊戲及VR/AR內容的開發經驗在Unity官方中文社區(unitychina.cn),請保持關注!







轉自:http://www.gameres.com/750888.html

在5月13日Unite 2017 案例分享專場上,藍港互動《鬧鬧天宮》項目組的主程序陳實分享了MOBA遊戲的網絡同步技術經驗,如下爲詳細內容:

  你們早上好,如今自我介紹一下,我叫陳實,來自藍港互動,如今是《鬧鬧天宮》項目組的主程序。我今天的主題是MOBA遊戲的網絡同步技術。這個主題昨天王者榮耀跟今天《球球大做戰》都涉及到一些,我講的內容可能會更底層一些,更接觸咱們實踐細節的部分。我不是在這裏教會你們怎麼作這個網絡同步的技術,而是想把咱們在使用這些技術的時候,遇到的坑,還有咱們認爲的重點,就是跟你們分享一下,而後可讓你們在使用一樣的技術方案的時候,能夠有一些坑你們就繞過了,若是節約你們開發的時間或者調試的時間,我以爲此次分享的價值應該就體現出來了。

  咱們講這個MOBA遊戲裏面的網絡同步技術,首先須要來了解一下,MOBA遊戲這個同步的一個特色。我把它概括爲三點,首先要求動如脫兔,就是實時性要求比較高,而後要順滑如絲,就是流暢性要求比較高。還有一個就是疏而不漏,就是公平性也要有必定要求。可是容許你在一些顯示的部分,咱們能夠說兩邊有一些差異,這是能夠接受的。可是涉及到核心的遊戲玩法的部分必須保證是同樣的。

  接下來我會分三個方面跟你們闡述一下這個主題,首先會講一下咱們在作這個網絡同步的時候,經常使用的兩種方案,狀態同步和幀同步,而後我會結合實際的案例來分析一下,哪些遊戲用哪一種方案,你們用對應的方案,能夠分析一下對應的作的比較好的遊戲,而後還會看一下,就是在網絡延遲的狀況下兩種方案表現有哪些不同。最後會着重介紹一下咱們項目在使用幀同步這個方案的時候,遇到的一些問題,而後裏面的一些重點和難點。

  那麼講一下狀態同步和幀同步。先說一下狀態同步,狀態同步顧名思義,就是同步玩家的狀態信息,好比位置,他的屬性,還有其餘跟玩法相關的數據。一般使用這種方案主邏輯基本上都在服務器運行,都在服務器進行計算,客戶端只是做爲一個顯示。還有一個特色,就是咱們通信的網絡流量大小是依賴於你的遊戲裏面,你的玩法裏面,須要同步的一個實體數量。

  咱們知道之前玩的比較多一些RTS遊戲,像星際爭霸,就不太會使用這種狀態同步的方案,他們能夠操縱兵的個體的數量是很是多,可能有上百個單位,若是這樣用狀態同步的話,流量就會很是大。咱們看一下這個方案的結構圖,你們能夠看到,客戶端會把一些,把他們的輸入發給服務器,而後服務器會作一個處理,把狀態信息發到客戶端作一個顯示。

  咱們再介紹一下幀同步,幀同步不太同樣的地方就是,只同步玩家的指令,不一樣步狀態。一般遊戲的邏輯都是在客戶端進行各自計算的。這確定帶來一個問題,就是說你要在各客戶端各自計算,你怎麼保證在各客戶端算出來的結果是同樣,這是幀同步的技術重點也是難點。而後就是網絡流量是不依賴於同步實體的個數,只依賴於指令,這麼一個大小,還有一個同步的頻率。像星際爭霸這種遊戲,即便須要同步的單位從一百個加到兩百個,加到三百個,對同步的網絡流量也不會有特別明顯的增長。

  咱們再看一下這個幀同步的結構圖,你們看到,客戶端會把它們的消息跟它們的輸出發送給服務器,服務器會以一個統一的頻率把各個客戶端的輸入轉發給其餘的客戶端,而後其餘各個客戶端收到你們的輸入以後,統一地進行運算。

  下面我就比較一下,咱們認爲這幾個重點的方面,使用這兩種解決方案可能有哪些不同。咱們來比較一下開發和調試難度,咱們認爲幀同步的難度是比狀態同步的開發調試難度會高一些。由於狀態同步的話,可能只須要有一份邏輯在服務器運行,只要寫好服務器的邏輯,保證正確就好了。幀同步由於各個客戶端去運算,很難說去保證一個一致性,很容易就會出現咱們所謂的不一樣步的現象,就各個客戶端整個遊戲的流程就分開了,兩個客戶端看到徹底不同的遊戲狀態。

  下面是一個安全性,咱們認爲狀態同步的安全性會高一些,由於全部邏輯都在服務器,由於幀同步邏輯是在客戶端運算,就存在一些hack,後面會降到一些外掛的問題,咱們若是用這個幀同步方案的話,咱們怎麼避免它。

  還有一個是離線戰鬥,咱們知道在手機上的MOBA遊戲,手機上的網絡,或者使用場景,網絡是不穩定的,可能咱們但願爲了體驗好一點,好比單排的時候,或者剛進來的時候第一場新手戰鬥,咱們但願跟AI在戰鬥。跟AI打的時候,不須要去跟服務器進行通信,保證剛開始的時候,體驗是很是好的。這個離線戰鬥也是一個很強的需求,若是你使用的是狀態同步的這種方案,可能須要額外去開發,由於一般咱們的Server和Client使用的開發語言是不同的,幀同步自己在客戶端算,只須要簡單轉發一下網絡的消息,就能夠實現說這麼一個離線戰鬥的邏輯。

  而後消耗流量的大小,一般來說狀態同步比較高,緣由也說過了,由於可能須要同步不少不少的屬性,而後還依賴於須要同步的實體的個數,還有一個就是網絡卡頓的時候的一個表現,狀態同步一般的表現是閃現,幀同步就是動做和輸入會出現一些延時。爲何會出現閃現,由於狀態同步一般使用的策略,會在本地作一個預算,你的預算很明顯極可能跟服務器算出來的最終結果不同,這樣他就會把客戶端重置到一個正確的狀態,就出現一個閃現的狀況。這種是原生就帶來這個問題,可是額外作一些處理的話,仍是能夠儘可能去避免這種問題。

  還有一個就是咱們說的錄像文件的大小,錄像文件的大小,這也是比較重要的。由於如今手機遊戲你們都但願去分享你的戰鬥,分享你的精彩的時刻。若是你使用狀態同步的話,這個錄像文件比較大,幀同步由於只存指令是比較小的,若是錄像文件比較大,你的儲存、傳輸都是很大的問題。

  下面我再結合具體案例再講一下,咱們來看一下,若是想使用狀態同步的話,你能夠去研究一下《Dota2》,他使用狀態同步的一個緣由,由於Dota2的廠商,有一個Source引擎,這個引擎基本上就是爲FPS類遊戲開發的,而FPS一般都是使用狀態同步,由於他們使用這個引擎,選擇狀態同步這麼一種方案,不少代碼就能夠複用。因此能夠看到狀態同步也能夠在MOBA遊戲上獲得一個很好的表現。還有就是你們比較熟悉的《守望先鋒》,他就是一個典型的FPS遊戲。咱們看一下使用幀同步的遊戲,幀同步就是《Dota》,他是基於魔獸爭霸3,還有就是《風暴英雄》,《風暴英雄》使用星際爭霸2的引擎,因此說就沿用了幀同步這麼一個結構。

  還有如今最火的《王者榮耀》,若是你們使用對應的方案能夠研究一下這些遊戲,他們的表現。下面截了一張,你們能夠看一下,這是騰訊的全民超神,你們能夠看到使用狀態同步方案,這個在400毫秒延遲的狀況下,你們看一下下面的小兵和英雄,就會出現閃現的狀況,還有一個你看最後英雄被擊殺的時候,沒有人打你,你卻莫名其妙的死了,這是一個典型的狀態同步在弱網絡環境下的表現。再對比看一下《王者榮耀》,王者榮耀一樣是400毫秒延遲的狀況下,看一下王者榮耀的表現,你明顯能夠看到左邊的搖桿往下以後英雄並無當即跟着往下,而是過了一下子才往下。可是你是怎麼死的,或者你的運行軌跡是怎麼樣的,仍是看的很是清楚的。我以爲可能右邊這種表現是更好的一種表現。

  上面就粗略地介紹了一下,咱們通用的兩種方案,我認爲沒有最好,只有最合適的,你們根據本身遊戲的一些需求和你策劃的玩法來選擇,使用哪種同步方案。

幀同步的重難點

  我會從三個方面來說,一個是怎麼樣保證肯定性,而後怎麼樣說能保證是流暢的。最後再來討論一下外掛的問題,外掛的處理。

  首先講一下肯定性,要保證肯定性,這是幀同步方案最難的地方。那麼你要保證這個肯定性,就是說各個客戶端根據一樣的輸入,算出一樣的結果,雖然這句話很簡單,可是想要作到算出一樣的結果是很是困難的。咱們能夠注意哪些問題呢,首先必定要把各客戶端的核心邏輯的同步頻率保持一致。若是你的頻率不同,好比用Unity的函數,每一幀運行時間間隔不同,若是這個不同的話會帶來很是多的問題,基本上是不可能算出同樣的結果,首先第一步就把這個頻率調成同樣的。

  而後是隨機數,咱們不少遊戲的話,確定會使用到一些隨機的東西,隨機數在使用的時候,咱們幾乎不能使用Unity自帶的隨機數,由於咱們知道咱們一般使用的是僞隨機數,咱們爲了保證在各客戶端的隨機數是同樣的,須要作哪些工做。首先須要把初始化的種子要同步,它們是同樣。而後還要保證在各個客戶端上,隨機數調用的次數是同樣。

  爲何不能使用Unity提供的隨機數,由於這個隨機數可能會被一些粒子系統,一些別的內部系統去調用,咱們是沒有辦法控制這些調用的次數的,因此,咱們須要實現一個本身的隨機數,來保證他的調用次數。而後浮點數,這也是討論比較多的主題了,到底咱們是應該使用浮點數仍是定點數來計算這個物理。據我所知,除了一些在主機上發佈的,由於他們只在PS4或者xbox上運行他們的遊戲,由於PS4和Xbox硬件架構是同樣,能夠得出結果。可是硬件架構不同,或者用不一樣的編譯器編譯咱們的代碼,能不能保證浮點數是同樣的結果,應該是能夠,可是基本沒有看到哪家廠商有這樣實現過,爲了作到這一點須要作很是多額外的工做,可能須要針對不一樣的CPU,而後不一樣的編譯器來優化咱們的代碼,還要作一些額外的工做,才能保證算出來的結果是同樣。咱們一般仍是用定點數來算。

  下面這點,爲何說幀同步開發難度比較高。若是不是很瞭解這個架構的人去寫這個遊戲邏輯的話,就極可能很天然使用一些本地的數據,就是一些客戶端獨有的數據,這我的能不能看到,渲染物體的位置等,可能這個位置在各客戶端上都是不同,若是拿這個來作判斷的話,就很容易顯示出來不一樣步,由於條件不同,那麼算出來結果天然就不同了。這個可能就得根據大家遊戲的一個設計,還有你的編碼來去判斷了,就你們可能須要注意這個問題。

  若是咱們在使用一些第三方庫的話,好比使用一些box2D這種庫,使用本身開發的庫來作物理運算的時候,仍是注意這個問題,可能一些變量沒有初始化,那在不一樣平臺上,或者不一樣編譯器編譯出來的代碼,初始的值是不肯定,若是用這個變量去運行一個邏輯的話,極可能就不一樣步了,並且還很難意識到這個問題。若是腦子裏面有這個概念,變量是必須初始化,就能避免這個問題,同時發生問題的時候,也能夠往這個方面想一下。

  而後就是一個遍歷的順序也會致使不一樣步,咱們的一個經研究說,咱們常常用Dictionary這個結構,你用這個結構是有問題,你可能天真地認爲,往Dictionary順序插入一二三四個元素,他是否是按一二三四的順序去遍歷,官方是不能保證的,若是用這個結構,你們能夠嘗試使用另一種SortedDictionary這個容器,這個容器有一些開銷,若是不頻繁插入的話是沒有什麼問題。

  而後就是Raycast返回的結果,在使用Unity的函數,可能會反饋給你一個結果,你碰到哪些東西。這個結果的東西也是不能保證,這個怎麼辦,咱們解決方法給每一個實體會有一個惟一的ID,這是咱們本身邏輯裏面的惟一ID經過這個ID作一個排序,最後排完序之後再使用Raycast的結果。

  咱們遊戲一些上層遊戲邏輯是用Lua來編寫的,Lua裏面有一個Table,使用這個結構也是注意這個問題,把他當成hash表來遍歷的時候,這個順序也很難保證,咱們必定要使用這個ipairs來遍歷,就是當成一個數組來遍歷。

  下面是流暢性,講流暢性以前,先了解一下,你不流暢的時候,究竟是一個什麼樣的表現。一般玩家反饋給你,只會反饋給你,一個是卡,或者說一卡一卡,或者卡卡的。玩家不會告訴你說,我是看到這個東西網絡是否是延遲了,或者說怎麼樣?不會這樣,他會給你的是一些很感性的詞。當玩家在說卡的時候,他在說什麼?其實他在說輸入和反饋之間存在延遲。輸入和反饋之間存在延遲,這極可能就是咱們的網絡,可能存在說你丟包要重發,就是網絡延遲。

  還有一個是畫面卡頓,畫面卡頓的話,遊戲存在性能問題,剛纔咱們《球球大做戰》跟咱們分享了優化的對你們也是挺有幫助的。而後還有一個就是遊戲物件在來回抖動,可能不是由於你的網絡延遲,也不是由於性能問題,可能單純只是由於你的這個物體,因爲你邏輯上有問題,致使它看起來在抖動,咱們就遇到過這個問題。

  下面講一下咱們怎麼來保證這個流暢性,TCP仍是UDP,這個問題討論的很是多了。一般來講,咱們認爲對實時性要求比較高的MOBA遊戲,咱們仍是選擇UDP,有些遊戲也是選擇TCP,其實也是作的挺好,也能夠根據本身的遊戲需求,若是你以爲TCP還OK,那就選擇TCP沒有問題,很成熟,也很可靠。不須要作額外的工做。若是你以爲你的遊戲對你的實時性要求比較強,仍是推薦你用UDP,使用UDP帶來什麼問題,首先UDP是不可靠的傳輸協議,可能須要本身去處理一下丟包,還有順序。一般經常使用的解決方案就是增長冗餘數據,若是一次發包,能夠一次帶兩幀的數據,若是丟包以後,丟了一個包,可是仍然可能仍是有額外的一幀供你使用,繼續去渲染。

  使用UDP,還有一個問題是說,中國網絡國情,有些網絡是連不上UDP的,在這種時候仍是須要處理一下,就是在UDP連不上的時候,是否是還要回去使用TCP。若是你們想要進一步瞭解TCP和UDP,我推薦你們一本書TCP/IP詳解,這個裏面講的是很是清楚的。

  第二個是Tran位置的更新順序,這是流暢性提到第三點問題,其實並非由於網絡延遲,也不是由於你的性能有問題,而是由於你的,就是更新有問題,而致使玩家看到抖動。而後會經常使用的一個方案就是說,使用這個運動補間,這就沒什麼好說的。這個還有一個問題,你們還會有疑問,剛纔說到了,咱們剛纔說的,要全部客戶端算出同樣的結果,若是用運動補間,由於這個運動補間是基於渲染幀,這個幀率也不能保證是固定間隔去調用的,這個就牽出下面一個問題,就是說你的顯示和邏輯必定要分離。你看到的這我的物的真實位置並非邏輯位置,就是客戶端已經拿到真實位置,可是並不把真實位置顯示到屏幕上,若是把真實位置顯示到屏幕上人物就是抖動,這個玩家體驗是很差,可是底層邏輯是抖動,可是顯示的物體是流暢的在移動的,我以爲這個玩家是能夠接受的。   下面再來討論一下外掛,外掛這個問題的話,一般外掛就是修改屬性,修改屬性的話,若是是使用幀同步的話,修改屬性基本上沒好說的,雖然是在客戶端各自算的,可是因爲你的數據並無說去同步,若是隻是簡單地把本地的數據給改了,好比把攻擊力從10調到一萬,去秒殺你,但這沒什麼用,由於別的客戶端攻擊力尚未提升,別的客戶端看到仍是正常,這種時候咱們可能須要一個檢測,是否本地有一些修改。可能你會會把一個玩家全部的屬性作一個Hash,而後去服務器上作一個校驗,若是你服務器沒有運行這個邏輯,不知道這個值算的對不對,可能須要把別的客戶端也發出來作一個仲裁,若是這我的算出來跟其餘幾我的算出來不同,那更傾向於認爲這個客戶端確定是有問題的。   修改屬性除了剛纔說的方法,能夠經過一些加密變量的方案,讓外掛找不到真實的值在哪裏。一般這個效果不是特別好,若是想改的話也是能改,一般仍是會去使用一個校驗。   第二個是透視外掛,之前老玩家玩的Dota比較多的,這個外掛仍是比較多的,由於在Dota裏面視野是很是重要的,因爲全部數據都在本地,你的控制這個玩家顯不顯示,可能只是一個變量的問題,改了這個東西,就能夠看到這個東西。可是對於一些其餘的遊戲可能,就相對來講沒有那麼重要,仍是說看大家的遊戲,這個重不重要。若是重要的話,咱們會怎麼辦?可能須要,一些關鍵數據。雖然幀同步只同步指令,可是應對外掛問題上,關鍵的數據仍是選擇去同步。好比你的透視只是一個變量的問題,可能就是一個字節的問題,對你網絡的帶寬就傳輸的東西影響是很是小的,可是就能夠徹底避免這個問題。   還有自動操做外掛,對咱們這種類DOTA的MOBA遊戲影響不大,能模擬一個玩家的操做表現很困難。可是對《守望先鋒》,這種操做外掛就影響很是大,比熟練玩家瞄的準多了,這個沒有特別好的方法,若是所作的是一種類DOTA的MOBA遊戲,就不須要去關注這種外掛,一由於也不太可能搞出這種外掛,若是作FPS這種遊戲還須要關注一下,目前業界沒有特別好的解決辦法,仍是會靠一些發動一些玩家去檢測來,用真人來檢查,來解決這個問題。   最後還有皮膚美化的外掛,若是很嚴重可能須要處理一下,去作一些檢查。若是不是特別嚴重,也不須要作一些額外的工做。以上就是個人全部的內容了,但願對你們有所幫助,謝謝你們。

相關文章
相關標籤/搜索