多人游戲?qū)?zhàn)技術(shù)(坦克大戰(zhàn)爷怀、狀態(tài)同步)

用狀態(tài)同步的方式實現(xiàn)一個坦克大戰(zhàn)的小游戲,這也是一次全新的嘗試带欢,從游戲的效果來看运授,在正常的網(wǎng)絡(luò)速度下效果符合預(yù)期。這里跟大家分享下游戲客戶端中用到的關(guān)鍵技術(shù)點乔煞。

一吁朦、 同步方式的選擇,狀態(tài)同步or 幀同步渡贾?

? 狀態(tài)同步: 同步的是游戲中的各種狀態(tài)逗宜,游戲邏輯由服務(wù)器實現(xiàn),只是將計算后的結(jié)果同步給客戶端空骚,客戶端根據(jù)收到的狀態(tài)纺讲,同步本地的游戲狀態(tài)。

? 實現(xiàn)狀態(tài)同步的一般流程是:

? 客戶端上傳操作至服務(wù)器 ====> 服務(wù)器收到后按固定頻率計算游戲行為的結(jié)果囤屹,然后以廣播的形式以固定頻率下發(fā)至客戶端 ====>客戶端根據(jù)收到的狀態(tài)熬甚,渲染游戲畫面

? 值得注意的是,狀態(tài)同步是一種不嚴謹?shù)耐?/strong>肋坚,只是保證了各種狀態(tài)的一致性乡括,并不能保證各客戶端在同一時刻顯示同樣的畫面。比如子彈擊中坦克智厌,那么狀態(tài)同步能保證子彈確實擊中了坦克粟判,但有可能有的客戶端先看到擊中的畫面,有的客戶端后看到峦剔。所以狀態(tài)同步對網(wǎng)絡(luò)的要求不高档礁。還有一點,服務(wù)器實現(xiàn)游戲邏輯的計算吝沫,安全性相對客戶端實現(xiàn)游戲邏輯計算高很多呻澜。

? 幀同步: 同步的是操作指令,指令包含當(dāng)前的幀索引惨险「遥客戶端上傳指令至服務(wù)器,服務(wù)器通過廣播下發(fā)至每個客戶端辫愉, 客戶端再根據(jù)指令栅受,本地計算游戲邏輯并進行渲染。幀同步確保服務(wù)器每幀下發(fā)的指令是一致的。如果出現(xiàn)網(wǎng)絡(luò)不好的情況屏镊,導(dǎo)致幀在本地積壓依疼,或者客戶端同時收到多個幀信息,則選擇加快速度渲染而芥,或者直接跳至最新的一幀(不建議律罢,除非斷線重連)。

? 實現(xiàn)幀同步的一般流程是:

? 同步隨機數(shù)種 (用于游戲中暴擊等計算) ====> 客戶端上傳操作指令 ====> 服務(wù)器按固定頻率廣播所有客戶端的操作 ====> 客戶端根據(jù)收到的操作棍丐,進行邏輯運算并渲染游戲畫面

? 嚴格的幀同步每個幀都會等待所有的玩家上傳操作至服務(wù)器后误辑,才會廣播指令至各客戶端,這樣的就能嚴格保證各個玩家的操作是同步的歌逢,但是巾钉,這樣做的壞處也是顯而易見的,這局游戲的網(wǎng)絡(luò)延遲秘案,就是網(wǎng)絡(luò)最差的那個玩家的網(wǎng)絡(luò)延遲睛琳,這樣對網(wǎng)絡(luò)好的玩家顯得不公平,而且游戲的操作手感也不好踏烙。所以延伸出來的樂觀鎖幀同步方式师骗,就是用來保證網(wǎng)絡(luò)好的玩家不受延遲高的玩家的影響。樂觀鎖就是默認在定時器觸發(fā)的那一刻讨惩,所有的玩家操作已經(jīng)上傳辟癌,然后再廣播至各個玩家。對于延遲高的玩家荐捻,會感覺操作延遲黍少,但對于網(wǎng)絡(luò)情況良好的玩家,會感覺很順暢处面。至于說這對于網(wǎng)絡(luò)不好的玩家不公平厂置,只能說網(wǎng)絡(luò)不好就不要玩這種對于網(wǎng)絡(luò)要求高的游戲嘛,當(dāng)然得優(yōu)先保證大多數(shù)玩家的體驗了魂角。

? 對于坦克大戰(zhàn)采用狀態(tài)同步的考量:

? 對于多人在線小游戲來說昵济,其實這兩種同步方式都可以。但考慮到實際應(yīng)用場景野揪,我們還是選擇了狀態(tài)同步访忿。第一、游戲邏輯在服務(wù)端實現(xiàn)斯稳,所以我們更新一款游戲海铆,直接更新服務(wù)端就好了。第二挣惰、對于移動端的網(wǎng)絡(luò)不穩(wěn)定卧斟,所以選擇對網(wǎng)絡(luò)要求稍微低的狀態(tài)同步殴边。

? 對于坦克大戰(zhàn)我們也把一些游戲邏輯交給了客戶端,我們選擇將坦克位置由服務(wù)器廣播至客戶端珍语,而子彈這個不是很關(guān)鍵的信息锤岸,我們是直接將開火指令廣播至客戶端,客戶端直接本地渲染廊酣,直到收到來自服務(wù)器的生命周期結(jié)束的訊息為止(擊中了障礙物)能耻。這部分放到客戶端直接渲染赏枚,是因為像子彈這種類型的元素亡驰,方向跟運動速度不變,除非碰到障礙物消失饿幅。所以凡辱,沒有必要將子彈的信息,也通過服務(wù)端廣播至客戶端栗恩。一個游戲子彈有很多透乾,僅僅附帶位置信息,那也是很占用帶寬的磕秤。其實后續(xù)可以考慮乳乌,子彈生命結(jié)束也由客戶端控制。至于他擊中的物體會怎么樣市咆,這個由服務(wù)端判斷

二汉操、客戶端與服務(wù)器時間的校準(zhǔn)

? 多人對戰(zhàn)游戲,需要一個統(tǒng)一的時間軸來運轉(zhuǎn)整個游戲世界蒙兰。而這個時間軸磷瘤,就是服務(wù)器的時間軸。所以CS之間的時間同步搜变,對整個游戲的運行是至關(guān)重要的采缚。

?

? 服務(wù)端時間 = 客戶端時間 + RTT/2 + difftime

屏幕快照 2018-06-27 上午103446.png

這里t1 為客戶端發(fā)送請求的時間, t2為服務(wù)端收到請求的時間挠他,t3為客戶端收到ack的時間扳抽。則有:

? t3-t1 = RTT

? t1 + RTT/2 + diff = t2

那么根據(jù)以上公式可以算出,客戶端與服務(wù)端的時間差diff.這樣就同步了客戶端與服務(wù)端的時間殖侵。

這里默認客戶端到服務(wù)端的延遲跟服務(wù)端到客戶端的延遲是一樣的摔蓝,可以多做幾次,取平均值愉耙。

?

三贮尉、客戶端的狀態(tài)同步的實現(xiàn)

? 不同于單機游戲,多人對戰(zhàn)游戲需要同步各個客戶端的信息朴沿,因此理論上來說沒法做到像單機游戲那種立即操作立即顯示猜谚“苌埃客戶端的操作需要經(jīng)過服務(wù)端的確認才能顯示。整個過程是這樣的:

屏幕快照.png

? 客戶端上傳至服務(wù)端

屏幕快照 2018-06-27 上午103412.png

? 服務(wù)端廣播至客戶端

? 這里是分開兩個過程魏铅,客戶端的操作不會立即對客戶端渲染產(chǎn)生影響昌犹,可以對比下單機游戲的過程是這樣的:

? 操作 ==> 本地進行游戲邏輯運算 ==> 渲染游戲畫面==>操作 ...

這里的網(wǎng)絡(luò)數(shù)據(jù)包包括 狀態(tài) + 操作 + 服務(wù)端時間, 狀態(tài)包括坦克的位置览芳、方向斜姥、速度, 操作包括坦克開火沧竟、移動铸敏、停止,每發(fā)生一個動作悟泵,就將動作push到隊列里等待發(fā)送杈笔。

? 可以注意到,只有確保服務(wù)端收到一個操作之后糕非,客戶端才會從隊列里取出下一個操作發(fā)送蒙具。如果不用隊列進行緩存,則有可能出現(xiàn)在一個周期內(nèi)發(fā)送多個操作的情況朽肥。

?

四禁筏、客戶端做插值平滑游戲畫面

? 由于服務(wù)端廣播至客戶端的幀為15幀/s, 如果按照這樣的頻率做本地渲染衡招,這樣得到的效果是讓人無法接受的呀打〔肝兀看到的游戲畫面是不連續(xù)的椭懊。也許有人認為視頻25幀/s就已經(jīng)非常流暢了垦缅,那么把服務(wù)端的廣播頻率設(shè)為25幀/s就可以了。其實窘茁,視頻的顯示與游戲的顯示機制是不一樣的怀伦,視頻可以由一幅幅畫連續(xù)播放得到,而這幅畫是由連續(xù)曝光得到山林,所以是一段時間的信息房待,而游戲是直接顯示,就是一個時間點的信息驼抹。所以游戲的幀率太少會讓人覺得很卡桑孩,一頓一頓的。

? 要平滑的顯示游戲畫面框冀,會選擇一個插值的操作流椒。就是基于兩個已知的狀態(tài)做插值,讓本來的兩幀數(shù)據(jù)明也,在渲染的時候宣虾,細分成多幀數(shù)據(jù)惯裕。服務(wù)端廣播幀率為15幀/s, 而本地渲染的是大約60幀/s.我們做個完美的假設(shè)绣硝,假設(shè)收到來自服務(wù)端的數(shù)據(jù)蜻势,倒數(shù)第二幀坦克位置為(X0,Y0); 最新收到的一幀中坦克的位置為(X1,Y1)鹉胖;之間相隔1/15s握玛。由于客戶端幀率是60幀/s, 故理論上可以服務(wù)端的一幀變?yōu)榭蛻舳说乃膸5歉Σぃ瑫l(fā)現(xiàn)由于js是單線程的挠铲,其定時器無法做到完美的定時,js的定時器也是一個坑淑蔚。它每隔dt個時間段市殷,渲染一次游戲畫面愕撰,而dt是小范圍波動的刹衫。所以有:

CodeCogsEqn.gif

? 其中 Xnow 是現(xiàn)在需要渲染的x坐標(biāo)位置,ts是兩個消息自帶的時間戳的差值搞挣,基本為66ms, 而dt的累加永遠要小于等于ts,當(dāng)dt的累加大于ts時带迟,說明渲染時間過長,而坦克的x坐標(biāo)已經(jīng)到達X1的位置了囱桨,因此不需要再移動仓犬,故當(dāng)dt的累加大于ts時做無效處理。

五舍肠、過程中可改進的點

1.傳輸?shù)男畔]有進一步壓縮

? 用的都是json格式搀继,而且玩家的數(shù)目與需要廣播的消息是成線性關(guān)系的,所以需要進一步壓縮翠语,才能更好的支持數(shù)量很多的玩家叽躯。也是節(jié)省玩家流量的一個措施。

2.可以提前渲染一至兩幀的圖像

? 目前是完全根據(jù)服務(wù)端的信息來進行渲染肌括,包括自己操縱的那輛坦克点骑。可以通過客戶端預(yù)測和與服務(wù)端的協(xié)調(diào)谍夭,來提前一兩幀顯示自己操縱的那輛坦克的位置黑滴。為何不走另外一個極端,即馬上操作紧索,馬上得到袁辈?因為這不是單機游戲,需要與服務(wù)器保持一致珠漂,只能提前顯示一至兩幀晚缩,也就是最多提前顯示120ms的畫面葛菇,再多的話就有問題,會導(dǎo)致坦克在服務(wù)端的位置與客戶端的位置相差過大橡羞,進一步導(dǎo)致整個游戲時間的不一致眯停。

3.幾乎同時收到服務(wù)端多個幀的數(shù)據(jù)

? 這個問題在mac 本上出現(xiàn)過,抓包發(fā)現(xiàn)本來間隔66ms的幀數(shù)據(jù)卿泽,有時候會只間隔幾毫秒莺债。這樣導(dǎo)致的現(xiàn)象就是,坦克會一頓一頓签夭,出現(xiàn)閃現(xiàn)齐邦。對于該問題偶然出現(xiàn)會有辦法改進,假如短時間內(nèi)收到3個包第租,那么直接丟棄前兩個包措拇。這樣坦克的畫面會突然加快,但總比閃現(xiàn)效果要好慎宾。如果經(jīng)常出現(xiàn)丐吓,則目前是無解的,客戶端沒收到來自服務(wù)端的幀數(shù)據(jù)趟据,是做等待處理的券犁,看起來是閃現(xiàn)的效果。只能通過提高網(wǎng)絡(luò)質(zhì)量或者網(wǎng)卡設(shè)備來避免這個問題汹碱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末粘衬,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子咳促,更是在濱河造成了極大的恐慌稚新,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件跪腹,死亡現(xiàn)場離奇詭異褂删,居然都是意外死亡,警方通過查閱死者的電腦和手機尺迂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門笤妙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人噪裕,你說我怎么就攤上這事蹲盘。” “怎么了膳音?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵召衔,是天一觀的道長。 經(jīng)常有香客問我祭陷,道長苍凛,這世上最難降的妖魔是什么趣席? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮醇蝴,結(jié)果婚禮上宣肚,老公的妹妹穿的比我還像新娘。我一直安慰自己悠栓,他們只是感情好霉涨,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著惭适,像睡著了一般笙瑟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上癞志,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天往枷,我揣著相機與錄音,去河邊找鬼凄杯。 笑死错洁,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的盾舌。 我是一名探鬼主播墓臭,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蘸鲸,長吁一口氣:“原來是場噩夢啊……” “哼妖谴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起酌摇,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤膝舅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后窑多,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仍稀,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年埂息,在試婚紗的時候發(fā)現(xiàn)自己被綠了技潘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡千康,死狀恐怖享幽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拾弃,我是刑警寧澤值桩,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站豪椿,受9級特大地震影響奔坟,放射性物質(zhì)發(fā)生泄漏携栋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一咳秉、第九天 我趴在偏房一處隱蔽的房頂上張望婉支。 院中可真熱鬧,春花似錦澜建、人聲如沸磅摹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽户誓。三九已至,卻和暖如春幕侠,著一層夾襖步出監(jiān)牢的瞬間帝美,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工晤硕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留悼潭,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓舞箍,卻偏偏與公主長得像舰褪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子疏橄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容