挑戰(zhàn)1:網(wǎng)絡(luò)同步
挑戰(zhàn)2:是網(wǎng)絡(luò)的可靠性,包括應(yīng)對網(wǎng)絡(luò)的延遲,丟包和掉線
挑戰(zhàn)3: 反作弊和安全系統(tǒng),因為網(wǎng)絡(luò)游戲的本質(zhì)是經(jīng)濟(jì)系統(tǒng)
挑戰(zhàn)4:多樣性(不同設(shè)備,不同服務(wù)器),在不停服的情況下熱更新
挑戰(zhàn)5:大量人數(shù)時對高并發(fā),高操作的要求
Network Protocols 網(wǎng)絡(luò)協(xié)議
Socket編程,通過接口,確認(rèn)好相互的協(xié)議,就可以快速的建立持續(xù)的鏈接
國內(nèi)是IVP4 居多,最好兼容IPV6,這是世界標(biāo)準(zhǔn)
通過三次握手建立可靠的連接,確保發(fā)送的包是有順序的,會進(jìn)行流量控制,但網(wǎng)絡(luò)阻塞時會自動降低發(fā)包的效率
基本原理:當(dāng)任何一個接受者收到一個信息時,給sender發(fā)送一個ACK(告知),當(dāng)sender收到ACK時,才持續(xù)的往后發(fā)包。如果sender未收到ACK,會持續(xù)發(fā)送同一個消息
阻塞控制:滑動窗口,可以動態(tài)的控制發(fā)送數(shù)據(jù)的大小,當(dāng)發(fā)生阻塞,丟包或者超時時,按照一定算法減少滑動窗口
端對端的傳輸,更簡單,不需要建立長時間的連接,不需要一定要保證穩(wěn)定,不管有沒有收到,不管順序,不管流量控制。發(fā)送完就不管了
對于時間(延遲)不太敏感的操作類型的游戲,可以選擇TCP,對于響應(yīng)特別快速(FPS類),尤其在公網(wǎng)這種不穩(wěn)定的網(wǎng)絡(luò)下,用UDP反應(yīng)較快
對于大型的MMO類型這種來說,不會用單一協(xié)議,會用組合協(xié)議,用TCP協(xié)議來進(jìn)行簽名認(rèn)證,確認(rèn)登陸,建立賬號連接,心跳包等。當(dāng)游戲進(jìn)入到戰(zhàn)斗,進(jìn)入到這個世界里時改用UDP,在聊天,郵件等,又走回TCP通道。
TCP太慢了,需要穩(wěn)定發(fā)送上一個消息,才能繼續(xù)發(fā)下一個消息,并且效率隨著帶寬變化不穩(wěn)定
UDP不可靠,無法確認(rèn)消息到底有沒有發(fā)送成功
實戰(zhàn)中常常對協(xié)議進(jìn)行深度的改造,定制適合的協(xié)議:基于UDP的可靠連接
1.需要可靠的連接(TCP)
2.保持一定的順序(TCP)
3.需要非??斓姆磻?yīng),最好沒有延遲 (UDP)
4.需要群發(fā)(UDP)
ACK:確認(rèn)收到
NACK:什么包沒收到
SEQ:序列號
ARQ:當(dāng)我建立一個網(wǎng)絡(luò)連接傳包時,如果我丟包或者未收到,能夠有辦法能告訴對方
滑動窗口協(xié)議:當(dāng)有很多數(shù)據(jù)要傳輸時,會一次性把窗口里的數(shù)據(jù)全部傳輸,當(dāng)我收到接收方返回的ACK包時,如果我收到的2號包的ACK,便確定0,1,2都已傳輸?shù)轿?,接下來傳?,4,5,6,因為3已經(jīng)傳了,只需傳輸4,5,6,直到收到剩下包的ACK,窗口便繼續(xù)往下滑動
窗口設(shè)成1,每個包發(fā)送完后要等ACK收到,才往下走
如果發(fā)現(xiàn)窗口里的一個包丟失,只把窗口里的包再傳輸一遍。窗口持續(xù)往下走,會被告知NACK(哪個包丟失),把丟失的包重新發(fā)送。連接更穩(wěn)定,能減少帶寬的浪費,但是有額外ACK類型,即NACK
解決UDP丟包的問題
丟包率低一個值的時候不管,然后通過FEC的方式把丟掉的包在傳輸段的另一頭計算回來,通過額外的數(shù)據(jù)量換取穩(wěn)定性
增加一個E(異或運算校驗位),丟包后的數(shù)據(jù)可以通過異或校驗位還原
對D構(gòu)建一個矩陣B(確保任意抽掉若干行,仍然是一個可逆的矩陣),
B矩陣 乘以 D 矩陣 得到了 G,包含了三個其他多算出來的
傳輸中出現(xiàn)丟包
B`相對于 B的去掉了丟包數(shù)據(jù)的行數(shù)
B` 的逆矩陣可以重新將數(shù)據(jù)還原
總結(jié):構(gòu)造一個矩陣,確保矩陣抽掉若干行仍然可逆。將拿到的信息乘上,抽掉了對應(yīng)行矩陣的逆,就可以恢復(fù)原始信息
定制自己獨立的UDP策略:對ARQ有所理解,使用滑動窗口的方法(一個pool)去傳遞數(shù)據(jù),確定resending/retransimission的策略,加上一定FEC的算法,保證即使在一定的丟包率下,包體仍然能正確收到,確保ACK盡量的成功
Clock Synchronization 時鐘同步
RTT和Ping非常接近,區(qū)別是Ping更底層,是不同的協(xié)議層
RTT 很多時候是應(yīng)用層自己寫的,游戲里很多時候不用區(qū)分的太嚴(yán)格,RTT用的多一點
在協(xié)議包里有四個時間
t0:客戶端發(fā)送的時間
t1:服務(wù)器收到的時間
t2:服務(wù)器發(fā)送的時間
t3:客戶端收到的時間
通過這個算法可以估算出RTT
案例:延遲delay是4秒,按延遲即服務(wù)器發(fā)送的時間t3,客戶端接收到的時間應(yīng)該是35秒,與客戶端本地時間05秒相差30秒。則估算出客戶端和服務(wù)器相差30秒
算法與現(xiàn)實不符合的假設(shè)是:
1.網(wǎng)絡(luò)的速度是恒定的
2.上下兩路是對等的
1.先跑一邊NTP算法,算出服務(wù)器和客戶端的時間差
2.快速調(diào)整客戶端的時間,然后做多次NTP算法,算出一系列NTP算法
3.把大于offset平均值50%的值扔掉,然后按剩下的offset值取平均值做時鐘校準(zhǔn)
鏈路不可靠的情況下,只能逼近準(zhǔn)確的服務(wù)器時間,無法真正的完全校準(zhǔn)
RPC Remote Procedure Call 遠(yuǎn)程程序調(diào)用
socket 編程模式緩解了復(fù)雜計算機(jī)網(wǎng)絡(luò)架構(gòu)的困難,但是在游戲業(yè)務(wù)邏輯方面其還有一系列的問題
socket 編程會需要使用到Messages的方式來工作,定義很多的消息,消息里面會包含很多的參數(shù)
客戶端和服務(wù)端很多時候系統(tǒng) OS 不一樣
1.常見的有Linux作為服務(wù)器收發(fā)處理數(shù)據(jù),客戶端是安卓, IOS,Windows
2.Big Ending 和 Small Ending, 高位在前還是低位在前
3.數(shù)據(jù)打包之后需要對齊(4個Byte為單位),否則就會有很多空間浪費
4.解密和加密
讓程序員像正常寫業(yè)務(wù)代碼,作為一個庫存在,然后傳入?yún)?shù)。之后如何變成Message,如何打包,如何序列化,網(wǎng)絡(luò)如何路由到服務(wù)器,服務(wù)器如何接受,處理消息,如何返回等等這些都交給RPC來完成
案例
免去后臺的處理過程,專注業(yè)務(wù)邏輯
IDL Interface Definition Language 界面定義語言
IDL 會定義各種參數(shù),類似schema的定義
RPC Stubs RPC 存根:
當(dāng)一個客戶端或服務(wù)器起來之后,彼此會告訴對方自己上線,然后注冊一大堆的RPC(用來個函數(shù)調(diào)用)。
每次call RPC時可以在RPC的存根里查詢,如果沒有對應(yīng)RPC,系統(tǒng)會報錯,但不影響其他業(yè)務(wù)邏輯的運行。
真實RPC路徑:發(fā)出RPC請求后,首先進(jìn)行壓縮,加密,然后網(wǎng)絡(luò)傳輸,服務(wù)器接收后,進(jìn)行解密,解壓縮
Network Topology 網(wǎng)絡(luò)拓?fù)?/h3>
現(xiàn)在多人游戲用的比較少,很多時候是點對點時使用,主要是switch這種局域網(wǎng)上使用p2p連接
p2p一般不會考慮作弊,沒有什么限制
相比P2P,會選擇一個玩家作為一個主機(jī)然后傳輸,早期網(wǎng)吧很多局域網(wǎng)游戲是這種類型。
現(xiàn)在一些沙盒類游戲,還有steam上的很多游戲是這種方式
不需要開發(fā)商維護(hù)一個服務(wù)器,玩家自己可以作為服務(wù)器
專用服務(wù)器:用于更復(fù)雜的大型MMO,電競對戰(zhàn)
會在服務(wù)端維持一個一致的世界,所有的客戶端獲得相對公平且穩(wěn)定的連接
當(dāng)跨越大洋的時候,物理延遲就是也需要考慮的。尤其是對于全球發(fā)行的游戲
所以各個區(qū)域一般都設(shè)置Protol,然后protol通過專有網(wǎng)絡(luò)會鏈接到服務(wù)器上,從而不會使用公網(wǎng)的轉(zhuǎn)跳,大大降低延遲
網(wǎng)絡(luò)游戲加速器也是基于這個原理
Game Synchronization Intro 游戲同步
單人運行,單人輸入
操作和顯示是有延遲的,所以需要同步兩個世界
1.快照同步 2.幀同步 3.狀態(tài)同步
Snapshot Synchronization:
客戶端只負(fù)責(zé)把輸入發(fā)給服務(wù)器
服務(wù)器進(jìn)行整個游戲世界的模擬
把整個游戲世界的狀態(tài)生成一個快照(每個物體的血量,位置,速度。。。)
將快照發(fā)送給客戶端
客戶端展示快照的數(shù)據(jù)信息,(渲染繪制)
保證了整個世界狀態(tài)的一致性,客戶端只是一個渲染繪制的表現(xiàn)。
服務(wù)器會希望快照的計算不要占用過多的帶寬,幀率會較低,10-20左右,客戶端為了更絲滑的效果,幀率會更高。
客戶端會在兩個服務(wù)器快照之間進(jìn)行插值
快照的數(shù)據(jù)量較大,且往往兩個快照間多數(shù)物體沒有變化,因此快照一般傳遞的是變化量,減少傳輸數(shù)據(jù)的大小
優(yōu)點:
1.代碼非常的簡潔干凈
2.絕對一致,無法作弊
缺點:
1.客戶端的算力被浪費掉
2.生成快照的數(shù)據(jù)量很大,所需的上傳帶寬非常大
Lockstep Synchronization
可以理解為軍隊行走,整齊劃一,某種程度上的高度性
也可以理解為是有回合制的,是有順序的,類比與下棋
所有的信息一致性的同步的傳遞給目標(biāo),目標(biāo)一致的處理
最簡單的思想
所有客戶端的操作統(tǒng)一的發(fā)給服務(wù)器,服務(wù)器再同一的分發(fā)給客戶端,客戶端做一致的模擬。
服務(wù)器一般做信息的匯總,同步及轉(zhuǎn)發(fā)的處理
第一步初始化游戲內(nèi)的初始狀態(tài)(王者榮耀的加載條),必須要做到完全的一致,因為同步的是操作,如果初始條件有一絲偏差,最終結(jié)果可能誤差非常大。
還需要同步時鐘
每一幀都接受所有的客戶端輸入,確認(rèn)收到所有輸入后統(tǒng)一的發(fā)給所有人,所有人然后同時開始模擬
優(yōu)點:簡潔明了
缺點:延遲非常明顯,所有人的延遲等于延遲最高客戶端的延遲
公網(wǎng)幀同步的優(yōu)化:
引入了Bucket,每隔一個Bucket(例如100ms)的時間內(nèi), 未收到客戶端的操作,則丟棄這個客戶端的操作
網(wǎng)絡(luò)差者獲利,與網(wǎng)絡(luò)優(yōu)者獲利。權(quán)衡一致性和實時性
幀同步需要整個游戲邏輯具有確定性(Deterministic)
一樣的輸入,經(jīng)過各種復(fù)雜的迭代運算后,保持一致結(jié)果很難
浮點數(shù)
隨機(jī)數(shù)
數(shù)據(jù)容器,計算的算法
數(shù)學(xué)庫
物理的模擬
邏輯執(zhí)行順序
幀同步上述一定都要保證一致
浮點數(shù)存儲要符合IEEE754的標(biāo)準(zhǔn),可以嚴(yán)格意義上保證浮點數(shù)一致性
但是不同平臺的實現(xiàn)是不一樣的
很多數(shù)學(xué)運算中需要用到三角函數(shù),根號等,需要用查表法:所有的數(shù)字必須要是鎖死的,不能各自算各自的
使用Fixed-point number 定點數(shù)的方法來計算,使用固定長的數(shù)字來處理數(shù)學(xué)運算,從而保證高度的一致性
整個游戲保持一致確定性幾乎是不可能的,要把最核心的業(yè)務(wù)邏輯確定一致性。比如角色的移動,位置,血量,一些游戲的狀態(tài)。但是渲染這種不確定不會有太大影響
同步隨機(jī)數(shù)種子,且隨機(jī)算法必須一致
游戲的確定性是幀同步的基礎(chǔ),如果無法保證一致性,則幀同步不能成立
跟蹤和調(diào)試
錯誤是會不斷累積的,需要不停地把游戲的狀態(tài)保存下來,使用checksum的方法。
checksum:把現(xiàn)在所有的變量存在一起,算出一個md5編碼,存出去,把游戲里所有的函數(shù)的call和parameter編程一個hash值存在那??赡苊?-10幀,存下快照,包括input也保存快照
滯后和延遲
把服務(wù)器傳過來的幀cache幾幀,當(dāng)服務(wù)器出現(xiàn)延遲,本地邏輯幀依舊能從cache獲取
例如網(wǎng)絡(luò)視頻播放,是分成很多塊,每次下載好幾塊作為cachebuffer
邏輯幀和渲染幀分離:
服務(wù)器差不多10幀,期間插入很多渲染幀。
當(dāng)網(wǎng)絡(luò)出現(xiàn)延遲或者各種問題時,渲染幀,畫面不會因此出現(xiàn)各種各樣的抖動。
斷線重連:
客戶端不僅僅只接收input,每隔一定幀數(shù)會有特定key frame把當(dāng)前所有游戲的狀態(tài)做一個snapshot并存在本地的內(nèi)存或磁盤,保證游戲即使崩潰,snapshot的快照還在。
每次重連,從上一次快照的幀數(shù)開始演算到當(dāng)前的幀數(shù)。避免從頭開始演算
如果發(fā)生了重連情況,那么可以放棄渲染幀,只跑邏輯幀,以更快速度的邏輯幀,一定能追上現(xiàn)在游戲的進(jìn)度
服務(wù)器再一些特定的keyFrame保存一個快照
當(dāng)有些玩家斷線時間過長,服務(wù)器可以給個更新的快照,幫助客戶端設(shè)置游戲的狀態(tài)
另一個應(yīng)用是觀戰(zhàn)模式
觀戰(zhàn)實際上與斷線重連的底層技術(shù)一模一樣。服務(wù)器把前面關(guān)鍵幀的信息發(fā)送給客戶端,再把參與玩家的input發(fā)送給客戶端。注意觀戰(zhàn)發(fā)送的數(shù)據(jù)是有主動延遲防止作弊
回放同理
幀同步防作弊
多人情況下:投票機(jī)制,每隔一段時間,讓所有客戶端把游戲里狀態(tài)的checksum校驗碼發(fā)給服務(wù)器,然后進(jìn)行對比,有不一樣的直接踢掉
雙人對戰(zhàn)的情況下,服務(wù)器會有個checksum。有來校驗。(通常大部分雙人游戲,都是采用p2p,很少幀同步。除非是電競屬性很強(qiáng)的游戲)
幀同步的一個難點是:所有的信息和狀態(tài)都在客戶端上模擬,理論上可以還原出一些不該讓玩家看見的信息,例如moba的全圖和fps的透視
現(xiàn)代的游戲不會單純的使用最簡單的幀同步,會有很多復(fù)雜方法策略的幀同步來規(guī)避
優(yōu)點:
1.帶寬要求低,僅同步指令
2.解決確定性問題之后,開發(fā)效率很高
3.可以做一些對打擊操作非常敏感,精確的游戲
4.方便做游戲錄屏
缺點:
1.保持一致性很難
2.難以防止全圖掛這種問題
3.如果沒有服務(wù)器快照,斷線較長時,追趕問題會比較嚴(yán)重文章來源:http://www.zghlxwxcb.cn/news/detail-716601.html
State Synchronization
核心思想是不會同步整個宇宙。
每個玩家只會提交自己部分的信息和部分的狀態(tài),每個玩家自己模擬自己的世界。
服務(wù)器會模擬一個完整的全宇宙,只會把部分的信息,和當(dāng)前玩家相關(guān)的信息發(fā)給對應(yīng)客戶端
放作弊的能力會好一點點
Server最大,一切指令以服務(wù)器優(yōu)先級最高
Authorized:是這個玩家對于本身local的操作
Replicated:其他玩家看到的這個玩家的復(fù)制品,依賴于服務(wù)器傳輸?shù)男畔?img src="https://imgs.yssmx.com/Uploads/2023/10/716601-111.png" alt="Games104現(xiàn)代游戲引擎筆記 網(wǎng)絡(luò)游戲架構(gòu)基礎(chǔ),Games104游戲引擎,學(xué)習(xí)筆記,游戲引擎,筆記,學(xué)習(xí)" referrerpolicy="no-referrer" />
玩家1與玩家2客戶端看到的情況
玩家1:開火,發(fā)送服務(wù)器
服務(wù)器:玩家1開火,廣播所有客戶端
玩家2:收到通知,玩家1開火
服務(wù)器通知每個客戶端重復(fù)玩家1炮彈的運動
服務(wù)器判定擊中了一個單位,廣播給所有客戶端
狀態(tài)同步核心思想:
每個人提出自己的動作,整個世界的核心業(yè)務(wù)邏輯由server完成。server產(chǎn)生的結(jié)果與client提出的動作都會被同步給所有客戶端。
并不要求所有的客戶端保持高度一致性,只需要服務(wù)器做出判斷。
狀態(tài)同步只同步對于客戶端需要的信息,即一個感知范圍內(nèi)的信息(AOI算法)
有個問題是玩家A如果自己需要操作,如往前走,依舊需要等待服務(wù)器的確認(rèn),這就會造成非常大的延遲,導(dǎo)致操作不順手。
1.客戶端預(yù)測
2.服務(wù)器校驗
根據(jù)客戶端預(yù)測,提前移動,服務(wù)器校驗沒問題則保持不變
由于RTT和一個command frame的延遲,會導(dǎo)致客戶端永遠(yuǎn)比服務(wù)器超前
守望先鋒:估計一個RTT,約160ms,半個RTT 80ms,一個command frame 16ms(刷新率60幀每秒),則客戶端永遠(yuǎn)往前預(yù)測16+80ms,等服務(wù)器消息回來后,進(jìn)行對齊,對齊是個插值的過程,盡可能使移動變得平滑
client本地一個消息發(fā)出到從server回來接收可能長達(dá)上百毫秒,本地可能已經(jīng)跑了好幾幀,此時會把本地的每一次預(yù)測和每一個狀態(tài)全部buffer到一個序列幀里。當(dāng)server的每一個信息回來時,會和過去的信息進(jìn)行檢驗。因為從server回來的信息是經(jīng)過了半個RTT時間的傳輸,對于client接收的瞬間是過去的信息。
如果和server的校驗信息不一致,則以server的信息反向校準(zhǔn)
從client角度看,會有做了某件事,但被校準(zhǔn)回退的情況發(fā)生client需要一個ring buffer,存儲在過去幾幀的數(shù)據(jù),當(dāng)發(fā)現(xiàn)校驗問題時,ring buffer之后的數(shù)據(jù)全部無效,重新算一遍
online游戲很常見,對網(wǎng)速慢的玩家不利,因為對世界的更新不及時,操作反應(yīng)不如網(wǎng)速快的玩家
丟包問題:
1.server會把用戶的輸入,用一個ring buffer存儲起來,會存儲好幾幀的輸入
2.如果在一定時間內(nèi),接收不到用戶的輸入,有時候會自動把過去的最后一次操作進(jìn)行復(fù)制(如,跑動過程中斷網(wǎng),在其他客戶端展示的是扔在一直跑)
3.不同游戲有不同的處理丟包策略
number of players反了
幀同步:適合注重打擊感,對抗感,競技類的游戲。對引擎的要求很高,需要引擎的核心邏輯業(yè)務(wù)確定性非常高
狀態(tài)同步:適合網(wǎng)絡(luò)本身比較復(fù)雜,不太穩(wěn)定,并且游戲業(yè)務(wù)比較復(fù)雜。以及游戲的參與者非常多
現(xiàn)代主流引擎大部分能實現(xiàn)狀態(tài)同步,實現(xiàn)幀同步通常需要自己的引擎團(tuán)隊專門定制。文章來源地址http://www.zghlxwxcb.cn/news/detail-716601.html
到了這里,關(guān)于Games104現(xiàn)代游戲引擎筆記 網(wǎng)絡(luò)游戲架構(gòu)基礎(chǔ)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!