快節奏的多人遊戲同步 - Part 3

在這個系列的第一篇文章中,我們介紹了權威服務器和其在防客戶端作弊方面的用處。然而考慮到可玩性和反饋機制簡單的應用這種技術也會帶來相當大的問題。在第二篇文章中,我們提出了用客戶端預演的方式來規避這些問題的方法。

在這兩篇文章中的整套概念和技術只是允許玩家像在單機遊戲中控制角色那樣來操作,儘管是在一個存在網絡連接延遲的連接了權威服務器的情況下。

在這篇文章中,我們將探索當有其他玩家連接在同一個服務器時的結果。

服務器的時間步

前文中,我們所描述的服務器行爲非常簡單——讀取客戶端輸入信息,更新遊戲狀態,回傳客戶端。當多客戶端連接時,主服務器的循環就會產生些許的不同了。

這種情景下,多個客戶的可能同時發送輸入信息,並且是以一種快節奏的形式。(同玩家發出指令的速度一樣快,可能是按下方向鍵,移動鼠標或點擊屏幕)。實時更新每個客戶端發送的輸入指令並廣播其遊戲狀態將會消耗太多cpu和帶寬。

更好的處理方式是將客戶端的輸入指令安卓其接收先後順序進行排列,先不處理。而遊戲世界則以一種低頻的方式週期性的進行同步,例如:每秒10次。在這種情況下,每次更新的延遲時間爲100ms,這就是所謂的服務器時間步。在每一次更新循環迭代中,所有沒處理的客戶端輸入指令都已應用(可能在一個小於時間步的增量時間內,來保證物理上更可預測),同時新的遊戲狀態會廣播至這些客戶端。

總之,遊戲世界的更新是獨立於存在的客戶端輸入指令以外的,以一種可預估的方式。

處理低頻更新

從客戶端視角來看,這種方式和之前一樣平滑——客戶端預演獨立於更新延遲以外,所以很明顯也是在預期中進行的,只要狀態更新相對較少。然而,由於遊戲狀態是以一種低頻的方式進行廣播的(繼續之前的例子,每100ms),客戶端只得到很少關於其他可能穿行於這個世界的其他實例的信息。

首先實現的是在收到遊戲狀態廣播後同步其他角色的位置,這馬上帶來劇烈的運動,那就是各個單位每100ms跳一次位置,而不是平滑的移動。

wKiom1ilt5DD1uwkAACfpevkX3A342.png-wh_50

 客戶端2眼中的客戶端1


根據你所開發的遊戲類型不同,有很多的方法來處理這個問題;通常來說,你的遊戲越具備可預測性,就越容易處理。

航位推測法

假設你在製作一款賽車遊戲,一輛賽車的行進就非常好預測——比如,它以每秒100米的速度行駛,那麼1秒後他就會出現在前方大概100米處。

爲什麼是“大概”?這一秒鐘中,車輛可能加速或減速了一點,或向左向右轉向了一點——關鍵詞是“一點”。不考慮玩家真實操作,高速情況下其所處位置的可操作性取決於其當前位置、速度和方向,換言之,賽車不會出現馬上掉頭的情況。


那麼在一個服務器更新間隔爲100ms的環境下,它將如何運作呢?客戶端接收到每輛賽車的權威速度和行進方向,在接下來的100ms中,客戶端不會接收到任何新信息,但仍然需要顯示他們的行駛狀態。最簡單的情況就是客戶端假設在接下來的100ms中車輛的行進方向和加速度會保持不變,並在這種參數下本地去運行車輛的物理系統。接着,100ms之後當服務器的更新消息到達時,正車輛的位置信息得以修正。

這種修正可能很大也可能在衆多依賴因素中相對較小。如果玩家確實保持車輛沿直線勻速行駛,那麼預演位置將幾乎與修正位置一致。另一種情況,如果玩家撞到了什麼東西,那麼預演位置則將大錯特錯。

注意,航位推測法可以在慢節奏的環境中應用——如戰艦。事實上,“航位推測法”這個詞組就是來源於海軍術語的。

實例插值

某些環境下航位推測法完全無法應用,最突出的例子就是,所有情境下玩家的方向和速度都是實時可變的。再比如,一個3d射手,玩家經常使用跑步,停止和高速轉向,這使得航位推測法基本失效了,因爲位置和速度信息無法從先前的數據中推測出來。

你不能只在權威服務器下發時更新玩家位置信息,否則你將看到一個每100ms進行一次短距離傳送的玩家,這就毀了遊戲體驗。

你擁有的只有每100ms得到的權威位置數據,而策略是如何表現角色在這期間的行爲。解決這個問題的關鍵點在於相對於當前玩家的角色來說,去顯示其他玩家的過去形態。

也就是說,你在第1秒鐘時所接收到的位置信息,其實你已經在第900ms時收到了,因此你知道角色在第900ms和1秒鐘時都處於什麼位置。那麼從第1秒到第1100ms,你的遊戲顯示了從第900ms到第1秒時其他角色都做了什麼。這種方法你可以一直顯示角色的實際行爲數據,而不是在100ms之後再顯示它。

wKioL1ilt8LhHk6tAACjkAVws7g520.png-wh_50

 客戶端2呈現出“過去的”客戶端1,用最後獲得的位置信息進行插值


從900ms到1秒時你所使用的插值位置信息取決於不同遊戲。通常插值法工作相當良好。如果不行,那麼你可以通過提高服務器每次發送的細節行爲信息——例如,接下來玩家成序列的連續片段,或者每10ms進行一次位置採樣,這樣進行插值後的效果將更好(不用再發送10次更多其他信息,因爲你將發送很多細微的位移變化,在這種特定情況下線上的效果將被極大的優化。)

注意,使用這種技術,每個玩家看到的遊戲世界都將呈現出細微的差別,因爲每個玩家會看到現時的自己和過去的其他實例。即使對於快節奏遊戲來說,看到100ms前的其他實例這件事也不是輕易能夠察覺的。

也有例外——當你需要大量立體的和臨時性的精確信息,比如玩家射擊擊中其他玩家。由於所見的其他玩家是過去時,你的瞄準會有100ms的延遲——也就是說,你所擊中的位置是你目標100ms前所處的位置!我們將在下一篇文章中處理這個問題。

小結:

在有權威服務器的客戶端——服務器架構中,低頻率的更新和網絡延遲情況下,你必須給玩家一種連續的平滑運動的假象。在本系列第二篇文章中,我們探究了一種使用客戶端預演和服務器調節來顯示玩家實時控制角色行爲的方法;這保證了用戶的操作能夠在本地角色上體現出即時效果,規避了延遲對遊戲表現帶來的低可玩性問題。

但無論如何其他實例仍然是個問題。這篇文章中,我們探究了2種解決方案。

第一個,航位推測法,應用在定情況下模擬實例位置,前提是其位置、速度和加速度情況的可預知性在可接受的範圍內。當條件達不到上述情況時,這種方案將無法生效。

第二個,實例插值法,完全不去預測未來的位置——只使用由服務器提供的真實的實例信息,從而呈現稍微延遲過的其他實例。

其淨效果是用戶看到自己的現時,而看到其他實例的過去。這通常可以製造一種天衣無縫的體驗。

然而,仍然沒有得到解決的是,這種假象在高度立體和臨時性的精確事件面前崩塌了,比如射擊一個移動目標,在客戶端2上呈現出的客戶端1的位置和服務器以及客戶端1上的位置都不匹配,這就導致了“爆頭”成爲了不可能!由於沒有幾個遊戲完全沒有“爆頭”(意旨類似於爆頭的關鍵性事件),我們將在下一篇文章中處理這個問題。


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