《魔獸爭霸III》是如何實現野怪同步的?
如果自己要實現多個客戶端的類似單位同步應該怎麼做呢。
你說的魔獸爭霸3是出了冰封王座資料片的暴雪那個魔獸爭霸3嗎?
它的同步機制我還稍微了解一點,但沒有詳細了解,憑記憶稍微說點吧。(如有錯誤請指正,因為我也想學習。)
@vczh 可能玩魔獸玩得少。其實魔獸爭霸3的同步很有意思。說到聯網,必然有一台伺服器(主機)。而遊戲中的種種情況,例如技能判定,野怪行為,電腦AI行為,諸如此類種種,伺服器皆不管,全部交由客戶端自行判定。
因此這點上和一般的網遊不一樣呢。
那主機幹嗎呢?實際上主機只干一個簡單的事情。
當某玩家A用滑鼠選中一個單位,讓他放個技能後。客戶端A首先會向伺服器發一條信息,說,我要放技能吧。伺服器接到這條信息後,會給這個信息定一個時間,如某年某月某日某分某秒,客戶端A放了個技能。然後把這個結果(包括時間戳)廣播給所有客戶端。於是所有客戶端受到了這條廣播(包括最初向伺服器發我要放技能這條信息的客戶端A)。
於是所有的客戶端根據伺服器廣播的信息,分別判定和計算客戶端A的玩家在特定時間放這個技能可能帶來的影響。
特別的,在此過程中,伺服器根本不進行判定,伺服器甚至根本都不知道這局遊戲的地圖長什麼樣子,地圖上有多少個兵。伺服器只做兩件事情:廣播客戶端提交的消息,以及為消息加一個統一的時間戳。
那麼既然伺服器判定都不判定,那麼同一局遊戲為每一個客戶端都可能看到相同的場景呢?(如果你在A的電腦上看到劍聖在開大轉圈圈,那麼在B的電腦、C的電腦上看到的也是劍聖在開大轉圈圈。)
因為每一局遊戲開始的情況是相同的。大家都進同一張地圖,而地圖都是一樣的。因此一局遊戲的初始條件在每一個客戶端上都是一樣的。
而每一個玩家的操作,都會被伺服器統一加一個時間戳並廣播給所有客戶端。因此在每一個客戶端上,任何玩家(包括其他其他客戶端表示的玩家)的任何操作也是一樣的。
因為大家都是玩同一個遊戲,所以技能的判定、野怪(或電腦)AI的判定也是一樣的。
因此,可以明確:對於每一客戶端,初始條件相同 -&> 操作相同 -&> 判定相同 -&> 結果也相同。於是乎,你讓你的劍聖開大轉圈圈,所有人的屏幕上都會看到你的劍聖在開大轉圈圈。但在此過程中,伺服器甚至不需要知道「劍聖「是什麼,他的大招是什麼。伺服器只負責把所有客戶端傳上來的消息蓋個統一的時間戳再廣播出去就行了。
當然還有一點值得一說:遊戲中是有隨機判定的,怎麼保證所有客戶端的隨機判定結果都一致呢?(如果不一致會很麻煩,你的屏幕中劍聖跳劈劈死敵人了,而他屏幕中劍聖只是普通A下被反殺,同一局遊戲同一個劍聖在一個人看來殺死了敵人,另一個人看來已經死了。此時劍聖處於量子疊加態,堪比薛定諤的貓了。)
其實在遊戲開始時,伺服器給每一個客戶端分一個統一的隨機數種子就行了。
OK,所有問題解決。大家終於可以愉快的開一局魔獸3了。不過事先聲明一下,以上結論都是我的推測,我也沒聽過暴雪官方有說過什麼。如果有誰有權威的解釋,方便的話在答案中AT下我咯。
另外,這麼做不怕客戶端作弊嗎?嗯,得分什麼作弊。如果是開圖這種紳士作弊行為,這種機制是避免不了的。但如果是無敵、秒殺、改錢這種流氓作弊行為,這種機制根本不怕。
因為無敵、秒殺、改錢必須有個合理的理由,例如喝無敵藥水,提升攻擊秒殺等。平白無故的無敵和秒殺敵人的消息,你要怎麼發給伺服器,而且令伺服器乖乖廣播給其他客戶端?換句話說,如果客戶端外掛令玩家可以平白無故無敵秒殺,那麼會發生什麼。
想像一下這麼一個場景,一個劍聖平白無故暴擊率100%攻擊力1W,於是到處跳劈殺得敵人屁滾尿流。於是作弊玩家看著心裡那個爽。但是劍聖平白無故變強這一結果無法廣播給其他客戶端,於是其他客戶端那裡,劍聖只是個戰五渣還到處追人砍,然後一遍一遍被別人秒。
於是作弊玩家更像是陷入了某種幻境中,以為自己叼炸天,其實自己就一戰五渣。被別人血虐自己還不知道呢。
(不過實際情況開這種外掛的玩家早因為數據不同步彈出遊戲了。)
順便提點推論的依據:
1、dota不可以斷線重連,LOL可以。
2、魔獸3的錄像只能快進,不能跳過。3、魔獸3外怪可以開地圖,即看見隱身單位和視野之外的單位,但不允許攻擊。
------------少許補充-------------- @鍾三鳴 提及了GetLocalPlayer函數,這是暴雪開發的腳本語言JASS可調用的一個函數。這個函數的存在以及利用這個函數可以實現的一些有趣效果,可以作為我以上言論的鐵證。不過這裡涉及到魔獸地圖製作的一些知識,以後有機會展開討論吧。早期rts 基本採用的都是p2p 點對點架構的lockstep 模型
具體實現可以看 帝國時代2的一篇論文
這類架構裡面所有客戶端是平等的,沒有伺服器 客戶端的概念
遊戲同步核心概念兩個時間同步和空間同步時間同步
所有客戶端互相發送報文,每隔100ms 發送一次
,遊戲有個模擬幀概念,100ms一幀大家互相同步當前的幀編號只有所有人取得一致,幀號才會加一這樣就保證了時間同步大家互相發送的報文,只包括玩家的操作命令,而玩家的操作命令都是按照幀來發送廣播的
例如 玩家操作生產一個農民,那麼就會發出一個報文 操作建築物在幀101,開始生產農民所有玩家都在第101幀的時候,執行生產命令
因為網路有延遲,通常你操作的時候,時間是第51幀,但程序實際上會調度,在第52幀才執行命令,這樣才能保證大家都在未來執行你所發出的命令
所有遊戲代碼還有一個重要特性,確定性,即給定確定的輸入,和當前狀態,計算的未來狀態是確定的
也就是邏輯模擬層不能有任何的隨機因素
這個通常需要偽隨機數,定點數學運算,網路幀,等基礎設施來保證 代碼的確定性可以參考 lol 拳頭 公司的一篇文章,如何保證lol的確定性這種架構最大的問題就是操作延遲比較大,因為你當前的操作命令都是在下一幀,或者幾幀之後才開始執行的
而為了保證代碼確定性,編程難度也很大
一旦出現不同步,遊戲就可能走向不同的未來遊戲也不能中間加人,因為沒有辦法狀態同步,只能從初始狀態,開始執行命令,進行驗算到當前狀態
剛才說的空間同步就是靠代碼的確定性來保證的
除了p2p的 lockstep方法外,還有基於伺服器客戶端的架構,這種架構,由伺服器確定每個幀的每個實體狀態,接著將實體狀態廣播給所有客戶端
伺服器可以調度在某一幀開始執行某個命令,廣播這個調度給所有客戶端而客戶端不需要保證確定性,可以通過定期狀態同步,來修正客戶端狀態,而一些決策性狀態,通常是伺服器廣播的,例如被擊打死亡
有些狀態伺服器總是比客戶端快一些的這就需要客戶端有預測能力,而伺服器也需要將客戶端發送的命令修正到合適的時機執行
這種架構操作反饋比較好
但是狀態同步報文會比較多犧牲操作反饋可以降低運算量和網路量
無論是lockstep還是狀態同步,都需要掩蓋 操作反饋時間,這個通常通過提前動畫或者特效來掩蓋,或者通過幀錯位執行
最近在做這方面研究,等完美了開源一個遊戲中的網路同步機制——Lockstep · 寂寞的賓狗
大家的隨機種子是一樣的。。
應該和輪子哥說的類似,聯機的時候會自動選一台計算機作為伺服器,然後最新信息從這台伺服器發出其他機器接收。也就是說信息同步是在這台機器上做的。
如果你的機器沒被選成伺服器,那麼你的機器卡了,野怪看著不動,但是等你不卡了,進來再看,自己也會被打掉血,因為主機還在愉快的觸發著野怪的攻擊。
如果你的是伺服器,恰好卡了,那麼你是沒事的。最多就是看到屏幕上有些字,「主機你個sx在幹啥」「趕緊把迅雷關了啊」「玩遊戲還下什麼毛片啊」「不行把qq也關了」
通常建主機的那個人會被選為伺服器,這個人掉了選下一個。
LockStep機制
推薦閱讀:
※伺服器被 DDos 攻擊就沒有有效的處理方法嗎?
※如何在linux伺服器上用 PHP 執行 python 腳本?
※linux下配的ftp伺服器埠僅僅開21,20埠還不夠?
※在Windows中,選擇TCP/IPv4協議設置中的」自動獲取DNS伺服器地址「,計算機究竟做了什麼?
※中國能否在未來擁有根伺服器?