【翻譯搬運】起源引擎網絡同步模型(Source Multiplayer Networking)【二】

寫在前面

文章的原文很多地方都能找到

我貼一處起源引擎(Source Engine)開發公司Valve Software的網址,其他的我提供一處steam的。
① V社 VALVE(Dota2、半條命的開發) Source Multiplayer Networking
https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking
② Steam CSGO(Counter-Strike: Global Offensive)Source Multiplayer Networking
http://steamcommunity.com/sharedfiles/filedetails/?id=527313998

也有人做過優秀翻譯 【騰訊GAD譯館】 Source引擎多人模式網絡同步模型,我只是因爲自己注意力渙散覺得文章乾澀不寫下來就看不動,也請閱讀的大家不要用我的渣翻水平做橫向對比,取得必要知識信息就好。

找資料途中發現一篇更加準確的翻譯https://tieba.baidu.com/p/1819264994 搬運原文地址已不可尋,貼吧排版不是很方便閱讀。(所以我的坑還是會填完的~)

【2018-03-12】 對格式進行了整理,逐句的方式太影響閱讀體驗了,內容和原來還是相同的。

正文


索引


概述(第一篇)
基礎部分 Basic networking(第一篇)
支持Tickrate修改的服務器 Servers that Support Tickrate(本篇)
實例平滑插值 Entity interpolation(本篇)
客戶端輸入預測 Input prediction(本篇)
服務器滯後補償 Lag compensation(第三篇)
網絡狀態視圖 Net graph(第三篇)
優化 Optimizations(第三篇)
參閱 See also(第三篇)



支持Tickrate修改的服務器 Servers that Support Tickrate

這一小節完全可以略過

The tickrate can be altered by using the -tickrate parameter
- Counter Strike: Global Offensive
- Half-Life 2: Deathmatch

Tick的頻率可以通過 -tickrate 命令修改的
- 反恐精英:全球攻勢(CS:GO)
- 半條命2:死亡競賽

The following servers tickrate cannot be altered as changing this causes server timing issues.

- Tickrate 66
- Counter Strike: Source
- Day of Defeat: Source
- Team Fortress 2

- Tickrate 30
- Left 4 Dead
- Left 4 Dead 2

下面這些服務器的Tick頻率,因爲服務器方面的影響不能改變

固定Tick頻率66
- 反恐精英:起源
- 勝利之日:起源
- 軍團要塞 2

固定Tick頻率30
- 求生之路
- 求生之路 2



平滑插值 Entity interpolation

Paragraph 1

By default, the client receives about 20 snapshot per second. If the objects (entities) in the world were only rendered at the positions received by the server, moving objects and animation would look choppy and jittery.Dropped packets would also cause noticeable glitches. The trick to solve this problem is to go back in time for rendering, so positions and animations can be continuously interpolated between two recently received snapshots. With 20 snapshots per second, a new update arrives about every 50 milliseconds. If the client render time is shifted back by 50 milliseconds, entities can be always interpolated between the last received snapshot and the snapshot before that.

通常情況下,客戶端每秒大約接受20個snapshot。 如果遊戲世界中的實體,根據從服務器接受的數據直接渲染出來,那麼運動和動畫將會表現的十分不平滑。 丟包也會造成明顯的問題。 解決這個問題的關鍵,在於滯後渲染。這樣位置和動畫可以在兩個最接近的snapshot之中進行插值。 如果每秒接收20個snapshot,也就是每50ms會收到一個新的更新。 如果客戶端的渲染時間點推延50ms,實體就可以一直在上一個與上上一個snapshot之間做平滑插值。

Paragraph 2

Source defaults to an interpolation period (‘lerp’) of 100-milliseconds (cl_interp 0.1); this way, even if one snapshot is lost, there are always two valid snapshots to interpolate between. Take a look at the following figure showing the arrival times of incoming world snapshots:
這裏寫圖片描述
The last snapshot received on the client was at tick 344 or 10.30 seconds. The client time continues to increase based on this snapshot and the client frame rate. If a new video frame is rendered, the rendering time is the current client time 10.32 minus the view interpolation delay of 0.1 seconds. This would be 10.22 in our example and all entities and their animations are interpolated using the correct fraction between snapshot 340 and 342.

客戶端時間根據這個snapshot Source引擎默認的插值週期(lerp)是100ms(cl_interp值爲 0.1) 。 這種放下下,即使是一個snapshot發生丟失,依舊有兩個有效的snapshot可供插值。 下圖就是輸入到客戶端的snapshot的時間軸圖示:
這裏寫圖片描述
【額外說明】關於編號,此圖中編號的來歷猜測。
首先,說明強調的是,tick的頻率和snapshot的頻率並不在同一個頻率上。雖然圖中一一對應,但是意義在於利用xxtick給snapshot的順序帶來一個編號。
所以,下面譯文中我使用的說明是tick xxx的snapshot。
最後,關於數值的猜測,簡單做個除法 10.15s = 10150ms, 10150/338 = 30(ms),所以是約30ms一次tick,50ms一次snapshot接收。

最後一個snapshot接收於tick 344或者說是10.30秒。客戶端時間根據這個snapshot和客戶端自己的幀率而增加。 在我們的例子中,如果此刻要進行新一幀的渲染,那麼渲染的取插值的時間點,是從當前時間10.32s減去插值延遲時間段0.1s。 也就是(渲染第)10.22s,所有的實例,以及實例上的動畫,將要使用tick 340 的snapshot 和 tick 342的snapshot 的平滑插值計算出的值。

Paragraph 3

Since we have an interpolation delay of 100 milliseconds, the interpolation would even work if snapshot 342 were missing due to packet loss.Then the interpolation could use snapshots 340 and 344. If more than one snapshot in a row is dropped, interpolation can’t work perfectly because it runs out of snapshots in the history buffer. In that case the renderer uses extrapolation (cl_extrapolate 1) and tries a simple linear extrapolation of entities based on their known history so far.The extrapolation is done only for 0.25 seconds of packet loss (cl_extrapolate_amount), since the prediction errors would become too big after that.

因爲我們使用了100ms的插值推延,所以就算tick 342的snapshot 因爲丟包而遺失的情況之下,也可以正常工作。插值使用的是tick 340 的snapshot 和 tick 344的snapshot。如果連續snapshot中丟失大於一個,那麼歷史緩存的snapshots用盡,插值就不能完美的工作了。這種情況下,渲染邏輯將使用推斷(cl_extrapolate 1【個人推測】 cl_extrapolate = 1 是Source引擎使能推斷從功能的開關),根據目前已知的歷史,進行一個線性的推斷。但是推斷只持續0.25s(cl_extrapolate_amount),更長時間的推斷將會使得偏差變得太大。

Paragraph 4

Entity interpolation causes a constant view “lag” of 100 milliseconds by default (cl_interp 0.1), even if you’re playing on a listenserver (server and client on the same machine). This doesn’t mean you have to lead your aiming when shooting at other players since the server-side lag compensation knows about client entity interpolation and corrects this error.

實例插值引起一個默認恆定100ms(cl_interp 0.1)的“延遲”,即使使用監聽服務器(客戶端和服務器是同一臺機器),也是同樣。這並不意味着玩家需要在設計的時候進行預瞄準,因爲服務器端知曉客戶端的實例插值,進行滯後補償來修正這個錯誤。

Tip: More recent Source games have the cl_interp_ratio cvar. With this you can easily and safely decrease the interpolation period by setting cl_interp to 0, then increasing the value of cl_updaterate (the useful limit of which depends on server tickrate). You can check your final lerp with net_graph 1.

Tips: 最近很多使用Source的遊戲支持cl_interp_ratio。這樣你可以安全簡單的設置 cl_interp到0,來減少插補週期(延遲的時間),然後增加cl_updaterate(上限取決於服務器的tickrate) 。你可以使用net_graph 1來查看最終插值週期。

Note: If you turn on sv_showhitboxes (not available in Source 2009) you will see player hitboxes drawn in server time, meaning they are ahead of the rendered player model by the lerp period. This is perfectly normal!

Note:如果你打開了sv_showhitboxes(Source 2009並不支持),你可以看到以服務器時間繪製的玩家有效射擊區,可以看到他們(繪製的有效射擊區)在玩家繪製模型的前面,因爲有插值的存在,這是完全正確的。



客戶端輸入預測 Input prediction

Paragraph 1

Lets assume a player has a network latency of 150 milliseconds and starts to move forward. The information that the +FORWARD key is pressed is stored in a user command and send to the server. There the user command is processed by the movement code and the player’s character is moved forward in the game world. This world state change is transmitted to all clients with the next snapshot update. So the player would see his own change of movement with a 150 milliseconds delay after he started walking. This delay applies to all players actions like movement, shooting weapons, etc. and becomes worse with higher latencies.

我們假設玩家有150ms的網絡延遲,並且向面向方向移動。這個玩家的 “forward 鍵值被按下”的消息被填充到玩家指令當中,並且發送給服務器。在服務器端,用戶指令由移動代碼處理,玩家的角色在模擬的遊戲世界裏向前移動。在下一個snapshot更新的時候,將這個世界所發生的狀態變化,傳送給所有的客戶端。所以,玩家可以在自己開始移動的150ms延遲後,見到自己的移動變化。這種延遲對於玩家的行走、武器射擊等行動都是存在的,而且對於高延遲的玩家,延遲更爲嚴重。

Paragraph 2

A delay between player input and corresponding visual feedback creates a strange, unnatural feeling and makes it hard to move or aim precisely. Client-side input prediction (cl_predict 1) is a way to remove this delay and let the player’s actions feel more instant. Instead of waiting for the server to update your own position, the local client just predicts the results of its own user commands. Therefore, the client runs exactly the same code and rules the server will use to process the user commands. After the prediction is finished, the local player will move instantly to the new location while the server still sees him at the old place.

這種玩家輸入與相應視覺反饋的延遲感,造成一種奇怪、不自然的感受,並且給移動和精準瞄準造成了難度。客戶端的一側可以使用輸入預測法(cl_predict 1) 來消除這個延遲,讓玩家的行爲反饋感覺更即刻。不同於等待服務器的更新來更新自己的位置,客戶端本地可以預測自己的命令結果。所以,客戶端要與服務器使用同樣的代碼和規則來處理用戶指令。預測完成後,玩家本地將會看到角色直接移動到了新的位置,而服務器上的玩家依舊在老的地方(玩家命令執行前)。

Paragraph 3

After 150 milliseconds, the client will receive the server snapshot that contains the changes based on the user command he predicted earlier. Then the client compares the server position with his predicted position. If they are different, a prediction error has occurred. This indicates that the client didn’t have the correct information about other entities and the environment when it processed the user command. Then the client has to correct its own position, since the server has final authority over client-side prediction. If cl_showerror 1 is turned on, clients can see when prediction errors happen. Prediction error correction can be quite noticeable and may cause the client’s view to jump erratically. By gradually correcting this error over a short amount of time (cl_smoothtime), errors can be smoothly corrected. Prediction error smoothing can be turned off with cl_smooth 0.

在150ms以後,客戶端將收到服務器發送的,包含了剛纔進行預測用戶指令運行結果的snapshot。 收到後,客戶端將自己的預測結果與服務器結果做對比。如果不同,那麼就是發生了預測錯誤。這是因爲,客戶端並沒有持有當前(預測Commond運行情況的時刻)遊戲世界中的實例信息、環境信息。這種情況,客戶端需要修正自己的位置,服務器的執行結果的優先級是高於客戶端自己預測結果的。如果cl_showerror置爲1(開關打開),客戶端將會看到預測錯誤的信息。預測錯誤的修正,會十分顯眼,並且可能會引起畫面的跳躍。想要平滑的修復預測錯誤,可以使用一小段時間(cl_smoothtime【個人推測】 設置平滑修復的時長)逐步來修正。平滑修正可以通過cl_smooth設置爲0來關閉。

Paragraph 4

Prediction is only possible for the local player and entities affected only by him, since prediction works by using the client’s keypresses to make a “best guess” of where the player will end up. Predicting other players would require literally predicting the future with no data, since there’s no way to instantaneously get keypresses from them.
因爲客戶端預測這個行爲,是使用客戶端的鍵位輸入做一個“最佳猜測”來決定玩家的結束時的位置, 預測僅僅對玩家本身以及玩家影響的實例纔可行。對於獲取不到當前按鍵信息的其他玩家,沒有這些數據,是不可能實現預測的。

寫在後面

第一篇:【翻譯搬運】Source引擎多人模式網絡同步模型(Source Multiplayer Networking)【一】
第三篇:【翻譯搬運】Source引擎多人模式網絡同步模型(Source Multiplayer Networking)【三】

歡迎糾錯

轉載請註明,出自喵喵丸的博客 http://blog.csdn.net/u011643833/article/details/77848012

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章