1. 程式人生 > >遊戲後臺狀態同步與幀同步

遊戲後臺狀態同步與幀同步

最近開始學習一下游戲後臺的一些知識,一直很好奇多個玩家之間的資料是如何同步的,查了一下,目前使用的比較多的是狀態同步和幀同步。

狀態同步

同步的是遊戲中的各種狀態。

一般的流程是客戶端上傳操作到伺服器,伺服器收到後計算遊戲行為的結果,即技能邏輯,戰鬥計算都由伺服器運算,然後以廣播的方式下發遊戲中各種狀態,客戶端收到狀態後,更新自己本地的動作狀態、Buff狀態,位置等就可以了,但是為了給玩家好的體驗,減少同步的資料量,客戶端也會做很多的本地運算,減少伺服器同步的頻率以及資料量,該方式多用於回合制的遊戲。

狀態同步其實是一種不嚴謹的同步。它的思想中,不同玩家螢幕上的表現的一致性並不是重要指標, 只要每次操作的結果相同即可。所以狀態同步對網路延遲的要求並不高。像玩RPG遊戲,200-300ms的延遲也可以接受。 但是在RTS遊戲中,50ms的延遲卻會很受傷。

舉個移動的例子,在狀態同步中, 客戶端甲上操作要求從A點移動到B點,但在客戶端乙上, 甲物件從A移動到C,然後從C點移動到了B。這是因為, 客戶端乙收到A的移動狀態時, 已經經過了一個延遲。這個過程中,需要客戶端乙本地做一些平滑的處理,最終達到移動到B點的結果。(可通過增加動作前後搖來減少延遲——多播一點動畫,給伺服器多爭取一些時間!)

幀同步

RTS(即時戰略遊戲)遊戲常採用的一種同步技術 ,上一種狀態同步方式資料量會隨著需要同步的單位數量增長,對於RTS遊戲來講動不動就是幾百個的單位可以被操作,如果這些都需要同步的話,資料量是不能被接受的,所以幀同步不同步狀態,只同步操作。

1、幀率

大家小時候應該看過這樣的小人書:快速翻看就可以看到漫畫上的人物會動起來。

由於人類眼睛的特殊生理結構,如果所看畫面之幀率高於每秒約10-12幀的時候,就會認為是連貫的, 此現象稱之為視覺暫留。

遊戲中的所有動畫也是採用這種方式來渲染,只不過幀率是由GPU來控制,你所看到的畫面都是由GPU一幀幀渲染的,比如30幀/s,你所看到的畫面就比較流暢了,幀率越高你所看到的越流暢。

2、Lockstep——幀同步

幀同步可以說是通過幀率延伸過來的,你可以把一個遊戲看成一個巨大的狀態機,所有的參與者都採用同一個邏輯幀率來不斷的向前推進。

  • 我們把遊戲的前進分為一幀幀,這裡的幀和遊戲的渲染幀率並不是一個,只是借鑑了幀的概念,自定義的幀,我們稱為turn。遊戲的過程就是每一個turn不斷向前推進,每一個玩家的turn推進速度一致。

  • 每一幀只有當伺服器集齊了所有玩家的操作指令,也就是輸入確定了之後,才可以進行廣播(並不計算遊戲行為),進入下一個turn,否則就要等待最慢的玩家,如此才能保證幀一致。

  • Lockstep的遊戲是嚴格按照turn向前推進的,如果有人延遲比較高,其他玩家必須等待該玩家跟上之後再繼續計算,不存在某個玩家領先或落後其他玩家若干個turn的情況。使用Lockstep同步機制的遊戲中,每個玩家的延遲都等於延遲最高的那個人。

  • 由於大家的turn一致,以及輸入固定,所以每一步所有客戶端的計算結果都一致的。

這種囚徒模式的幀同步,因為某個玩家有延遲,而導致該幀的同步時間發生延遲,從而導致所有玩家都在等待,出現卡頓現象。

3、樂觀鎖&斷線重連

囚徒模式的幀同步,有一個致命的缺陷就是,若聯網的玩家有一個網速慢了,勢必會影響其他玩家的體驗,因為伺服器要等待所有輸入達到之後再同步到所有的c端。另外如果中途有人掉線了,遊戲就會無法繼續或者掉線玩家無法重連,因為在嚴格的幀同步的情況下,中途加入遊戲從技術上來講是非常困難的。因為你重新進來之後,你的初始狀態和大家不一致,而且你的狀態資訊都是丟失狀態的,比如,你的等級,隨機種子,角色的屬性資訊等。

為了解決這個問題,伺服器可儲存玩家當場遊戲的遊戲指令以及狀態資訊,在玩家斷線重連的時候,能夠恢復到斷線前的狀態。不過這個還是無法解決幀同步的問題,因為嚴格的幀同步,是要等到所有玩家都輸入之後,再去通知廣播client更新,如果A伺服器一直沒有輸入同步過來,大家是要等著的,那麼如何解決這個問題?

採用“定時不等待”的樂觀方式,在每次Interval時鐘發生時固定將操作廣播給所有使用者,不依賴具體每個玩家是否有操作更新。如此幀率的時鐘由伺服器控制,當客戶端有操作的時候及時的傳送伺服器,然後服務端每秒鐘20-50次向所有客戶端傳送更新訊息。(如果沒有操作, 也要廣播空指令來驅動遊戲幀前進)

在這種情況下,伺服器不會等到蒐集完所有使用者輸入再進行下一幀,而是按照固定頻率來同步玩家的輸入資訊到每一個c端,如果有玩家網路延遲,伺服器的幀步進是不會等待的,網速慢的玩家不會卡到快的玩家,只會感覺自己操作延遲而已。

4、技能同步

遊戲中有很多是和概率相關的,比如說技能的傷害有一定概率的暴擊傷害或者折光被擊等。按照幀同步的話,基於相同的輸入,每個玩家的client都是獨立計算傷害的,那麼如何保證所有電腦的暴擊傷害一致呢。這個時候就需要用到偽隨機了。

大部分程式語言內建庫裡的隨機數都是利用線性同餘發生器產生的,如果不指定隨機種子(Random Seed),預設以當前系統時間戳作為隨機種子。一旦指定了隨機種子,那麼產生的隨機數序列就是確定的。就是說兩臺電腦採用相同的隨機種子,第N次隨機的結果是一致的。

所以在遊戲開始前,伺服器為每個玩家分配一個隨機種子,然後同步給client,如此每個client在計算每個角色的技能時候,就能保證傷害是一致的。

幀同步的特性導致客戶端的邏輯實現和表現實現必須完全分離。Unity中的一些方法介面(如 Invoke, Update、動畫系統等)是不可靠的,所有要自己實現一套物理引擎、數學庫,做到邏輯和表現分離。 這樣即使Unity的渲染是不同步的,但是邏輯跑出來是同步的。

王者榮耀網路同步方案分享

霸三國(端遊):

採用Client-Server模式,伺服器做判定,客戶端純表現。

​好處:

  • 安全,因為都是伺服器計算,客戶端只負責表現層的功能,不會影響各種判斷的結果。
  • C端可以預表現,根據S的結果做修正、拉扯,抖動平滑,還允許丟包快速恢復。

缺點:

  • 需要同步的流量非常高(約等於本身的一個錄影),後續加入東西需要傳的內容會越來越多。(MOBA單位多,同步狀態多,流量大)。
  • CS開發關聯耦合多,聯調、週期長
  • 同等網路條件下,CS配合高頻度表現同步困難(客戶端表現與服務端判定的完美匹配困難)

王者榮耀:

採用幀同步,對網路要求苛刻,下發的執行序列不允許丟包,如果中間出現丟包,需要等待丟的包重新到達後才能順序後續執行。

技術要點:
lockstep是一種基於相同的初始狀態,相同的輸入,相同的處理邏輯,最終有相同的輸出的同步方式。每個客戶端開始load相同的資料,然後等待同步訊號的驅動,每一個step到來之後,才能驅動推進一幀的update,幀間隔(delta)是相同的,如果沒收到期望的那一個step驅動則需要掛起邏輯。每個客戶端上報自己的輸入引數,伺服器按固定間隔將輸入收集起來,帶上step編號廣播給所有客戶端。

  • 相同的初始狀態(不受畫質,本地順序和狀態影響)
  • 完全一致的輸入驅動內容及順序
  • ​完全一直的程式碼執行流程(模組呼叫順序,容器順序)
  • 完全一致的隨機數生成規則,一致的呼叫時機及次數
  • 儘量用整數實現各種遊戲系統和基礎數學庫(浮點數運算有精度問題)
  • 避免本地邏輯(比如獲取本地的時鐘引數之類的,即要保證使用的引數都是所有客戶端都一致的)

整體的網路結構,分三層:伺服器、客戶端邏輯層、客戶端表現層。

伺服器主要負責的功能有兩部分:一是收集所有玩家上行的輸入,把它按定時的間隔打包成輸入的序列,投放給所有客戶端;二是當客戶端出現丟包的時候,伺服器進行補發;還有把客戶端上行冗餘的資訊替換掉,比如有新的輸入到了,就把老的輸入Drop或者替換掉。王者我們的邏輯是66毫秒一次,1秒同步15個包,這是不能少的,因為幀同步不能丟包,資料包必須有嚴格的執行序列。

客戶邏輯層理解為客戶端本地的服務,就是所有客戶端執行的結果必須強一致,不能有真的隨機,不能有本地邏輯,不能有浮點數的運算,拿到相同的輸入,產生結果必須一致。

客戶端表現層是根據邏輯層的資料去做Copy或者映象,然後在表現層進行平滑,幀數不一樣,但是不會影響最終的運算結果,隻影響動畫和動作的表現。

TCP技術當外網出現丟包或者抖動的時候,受限於實現方式,比如視窗、慢啟動各方面的原因,會發現當出現重聯的時候會非常卡,所以PVP沒有用TCP,改為了採用udp。如果出現丟包,伺服器會在應用層做補發。客戶端不需要做反向ACK,因為幀是有序的,如果客戶端收到一個1,然後收到一個3,那麼肯定2丟失了,然後就請求伺服器重發。
上行和下行都會有冗餘,對於客戶端訊息上行的冗餘,當客戶端放了2個技能,收到回包之後,發現沒有訊息來抵消剛剛的操作,則會進行補發。對於下行的冗餘,每一幀都會帶上至少3幀的資料(會根據具體情況浮動),這樣子如果最近3幀資料有丟包,則客戶端直接可用,不需要再重發,減少延遲。冗餘儘量放在同一個mtu裡面。udp受限於mtu的大小,大於mtu,會出現分包,可能也會出現整包的丟失。所以我們也會有些比較大的包會在應用層由伺服器做分包,中間出現丟包再由伺服器補發,把零碎的包拼成整包再做解包。

幀同步的訊息比較小,按照理論1秒15個驅動幀來算,20分鐘的錄影是10M左右。但是我們外網統計,正常的5V5對局20分鐘,錄影的大小大概是3M左右。伺服器會把玩家的操作做純記憶體的儲存,當出現丟包的時候,伺服器會通過編號快速找到快取資訊進行下發(可靠UDP下發)。同時根據丟包的情況,我們會計算給這個人傳送冗餘量的變化量。最開始傳送每個包會冗餘前面3幀的資訊,如果丟包嚴重,我們會嘗試冗餘更多資訊再下發。客戶端拿到之後會盡量壓縮邏輯執行的過程。幀同步有比較麻煩的模式在於,它不像CLIENT-SERVER的模式隨進隨出,崩潰之後重回必須從一開始執行,中間運算過程不能少掉。

一些嘗試最後放棄:

  • 客戶端上行之後,不需要伺服器定時的間隔去做收集然後下發,而是通過染色幀編號直接下發,這樣響應更及時,操作反饋更強、更快。當時我們做出來的結果是,這對手感的提升微乎其微,但是帶來的負面問題卻很大,因為不再是一秒15個包固定的下發,下發包的數量非常多,完全和這個人的操作習慣有關係,有可能一個人一秒之內產生了十幾二十個輸入,就需要把這些輸入打包之後對客戶端下發。客戶端因為收包很多,裝置也會明顯發燙。

  • 傳統的幀同步的方式會做延遲投遞,這個我們也有嘗試過。如果間隔時間內出現丟包,或者出現包下行的時網路波動,可以通過延遲投遞這種方式抹平抖動和丟包的情況。我們嘗試過這個方案但最終沒有這樣做的原因在於:《王者榮耀》裡面一些英雄體驗起來感覺偏動作,對反應要求比較快,延遲投遞雖然抗抖動和抗丟包的能力確實不錯,但是手感上達不到我們的要求。

  • 做CLIENT-SERVER方式的實現,一般都會有一個套路,客戶端提前表現,根據伺服器的表現做平滑或者拉扯。這個方案我們也嘗試過,但最終還是放棄了,因為這個技術會讓角色本身的表現有點發飄。客戶端本地動,馬上客戶端表現就跟著動,但根據伺服器的下行,其實會做一些偏移或者修正。當網路抖動出現的時候,角色會有一點發飄,所以這個方案我們放棄掉了。(目前的預表現是大概20幀,一秒多,之後如果沒有收到包會卡住不動了)

  • 幀同步方案,所有客戶端進行運算,期望產生一致的結果,但如果因為bug或者某個人使用修改器,跑出來的結果會和其他人不一樣,當不一樣出現,我們的說法是不同步了。我們會定時把一些關鍵資訊提取出來做hash,不同步的人的hash和其他人會不一樣。這是時候把這個人踢掉重連。

安全方面:

  • 舉手表決:出現不一致時,多數結果者定為最終結果。
  • 對於爭議局:客戶端記錄關鍵資訊,結算時傳給伺服器,伺服器做判定記錄,看看哪個異常點多,多者無效。

相關推薦

遊戲後臺狀態同步同步

最近開始學習一下游戲後臺的一些知識,一直很好奇多個玩家之間的資料是如何同步的,查了一下,目前使用的比較多的是狀態同步和幀同步。 狀態同步 同步的是遊戲中的各種狀態。 一般的流程是客戶端上傳操作到伺服器,伺服器收到後計算遊戲行為的結果,即技能邏輯,戰鬥計

伺服器的cs同步同步

(一):cs同步          客戶端傳送訊息到伺服器,伺服器進行廣播(伺服器不儲存玩家移動或者位置等等相關資訊) (二)幀同步       玩家所有的動作都做在伺服器上面,是伺服器決定玩家的動作然後發給客戶端,客戶端進行表現。(伺服器儲存玩家所有狀態,伺服器先進行操作

solr之mysql全量同步增量同步

一、solr管理員命令 二、案例實戰說明(全量同步與增量同步) 一、solr管理員命令 我們在生產環境時,需要管理員維護solr伺服器的資料資訊,,那麼這裡有3種主要手段: 1.curl方式 curl http://localhost:8080/solr/updat

總結moba遊戲皇室戰爭類遊戲同步區別

  之前公司做一款類皇室戰爭遊戲,實時性操作要求不是那麼強,最近在找工作,自己做了一個demo,模仿王者榮耀的moba遊戲,實時性操作非常強,兩個遊戲都是幀同步,因為實時操作的問題,導致兩個專案架構有很大不同。例如:伺服器給客戶端同步間隔時長,客戶端邏輯層驅動,操作執行時間各不相同等。今天

什麽是遊戲中的同步

提高 服務 顯示 多個 網絡數 操作 導致 其他 方式 遊戲中的幀同步是一種客戶端與服務器的同步方式,是為了實現高實時性的需求而設計的。在實時pvp遊戲中,要求每個客戶端高度同步,怎麽做到精確的同步呢,那就是向同步的所有客戶端廣播同步消息。由於網絡存在延遲,因此一個客戶端發

覆盤王者榮耀手遊開發全過程,Unity引擎使用同步放棄狀態同步

https://blog.csdn.net/anypkv/article/details/78480877 http://king.shandian.biz/88.html   如今已經大獲市場成功的《王者榮耀》一直是業內各方關注的物件,而我們也知道這款產品在成為國民級遊戲之前

小樂樂打遊戲 哈爾濱理工大學軟體微電子學院第八屆程式設計競賽同步賽(高年級)

連結:https://ac.nowcoder.com/acm/contest/301/G 來源:牛客網   題目描述         小樂樂覺得學習太簡單了,剩下那麼多的時間好無聊,於是便想打遊戲。      

手遊網絡遊戲Unity3D同步

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

同步的一些思考(四):Kcp RakNet 測試比較

測試程式碼 測試內容 伺服器以 66 毫秒 傳送 400 位元組的資料包,檢視客戶端前後 2 個包的時間間隔 弱網模擬 本次測試做以下2種測試: 伺服器輸出方向模擬 類似: tc qdisc add dev $NETCARD root

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

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

unity同步遊戲極簡框架及例項(附客戶端伺服器原始碼)

閱前提示:  此框架為有幀同步需求的遊戲做一個簡單的示例,實現了一個精簡的框架,本文著重講解幀同步遊戲開發過程中需要注意的各種要點,伴隨框架自帶了一個小的塔防sample作為演示. 目錄:

使用cocos2dx製作 同步 遊戲

重構了之前的遊戲程式碼,尋思把遊戲做成可以網路聯機的遊戲,於是百度各種資源,想學習一下。 學習資料倒是很多,最終選擇使用跟 皇室戰爭 一樣的同步方式,進行幀同步。 具體資料自行百度。 主要記錄一下遇到的問題。 一、修改原始碼 由於使用的是cocos2dx引擎,看原始碼,在c

漫談遊戲同步

在現代多人遊戲中,多個客戶端之間的通訊,多以同步多方狀態為主要目標。為了實現這個目標,主要有兩個方向的技術:  一種叫狀態同步:客戶端傳送遊戲動作到伺服器,伺服器收到後,計算遊戲行為的結果,然後通過廣播下發遊戲中各種狀態,客戶端收到狀態後顯示內容。這種做法類似於各個客戶端都遠

同步遊戲開發框架(推倒重構版)

幀同步訊息、物件池、邏輯/檢視層物件、事件訊息! 1. 幀同步訊息 幀同步訊息由Msg目錄下的幾個檔案進行管理,所有Input進行的操作皆是SendMsg來開始。 2. 物件池 物件池管理比較複雜, 但是對於整個程式而言十分重要,且可以幫助理清程式的結構,一定程度上幫助

實時對戰網路遊戲--基於同步的最佳實踐

網路遊戲概述   網路遊戲的發展始於90年代。歷經超過20年的發展,遊戲結構和內容發生了天翻地覆的變化。自2005年以後,網路遊戲的結構逐漸趨於穩定。網路遊戲從聯網特性上,可以大致分為弱聯網和強聯網兩大類。弱聯網,如大部分的頁遊,部分的手遊。除此之外的網路

網路遊戲同步物理模擬

筆者介紹:姜雪偉,IT公司技術合夥人,IT高階講師,CSDN社群專家,特邀編輯,暢銷書作者,已出版書籍:《手把手教你架構3D遊戲引擎》電子工業出版社和《Unity3D實戰核心技術詳解》電子工業出版社等。本篇部落格我們將用網路中的幀同步技術進行物理模擬,幀同步是通過僅傳送控制該

同步遊戲開發小結

*本文發表於程式設計師劉宇的個人部落格,轉載請註明來源,https://www.cnblogs.com/xiaohutu/p/12402399.html* 這幾年做了一些網路同步專案,總結一下幀同步的一些東西。 ## 1. 幀同步基本特點 1. 所有的邏輯行為運算都在客戶端進行,客戶端保證彼此之間執

配置DNS的正反向解析主從同步

dns配置DNS的正反向解析與主從同步準備:本實驗基於兩臺centos6.5其內核版本號為2.6.32-431.el6.x86_64配置時間同步# echo "#update system date by jiajie at 20170506" >>/var/spool/cron/root #

Linux同步相互排斥應用(零):基礎概念

使用 line 關系 並發執行 來看 文章 必須 生產者 而且 【版權聲明:尊重原創,轉載請保留出處:blog.csdn.net/shallnet 或 .../gentleliu,文章僅供學習交流,請勿用於商業用途】 當操作系統進入多道批處理

linux同步通信

數據不一致 sha 能夠 屬性。 異常終止 內存拷貝 互斥鎖 協議 關聯 這幾天讀完了UNP v2,對進程間通信與同步的方式有所了解,現對主要的知識點總結如下: 根據出現的歷史,先有的管道,FIFO,信號,然後是systemV IPC,再是後來的Poxis IPC,syst