思來想去還是在開篇寫一下自己相對比較熟悉的網路模塊,因為它對於剛入門做網遊的同學來說,是一個必須要攻克的知識點,可以作為聯網Gameplay開發學習的入門著手點。

看了下知乎上已經有幾位大神詳細介紹了經典同步方案,從詳細程度上還是要首先推薦

Jerish:《Exploring in UE4》網路同步原理深入[原理分析]?

zhuanlan.zhihu.com
圖標

內容非常詳細,如能對比研讀相關同步代碼,一定會受益很多,我自己也很難在這個基礎上再詳實介紹了。另一篇

Jerish:《Exploring in UE4》關於網路同步的理解與思考[概念理解]?

zhuanlan.zhihu.com圖標

以問答的方式介紹了實際使用過程中可能遇到的疑問,都是實實在在的一線乾貨,如有相關工程經驗,讀起來會頗有共鳴。

還有這篇

JettHuang:UE4網路模塊淺析?

zhuanlan.zhihu.com
圖標

簡潔幹練地總結了收發端主要邏輯,也非常推薦閱讀。

我這裡想以比較容易理解的問答方式闡述下我對UE網路的理解:

1. 什麼是網路同步?

多人遊戲裡面需要把某個玩家操作的結果通知給其玩家,這個通知的過程就是同步,再放到區域網或者廣域網中進行,就是網路同步了。

2. 點對點還是中介轉發?

點對點(P2P)就是N台機器相互直連,每台機器需與剩下N-1個機器建立連接,複雜度為O(N^2),而且增刪機器也非常麻煩,對於大型網遊來說這個方案基本不考慮。

中介轉發就是我們常說的客戶端/伺服器模式(C/S),添加一個伺服器作為中介節點,每台客戶端只與伺服器建立連接,客戶端與客戶端彼此獨立,伺服器負責轉發消息。這種架構的複雜度僅為O(N),維護起來也方便,所以網遊幾乎清一色的採用這套架構。

3. 幀同步還是狀態同步?

幀同步是伺服器將某個玩家的輸入直接轉發給其他玩家,自己不做處理。理論上所有客戶端都以相同的初始狀態開始,只要收到的輸入相同,那麼每時每刻的狀態都會是相同的。

狀態同步是伺服器只同步影響遊戲功能的某些重要狀態變數,並且這些重要變數是在伺服器運算出來的或者至少校驗過的,客戶端拿到這些狀態變數後自行做本地的表現。

一般來說幀同步在實時性、節省流量方面比較好,狀態同步則在安全性角度來說更勝一籌。具體選用哪種方案由具體遊戲類型來決定,UE是在射擊遊戲基礎上發展而來的,它默認的網路同步方案是狀態同步,把決策權放在伺服器上做,可以有效減少外掛,對於中途加入/斷線重連也能天然支持。

4. TCP還是UDP?

TCP連接的優點是可靠穩定,但速度慢這個缺點導致它並不適合網遊。但UE也並未照搬UDP連接方案,而是在這個基礎上融合了TCP的優點,例如加入了亂序處理,以及對reliable的包丟失重傳。可謂是各取所優,既保證了連接速度,也保證了可靠性。

5. UE如何同步重要狀態變數?

保守的方法是把這些重要狀態變數每時每刻都對所有客戶端進行廣播,但這樣會造成流量的問題,也會帶來客戶端本地的計算複雜性。對於UE來說,需要同步的重要狀態變數都存在於Actor這個容器里。UE網路同步的設計方案有以下兩個特點:

(1)儘可能節省帶寬:

相關性計算:對於像吃雞這種大世界玩法,不需要每幀都同步一百個玩家的狀態,對於A玩家而言,只需要同步他可以看到的或者會受到影響的那部分玩家就可以了,這就是相關性的計算。

優先順序計算:判斷相關後還會進行優先順序計算,優先同步高優先順序的狀態變數,如帶寬飽合則當幀不會同步低優先順序的狀態變數。

成員變數計算:需要同步的Actor裡面會包含很多成員變數,但不是每個成員變數都需要同步,只有開發者打上網路同步標記的變數才會被同步,而且這個變數只有在伺服器端發生變化了才會同步給相關的客戶端,甚至還有額外標記控制同步,比如bNetInit只在剛建立同步通道時同步。

合包:每個包里都會有額外的包頭信息,如果包拆得越細那麼佔用帶寬就會越多,UE裡面將多個Bunch(最小的同步單位)合入到一個Packet裡面進行發送,再在收端分拆回Bunch進行逐個處理。

(2)儘可能可靠:

丟失重傳:reliable的包在發端會保存一個備份,只有收到收端返回的Ack包確認後才會清掉,若收到的Ack包跳序則會觸發重傳。

Packet亂序整理:因網路鏈路複雜性,到達包順序可能與發端不一致,這時會進行整理,對於分包導致的不完整的部分(Partial)包也會等待重組。

包頭校驗:包頭存有內容塊的大小,如果不符合,則會丟棄這個包,防止壞包帶來的後續數據處理異常。

6. 成員變數同步還是遠程函數(RPC)?

成員變數同步的持久性較好,RPC則是瞬發的,玩家斷線重連後採用變數同步的方式仍是正確的,但RPC同步的東西卻不會再重放。

成員變數同步僅發生在伺服器到客戶端,RPC則是雙向的,如果想客戶端同步給伺服器什麼東西,那沒得選只能RPC。

RPC的實時性比成員變數好,因為RPC調用是瞬時發到遠端執行的,而成員變數同步還要等packet滿了之後才發車,不過這個因素其實不那麼重要,兩者相差很小。

7. 如何正確又優雅地使用UE網路同步功能?

提三點建議:

其一:一開始做功能先別管網路,優先單機,單機表現不正常剩下的都是白談。

其二:大概看下UE官網對於網路同步的使用,知道有哪些關鍵字(不多很簡單),再結合自身項目代碼或者ue4的sample工程(如shooter game),看下別人如何使用的,理解後學以致用,寫好後在編輯器裡面選2人勾DedicatedServer跑下是否正常。值得一說的是,UE4新加了component的同步,要善用這個模塊化的利器,不必像UE3一樣把同步變數都堆在Actor上。

其三:知其然更要知其所以然,使用起來方便但背後設計卻非常複雜,要靜下心下跟跟代碼,看看前面幾位大神的文章,對網路實現細節深入理解。

UE4.20版本針對大世界推出了一套新的網路同步方案RepicationGraph,解決50000+對象同步問題,這塊知乎上提的人比較少,我打算下一篇中介紹,詳見:

Jerry:UE4網路同步思考(二)---大世界同步方案?

zhuanlan.zhihu.com
圖標

推薦閱讀:
相关文章