ECS與網路同步

2021-08-21 11:21:50 字數 2235 閱讀 9154

這個演講其實並沒有談及**和同步的具體技術,而是談 ecs 怎麼幫助降低利用這些技術的實現複雜度。同時也提及了一些有趣的細節。

但是,遊戲和電影不一樣的地方是,玩家自己的操作影響了電影的情節。我們需要在伺服器仲裁玩家的輸入對世界的影響。玩家需要告知伺服器的是,我這個操作是在電影開場的幾分幾秒下達的,伺服器按這個時刻,把操作插入到世界的程序中。如果客戶端等待伺服器回傳操作結果那就實在是太卡了,所以客戶端要在操作下達後自己模擬後果。如果操作不被打斷,其實客戶端模擬的結果和伺服器仲裁後的結果是一樣的,這樣伺服器在回傳後告之客戶端過去某個時間點的物件的狀態,其實和當初客戶端模擬的其實就是一致的,這種情況下,客戶端就開開心心繼續往前跑就好了。

只有在**操作時,比如玩家一直在向前跑,但是伺服器那裡感知到另乙個玩家對他釋放了乙個冰凍,將他頂在原地。這樣,伺服器回傳給玩家的位置資料:他在某時刻停留在某地就和當初他自己**的那個時刻的位置不同。產生這種**失敗後,客戶端就需要自己調節。有 ecs 的幫助,狀態回滾到發生分歧的版本,考慮到伺服器回傳的結果和新了解到的世界變化,重新將之後一段時間的操作重新作用到那一刻的狀態上,做起來就相對簡單了。

對於伺服器來說,它預設客戶端會持續不斷的以固定週期向它推送新的操作。正如前面所說,伺服器的時刻是有意比客戶端延後的,這樣,它並非立刻處理客戶端來的輸入,而是把輸入先放在乙個緩衝區裡,然後按和客戶端固定的週期 ( 60fps ) 從緩衝區裡取。由於有這個小的緩衝區的存在,輕微的網路波動(每個網路包送達的路程時間不完全一致)是完全沒有影響的。但如果網路不穩定,就會出現到時間了客戶端的操作還沒有送到。這個時候,伺服器也會嘗試**一下客戶端發生了什麼。等真的操作包到達後,比對一下和自己的**值有什麼不同,基於過去那個產生分歧的**產生的狀態和實際上傳的操作計算出下乙個狀態。

同時,這個時候伺服器會意識到網路狀態不好,它主動通知客戶端說,網路不太對勁,這個時候的大家遵循的協議就比較有趣了。那就是客戶端得到這個訊息就開始做時間壓縮,用更高的頻率來跑遊戲,從 60fps 提高到 65fps ,玩家會在感受到輕微的加速,結果就是客戶端用更高的頻率產生新的輸入:從 16 ms 一次變成了 15.2 ms 一次。也就是說,短時間內,客戶端的時刻更加領先伺服器了,且越領先越多。這樣,伺服器的預讀佇列就能更多的接收到未來將發生的操作,遇到到點卻不知道客戶端輸入的可能性就變少了。但是總流量並沒有增加,因為假設一局遊戲由一萬個 tick 組成,無論客戶端怎麼壓縮時間,提前時刻,總的資料還是一萬個 tick 產生的操作,並沒有變化。

一旦度過了網路不穩定期,伺服器會通知客戶端已經正常了,這個時候客戶端知道自己壓縮時間導致的領先時長,對應的膨脹放慢時間(降低向伺服器傳送操作的頻率)讓狀態回到原點即可。

btw, 守望先鋒 是基於 udp 通訊的,從演講介紹看,對於 udp 可能丟包的這個問題,他們處理的簡單粗暴:客戶端每次都將沒有經過伺服器確認的包打包在一起傳送。由於每個邏輯幀的操作很少,打包在一起也不會超過 mtu 限制。

ecs 在這個過程中真正發生威力的地方是在**錯誤後糾正錯誤的階段。一旦需要糾正過去發生的錯誤,就需要回滾、重新執行指令。移動、射擊這些都屬於常規的設定,比較容易做回滾重新執行;技能本身是基於暴雪開發的 statescript 的,通過它來達到同樣的效果。ecs 的威力在於,把這些元素用 component 分離了,可以單獨處理。

movementstate 會因為需要糾正錯誤**而被回退,同時還有一些非 movementstate 的狀態也會回退,比如門的狀態、平台的狀態等等。這個回退是 utility 函式的行為,它可能會影響受擊的表現,而受傷則是另一種固定行為(伺服器確定的推送)的後果。他們發生在 entity 的不同元件切片上,就可以正交分離。

射擊**和糾正可以利用物件的活動區域來減少判定計算量。如果能總是計算保持當前物件在過去一段時間的最大移動範圍(即過去一段時間的包圍盒的並集),那麼當需要做乙個之前發生的射擊命中判定時,就只需要把射擊彈道和當前所有物件的檢測區域比較,只有相交才做進一步檢測:回退相關物件到射擊發生的時刻,做嚴格的命中校驗。如果當初**的命中結果和現在核驗的一致就無所謂了,不需要修正結果(如果命中了,具體打中在哪不重要;如果未命中,也不管子彈射到**去了)。

如果 ping 值很高,客戶端做命中**往往是沒有什麼意義的,徒增計算量。所以在 ping 超過 220ms 後,客戶端就不再提前**命中事件,直接等伺服器回傳。

ecs 框架在這件事上可以做到只去回滾和重算相關的 component ,乙個 system 知道哪些 entity 才是它真正關心的,該怎麼回退它所關心的東西。這樣開發的複雜度就減少了。遊戲本身是複雜的,但是和網路同步相關的影響到遊戲業務的 system 卻很少,而且參與的 component 幾乎都是唯讀的。這樣我們就盡可能的把這個複雜的問題和引擎其它部分解耦。

同步與非同步訪問網路

訪問網路的基本流程 同步請求與非同步請求的比較 1 構建url位址 nsurl url nsurl urlwithstring 2 構建請求nsurlrequest,nsurlrequest 不可變物件,不能動態的新增請求資訊 nsmutableurlrequest request nsmutabl...

CentOS系統時間與網路同步

新裝的centos系統伺服器可能設定了錯誤的,需要調整時區並調整時間.如下是centos系統使用ntp來從乙個時間伺服器同步 第一步 把當前時區調整為上海就是 8區,想改其他時區也可以去看看 usr share zoneinfo目錄 cp usr share zoneinfo asia shangh...

CentOS系統時間與網路同步

新裝的centos系統伺服器可能設定了錯誤的,需要調整時區並調整時間.如下是centos系統使用ntp來從乙個時間伺服器同步 第一步 把當前時區調整為上海就是 8區,想改其他時區也可以去看看 usr share zoneinfo目錄 cp usr share zoneinfo asia shangh...