帧同步
【幀同步】
1、RTS游戲有很多,比如我們都玩過(guò)的的Warcraft III(大家耳熟能詳?shù)?code class="highlighter-rouge">Dota是它的一張地圖)和StarCraft,還有EA的代表作命令與征服系列(Command & Conquer)等等,以及現(xiàn)在非常流行的Dota2和LOL。
早期廣泛在RTS(即時(shí)策略)游戲中應(yīng)用的同步機(jī)制——Lockstep。
那么為什么要強(qiáng)調(diào)早期呢?因?yàn)?code class="highlighter-rouge">Dota2和LOL等新興的游戲使用的同步機(jī)制不再是傳統(tǒng)的Lockstep了。嚴(yán)格來(lái)說(shuō),Warcraft和現(xiàn)在意義上的網(wǎng)游有很大區(qū)別,因?yàn)樗^的網(wǎng)是局域網(wǎng)(LAN)。早期RTS游戲出現(xiàn)時(shí)互聯(lián)網(wǎng)還沒(méi)有現(xiàn)在那么普及,網(wǎng)速也很慢,更沒(méi)有什么像樣的網(wǎng)游,能夠支持局域網(wǎng)對(duì)戰(zhàn)已經(jīng)很不錯(cuò)了。
有人可能會(huì)有疑問(wèn),我們平時(shí)經(jīng)常在對(duì)戰(zhàn)平臺(tái)上和全國(guó)各地的人打Dota,你為什么說(shuō)Warcraft III只支持局域網(wǎng)呢?這又是一個(gè)很有意思的話題,實(shí)際上,對(duì)戰(zhàn)平臺(tái)使用了虛擬局域網(wǎng)(VLAN)技術(shù),通過(guò)進(jìn)程注入,HOOKWinSock函數(shù)調(diào)用,將數(shù)據(jù)包發(fā)送到對(duì)戰(zhàn)平臺(tái)服務(wù)器上,由服務(wù)器分配虛擬IP,這里還能夠進(jìn)行天梯匹配等等,在隨后的游戲過(guò)程中游戲數(shù)據(jù)包都是通過(guò)對(duì)戰(zhàn)平臺(tái)的服務(wù)器進(jìn)行轉(zhuǎn)發(fā),但是這一切對(duì)Warcraft III進(jìn)程本身來(lái)說(shuō)是透明的,它依然感覺(jué)自己在一個(gè)局域網(wǎng)環(huán)境中。
Lockstep中會(huì)不會(huì)出現(xiàn)延遲導(dǎo)致的不一致問(wèn)題?顯然不會(huì),使用Lockstep的游戲是嚴(yán)格按照turn向前推進(jìn)的,如果有人延遲比較高,其他玩家必須等待該玩家跟上之后再繼續(xù)計(jì)算,不存在某個(gè)玩家領(lǐng)先或落后其他玩家若干個(gè)turn的情況。使用Lockstep同步機(jī)制的游戲中,每個(gè)玩家的延遲都等于延遲最高的那個(gè)人。
Lockstep是非常嚴(yán)格的,要求每一步的的計(jì)算結(jié)果都完全一樣,任何計(jì)算錯(cuò)誤都有可能導(dǎo)致蝴蝶效應(yīng),產(chǎn)生嚴(yán)重的后果,因?yàn)闋顟B(tài)不能同步的話游戲根本就沒(méi)有辦法進(jìn)行下去,最終將崩潰退出。
2、追幀時(shí),表現(xiàn)層應(yīng)當(dāng)一幀一幀依次快速播放,就像邏輯怪一幀一幀快速計(jì)算一樣,而不能直接從當(dāng)前幀狀態(tài)插值到最終幀狀態(tài)。
例如下圖,F(xiàn)1->F2->F3,F(xiàn)1幀時(shí)在A位置,F(xiàn)2幀時(shí)到B位置,F(xiàn)3幀時(shí)到C位置。如果F1幀過(guò)了很長(zhǎng)時(shí)間同時(shí)收到F2和F3包,如果表現(xiàn)層直接從F1狀態(tài)A位置插值到F3狀態(tài)的C位置,則會(huì)穿越中間的黑色障礙物。好的解決方法是表現(xiàn)層也采用追幀模式,快速播放。
3、隨機(jī)問(wèn)題
Dota中有許多問(wèn)題是與概率相關(guān)的,比如整點(diǎn)時(shí)野怪是隨機(jī)刷新的,出了水晶劍之后是有概率暴擊的。那么按照Lockstep同步機(jī)制,計(jì)算都是在每個(gè)玩家自己電腦上完成的,那么在有概率存在的情況下,怎么可能保證每臺(tái)電腦的計(jì)算結(jié)果一致呢?!這時(shí)就輪到偽隨機(jī)數(shù)派上用場(chǎng)了。
大部分編程語(yǔ)言內(nèi)置庫(kù)里的隨機(jī)數(shù)都是利用線性同余發(fā)生器產(chǎn)生的,如果不指定隨機(jī)種子(Random Seed),默認(rèn)以當(dāng)前系統(tǒng)時(shí)間戳作為隨機(jī)種子。一旦指定了隨機(jī)種子,那么產(chǎn)生的隨機(jī)數(shù)序列就是確定的。
所以,游戲開(kāi)始前,參與游戲的玩家電腦協(xié)商確定一個(gè)隨機(jī)種子,就可以保證在游戲進(jìn)行過(guò)程中大家產(chǎn)生的隨機(jī)數(shù)序列是相同的,也就可以保證計(jì)算結(jié)果一致。
例如一個(gè)英雄的暴擊率為30%,對(duì)某個(gè)目標(biāo)持續(xù)普攻,如果隨機(jī)數(shù)序列為12 32 90 25,小于等于30判定暴擊,大于30判定不暴擊,那么每個(gè)玩家電腦的計(jì)算結(jié)果都是暴擊 不暴擊 不暴擊 暴擊。
4、udp的可靠性。
我們可以知道udp主要在可靠性上主要是不能保證數(shù)據(jù)包的順序,比如第100個(gè)收到的數(shù)據(jù)包并不一定是第100個(gè)發(fā)出的數(shù)據(jù)包,同時(shí)也無(wú)法保證不丟包,期間有一個(gè)包丟失,udp本是也不會(huì)去校檢。如果這兩個(gè)問(wèn)題解決了,udp的大部分可靠性問(wèn)題也就解決了。
為每個(gè)數(shù)據(jù)包增加序列號(hào),每發(fā)一次包,增加本地序號(hào)。
5、經(jīng)典的 Lockstep 流程如下。
上圖中我們可以明顯看到,這種囚徒模式的幀同步,在第二幀的時(shí)候,因?yàn)橥婕?有延遲,而導(dǎo)致第二幀的同步時(shí)間發(fā)生延遲,從而導(dǎo)致所有玩家都在等待,出現(xiàn)卡頓現(xiàn)象。
6、檢測(cè)同步。
帝國(guó)時(shí)代和最高指揮官會(huì)在每邏輯幀計(jì)算當(dāng)前所有單位的屬性的crc值,幾個(gè)客戶端之間比較這個(gè)crc值,如果發(fā)現(xiàn)不一致,那么就是不同步現(xiàn)象。此時(shí)可以把不同步的客戶端踢出游戲。
7、不公平問(wèn)題。
如果一幀中,輸入無(wú)序,會(huì)導(dǎo)致重大問(wèn)題。如A射擊B,同一幀內(nèi),B也射擊A。
如果先計(jì)算A射擊B,則B死了,A贏了。
如果先計(jì)算B射擊A,則A死了, B贏了。
所以幀同步無(wú)法做到真正的公平。上述情況下,如果處理輸入有序,則A、B必有一方占優(yōu)。
參考:
1、http://bindog.github.io/blog/2015/03/10/synchronization-in-multiplayer-networked-game-lockstep/
2、http://www.sohu.com/a/153269736_163917
3、http://blog.csdn.net/langresser_king/article/details/46756393
總結(jié)
- 上一篇: 骨折多少天走路才能回到原来那样(骨折多少
- 下一篇: 3分钟读懂开关插座怎么装开关插座怎么装?