大多數實時網路遊戲,將 server 的時間和 client 的時間校對一致是可以帶來許多其他系統設計上的便利的。這裡說的對時,並非去調整 client 的 os 中的時鐘,而是把 game client 內部的邏輯時間調整跟 server 一致即可。
乙個粗略的對時方案可以是這樣的,client 發乙個資料報給 server,裡面記錄下傳送時刻。server 收到後,立刻給這個資料報新增乙個server 當前時刻資訊,併發還給 client 。因為大部分情況下,game server 不會立刻處理這個包,所以,可以在處理時再加乙個時刻。兩者相減,client 可以算得包在 server 內部耽擱時間。
client 收到 server 發還的對時包時,因為他可以取出當初傳送時自己附加的時刻資訊,並知道當前時刻,也就可以算出這個資料報來回的行程時間。這裡,我們假定資料報來回時間想同,那麼把 server 通知的時間,加上行程時間的一半,則可以將 client 時間和 server 時間校對一致。
這個過程用 udp 協議做比用 tcp 協議來的好。因為 tcp 協議可能因為丟包重發引起教大誤差,而 udp 則是自己控制,這個誤差要小的多。只是,現在網路遊戲用 tcp 協議實現要比 udp 有優勢的多,我們也不必為對時另起一套協議走 udp 。
一般的解決方法用多次校對就可以了。因為,如果雙方時鐘快慢一致的情況下,對時包在網路上行程時間越短,就一定表明誤差越小。這個誤差是不會超過包來回時間的一半的。我們一旦在對時過程中得到乙個很小的行程時間,並在我們遊戲邏輯的時間誤差允許範圍內,就不需要再校對了。
或者校對多次,發現網路比較穩定(雖然網速很慢),也可以認為校對準確。這種情況下,潛在的時間誤差可能比較大。好在,一般,我們在時間敏感的包上都會攜帶時間戳。當雙方時間校對誤差很小的時候,client 發過來的時間戳是不應該早於 server 真實時刻的。(當時間校對準確後,server 收到的包上的時間戳加上資料報單行時間,應該等於 server 當前時刻)
一旦 server 發現 client 的包「提前」收到了,只有一種解釋:當初校對時間時糟糕的網路狀態帶來了很多的時間誤差,而現在的網路狀態要明顯優於那個時候。這時,server 應該勒令 client 重新對時。同理,client 發現 server 的資料報「提前」到達,也可以主動向 server 重新對時。
乙個良好的對時協議的設定,在協議上避免 client 時間作弊(比如加速器,或者減速器)是可行的。這裡不討論也不分析更高階的利用遊戲邏輯去時間作弊的方式,我們給資料報打上時間戳的主要目的也非防止時間作弊。
校對時間的一般通途是用來實現更流暢的戰鬥系統和位置同步。因為不依賴網路傳輸的統一時間參照標準可以使遊戲看起來更為實時。
首先談談位置同步。
好的位置同步一定要考慮網路延遲的影響,所以,簡單把 entity 的座標廣播到 clients 不是乙個好的方案。我們應該同步的是乙個運動向量以及時間資訊。既,無論是 client 還是 server ,發出和收到的資訊都應該是每個 entity 在某個時刻的位置和運動方向。這樣,接收方可以根據收到的時刻,估算出 entity 的真實位置。對於 server 一方的處理,只要要求 client 按乙個頻率(一般來說戰鬥時 10hz 即可,而非戰鬥狀態或 player 不改變運動狀態時可以更低) 給它傳送位置資訊。server 可以在網路狀態不好的情況下依據最近收到的包估算出現在 player 位置。而 client 發出的每次 player 位置資訊,都應該被 server 信任,用來去修正上次的估算值。而 server 要做的只是抽查,或交給另乙個模組去校驗資料報的合法性(防止作弊)。
在 server 端,每個 entity 的位置按 10hz 的頻率做離散運動即可。
client 因為涉及顯示問題,玩家希望看到的是 entity 的連續運動,所以處理起來麻煩一點。server 發過來的位置同步資訊也可能因為網路延遲晚收到。client 同樣根據最近收到的包做估算,但是再收到的包和之前已經收到的資訊估算結果不同的時候,應該做的是運動方向和速度的修正,盡可能的讓下次的估算更準確。
關於戰鬥指令同步,我希望是給所有戰鬥指令都加上冷卻時間和引導時間,這正是 wow 的設計。這樣,信任 client 的時間戳,就可以得到 client 準確的指令下達時間。引導時間(或者是公共冷卻時間)可以充當網路延遲時間的緩衝。當然我們現在的設計會更複雜一些,這裡不再列出。對於距離敏感的技能,例如遠端攻擊和範圍魔法,我們的設計是有乙個模糊的 miss 判定公式,解決距離邊界的判定問題。
這裡, server 對攻擊目標的位置做估算的時候,可以不按上次發出包的運動方向去做位置估計,而選擇用最有利於被攻擊者的運動方向來做。這樣,可以減少網路狀況差的玩家的劣勢。
對於 pve 的戰鬥,甚至可以做更多的取捨,達到遊戲流暢的效果。比如乙個網路狀態差的玩家去打 npc,他攻擊 npc 的時刻,npc 是處於攻擊範圍之內的。但是由於網路延遲,資料報被 server 收到的時候,npc 已經離開。這個時候 server 可以以 client 的邏輯來將 npc 拉會原來的座標。
雖然,這樣做,可能會引起其他玩家(旁觀者) client 上表現的不同。但是,網路遊戲很多情況下是不需要嚴格同步的。在不影響主要遊戲邏輯的情況下,player 的手感更為重要。
雲風 提交於 april 15, 2006 10:37 pm
|固定鏈結
如果你想引用這篇文章,請複製下面的鏈結傳送引用通告(gbk)
好文! 對我的工作很有幫助!謝謝!
posted by: linker m lin | march 8, 2007 12:19 pm
網遊並不需要這麼嚴格的對時吧,一直都讓客戶端比伺服器端慢一定的幀數就行了。至於戰鬥指令,完全可以認為是伺服器收到時刻發出的,對網路時延做補償意義不大,特別是對wow這樣的慢節奏來說。250ms以下的延時,完全可以忽略;再高,應該是isp的問題,而不是程式設計師的了。至於位置同步,我看最重要的不是處理時延,而是廣播占用的頻寬,o(n^2)的複雜度,膨脹起來可是非常嚇人的。wow裡一攻打堡伺服器就down,上次aql開門客戶端下行資料有50kb/s,一千個玩家就有50mb/s啊,就是400mb/s。
posted by: 用屁股思考的豬 | april 23, 2006 03:43 pm
呃..犯了個常識錯誤。呵呵。
在複雜的網路環境下同步的確很困難。 :) 你的文章對我作web應用也有點啟發。
posted by: felix | april 18, 2006 05:22 pm
可見cs的時間同步比較精確了一顆子彈耽誤了時間kill可不了土匪了
posted by: ninstein | april 18, 2006 11:03 am
這要看怎樣定義通訊協議,長度資訊是乙個冗餘資訊,如果有利於設計那麼可以選擇保留。但是並非所有的設計都需要這個來降低耦合性。正如你說,"一般我們使用乙個網路層來接收資料報,由他來劃分包的邊界",這個只是一般的設計。完全可能存在另一種設計把型別的初步解析放在同乙個層次,而並不會增加這個層次的規模。
我的意思是,在設計基於 tcp 的通訊協議的時候不應該有教條。
posted by: cloud
| april 17, 2006 06:58 pm
posted by: 托尼 | april 17, 2006 05:59 pm
npc 逃掉不是由 client 做的,是由 server 做的。client 只是收到比較晚。
這裡說的是一種 server 在可以選擇的情況下把時間回退,而非讓 client 參於運算。真正處理時有很多東西要考慮,不想展開討論。
posted by: cloud
| april 16, 2006 07:33 pm
雲風你好:我是武漢大學的學生,和你也是老鄉了:)
我即將去北歐讀碩士,有2個不同的專業供選擇,想徵求你的建議。
我本人對internet技術最感興趣,以下2個專業都是與此相關的,但方向不同。
乙個是赫爾辛基理工大學的mobile computing-service and security專業,課程描述的**是http://www.tkk.fi/units/cse/studies/master/studies/mobile_courses.html
另乙個是瑞典皇家工學院的分布式系統專業,課程描述在http://www.imit.kth.se/seds/courses.html
這些課程描述幾分鐘內就可以瀏覽一遍,希望能聽聽你對這2個專業的簡要分析,十分感謝!
posted by: rabbitrun84 | april 16, 2006 06:01 pm
後面乙個是wow常見的問題:由於網路延遲,client端的npc已經逃跑掉,但server端沒收到相應的資訊。如果是1個client這個問題還好辦,但如果有n個client組成隊伍,同步就比較麻煩了,如果有更多的人組成團隊,這個問題就更嚴重了。。
posted by: felix | april 16, 2006 12:30 pm
恩...對我做外掛程式有點幫助...
posted by: anonymous | april 16, 2006 11:30 am
對於 pve 的戰鬥,甚至可以做更多的取捨,達到遊戲流暢的效果。比如乙個網路狀態差的玩家去打 npc,他攻擊 npc 的時刻,npc 是處於攻擊範圍之內的。但是由於網路延遲,資料報被 server 收到的時候,npc 已經離開。這個時候 server 可以以 client 的邏輯來將 npc 拉會原來的座標。
我感覺這樣不好,可以考慮使用miss來避開這樣的情況
因為,你這樣可能出現多個玩家拉乙個npc導致都打乙個npc,攻擊判定就更複雜了
posted by: siney | april 15, 2006 11:51
網路遊戲的對時以及同步問題
大多數實時網路遊戲,將 server 的時間和 client 的時間校對一致是可以帶來許多其他系統設計上的便利的。這裡說的對時,並非去調整 client 的 os 中的時鐘,而是把 game client 內部的邏輯時間調整跟 server 一致即可。乙個粗略的對時方案可以是這樣的,client 發...
網路遊戲的對時以及同步問題
大多數實時網路遊戲,將server 的時間和 client 的時間校對一致是可以帶來許多其他系統設計上的便利的。這裡說的對時,並非去調整 client 的os 中的時鐘,而是把 game client 內部的邏輯時間調整跟 server 一致即可。乙個粗略的對時方案可以是這樣的,client 發乙個...
網路遊戲的對時以及同步問題
from 網路遊戲的對時以及同步問題 大多數實時網路遊戲,將 server 的時間和 client 的時間校對一致是可以帶來許多其他系統設計上的便利的。這裡說的對時,並非去調整 client 的 os 中的時鐘,而是把 game client 內部的邏輯時間調整跟 server 一致即可。乙個粗略的...