16年年底的時(shí)候我從當(dāng)時(shí)的公司離職,來到了目前任職的一家更專注于游戲開發(fā)的公司。接手的是一個(gè)platform游戲項(xiàng)目,基本情況是之前的團(tuán)隊(duì)完成了第一個(gè)版本,即單人模式的基礎(chǔ)玩法,但是之后對(duì)該項(xiàng)目的定位又變成了一個(gè)本地局域網(wǎng)的聯(lián)機(jī)手游(2-4個(gè)玩家)。因此,重寫項(xiàng)目底層外加確定網(wǎng)絡(luò)同步方案就成了第一件需要去認(rèn)真考慮的事情了。那么本文就來聊聊網(wǎng)絡(luò)同步這件事吧。

游戲同步中的主次

開發(fā)網(wǎng)絡(luò)多人游戲是一件十分有趣的事情,但是和單機(jī)游戲相比無疑增加了更多的挑戰(zhàn)。

例如,我們之前開發(fā)的單機(jī)版本并不需要多么擔(dān)心作弊的問題。這是因?yàn)橘?gòu)買我們游戲的玩家(假如我們的單機(jī)游戲不免費(fèi)發(fā)布的話)即便作弊,影響的也僅僅是他自己的游戲體驗(yàn),不會(huì)影響到別人。

但是開發(fā)多人游戲就不是這樣了,為了保證讓每個(gè)人都有好的游戲體驗(yàn),防止作弊總是需要去考慮的。

除此之外,在開發(fā)多人游戲時(shí)我們還需要考慮如何“欺騙”玩家的眼睛,讓他們認(rèn)為他們?cè)谕粋€(gè)世界中。

當(dāng)2個(gè)或4個(gè)玩家一起在手機(jī)上玩游戲時(shí),看上去他們確實(shí)像是在共享同一個(gè)虛擬世界,在同一個(gè)世界中游玩。但事實(shí)卻是,玩家自己的手機(jī)只是對(duì)“同一個(gè)”虛擬世界的近似模擬。換言之,他們的游戲世界每一個(gè)都是獨(dú)一無二的,只不過從外觀上看起來像。

因此,為了達(dá)到這種看上去近似的效果,我們需要確認(rèn)哪些狀態(tài)是需要同步的,只要同步了這些狀態(tài),這個(gè)游戲世界就看上去一樣了。而哪些狀態(tài)是無需同步的,即這些對(duì)象的狀態(tài)是否同步對(duì)整個(gè)游戲是否看上去一樣并沒有特別大的影響。

在我們的游戲中,玩家的各種屬性、在世界中的坐標(biāo)、游戲世界中的敵人各種屬性、道具獲取以及各種觸發(fā)器的觸發(fā)等等都有可能會(huì)對(duì)游戲的表現(xiàn)產(chǎn)生影響,因此需要考慮同步;但是像例如海底的水泡粒子效果、道具獲取后的碎裂效果,甚至是背景音樂則不會(huì)對(duì)游戲的表現(xiàn)產(chǎn)生特別的影響,因此并沒有必要去同步這些內(nèi)容。

同步輸入or同步狀態(tài)

既然明確了不存在兩個(gè)完全一樣的游戲世界,每個(gè)游戲世界無非都是近似的模擬。那么接下來我們就要來選擇一個(gè)適合的網(wǎng)絡(luò)同步方案以滿足這種需求了。最基本的游戲網(wǎng)絡(luò)同步模型大概可以分為以下4種(畫圖水平一般,見諒):

143450kjoj3zojuo0co3ou.png client-server:專用服務(wù)器
143451p8atsk88tr3seg77.png client-server:玩家之一作為服務(wù)器
143451lmezeddqpe9qdepi.png peer-to-peer
143452derdkxtkozkhovki.png
當(dāng)然,將所有的邏輯放到服務(wù)器并經(jīng)過服務(wù)器的模擬之后再將結(jié)果返回給客戶端的過程會(huì)帶來一些滯后感,當(dāng)玩家對(duì)操作的敏感度要求較高時(shí),這顯然不是一個(gè)很好的解決方案。因此,客戶端的輸入預(yù)測(cè)和服務(wù)端的延遲補(bǔ)償開始得到應(yīng)用。通過在客戶端側(cè)的輸入預(yù)測(cè),可以讓玩家的輸入得到立刻的反饋。而延時(shí)補(bǔ)償則保證了結(jié)果的正確性。這個(gè)過程可以基本概括為以下幾個(gè)階段:

§當(dāng)玩家按下按鈕時(shí),客戶端立刻執(zhí)行相應(yīng)的操作例如開始播放某個(gè)動(dòng)作或是開始移動(dòng)。與此同時(shí),客戶端還會(huì)向服務(wù)器發(fā)送一條包含了時(shí)間戳的消息。

§服務(wù)器經(jīng)過一段延遲后收到了客戶端發(fā)來的按鈕被按下的消息,于是服務(wù)器會(huì)回滾到按鈕被按下的時(shí)刻,在這個(gè)時(shí)刻執(zhí)行按鈕對(duì)應(yīng)操作,之后再重新模擬到當(dāng)前時(shí)刻。

§之后服務(wù)器將當(dāng)前的狀態(tài)同步給客戶端。

§客戶端收到服務(wù)器同步過來的數(shù)據(jù),此時(shí)由于網(wǎng)絡(luò)延遲的緣故,客戶端收到服務(wù)器的消息時(shí)也已經(jīng)過去一段時(shí)間。所以客戶端同樣需要回滾到服務(wù)器發(fā)出消息的時(shí)刻,并根據(jù)服務(wù)器發(fā)送的狀態(tài)來修正自己的狀態(tài)。

雖然這樣做能夠更好的保證玩家的手感,但是我們發(fā)現(xiàn)無論是客戶端還是服務(wù)器,一旦收到消息包之后都需要回滾。而這種回滾機(jī)制相對(duì)來說較為復(fù)雜,并且也不容易在已有的游戲中加入這種機(jī)制。

綜上,我們可以看到在這兩種同步模型中,服務(wù)器獲取客戶端的操作指令并在服務(wù)器內(nèi)模擬整個(gè)游戲世界,之后服務(wù)器是將服務(wù)器所維護(hù)的游戲世界內(nèi)的狀態(tài)同步給各個(gè)客戶端,因此這里主要是做狀態(tài)同步。

Peer to Peer

Peer to Peer點(diǎn)對(duì)點(diǎn)同步模型是一種很經(jīng)典的網(wǎng)絡(luò)游戲網(wǎng)絡(luò)同步模型。帶有幀同步模型的Peer to Peer在很多RTS游戲中得到了大量應(yīng)用,不過在討論幀同步模型之前,我們先來聊聊一般的Peer to Peer。

相對(duì)于C/S模型擁有一個(gè)計(jì)算機(jī)負(fù)責(zé)整個(gè)游戲世界的模擬,Peer to Peer模式并沒有單一的計(jì)算機(jī)來負(fù)責(zé)模擬游戲世界。相反它將對(duì)游戲世界的模擬分配給了所有玩家,因而每個(gè)玩家的客戶端都在模擬著自己的游戲世界。這樣做的一大好處在于玩家的輸入總是立刻響應(yīng)的,我按下一個(gè)按鈕,按鈕造成的結(jié)果便發(fā)生了,同時(shí)我需要做的是將我的操作發(fā)送給和我相連的客戶端,讓他們也去根據(jù)我發(fā)送的操作模擬游戲世界。但是這樣做的一大弊端在于不能保證客戶端看到的游戲畫面是一樣的。

143453cbbe9zmycep08ttm.jpg
例如上圖上方的怪物射出的可以通過畫線來阻擋,但是由于client1和client2都是在模擬自己的游戲世界,因此延遲或是不同移動(dòng)設(shè)備本身的性能問題就有可能會(huì)造成client1的畫線操作同步到client2上時(shí)產(chǎn)生不同的結(jié)果。所以我們發(fā)現(xiàn)只是簡(jiǎn)單的讓每個(gè)客戶端模擬自己游戲世界(就像單機(jī)那樣),同時(shí)簡(jiǎn)單的將操作同步給別的客戶端,至少在同步這個(gè)問題上是不靠譜的。

因此,游戲行業(yè)大多會(huì)采用幀同步模型來保證同步的可靠性。很多早期的RTS游戲都采用了幀同步來作為網(wǎng)絡(luò)同步的方案。至于為什么很多人在介紹幀同步的時(shí)候,都喜歡把早期的RTS游戲搬出來作為一個(gè)例子呢?我想各位看一眼RTS游戲的游戲截圖就能猜到個(gè)大概了。

143454oaia10xg0v551is0.jpg
RTS游戲中常常伴隨著數(shù)十上百甚至上千個(gè)邏輯實(shí)體單位,如果采用狀態(tài)同步的話數(shù)據(jù)量相對(duì)要大很多。但是如果只同步玩家的操作呢?如果每個(gè)客戶端在相同的情況下開始游戲,并且運(yùn)行完全相同的步驟,那么客戶端就可以不通過接收狀態(tài)同步信息就能保證游戲的同步了。

這也是這種模型的一大優(yōu)勢(shì),我們除了發(fā)送玩家的操作之外幾乎不需要再發(fā)送任何數(shù)據(jù)。這種同步輸入的方式可以說非常適合RTS游戲,因?yàn)樗鼈冇心敲炊嗟膯挝?,同步所有單位的狀態(tài)是不容易的。

因此,采用這種模型就可以把游戲的過程分為一個(gè)一個(gè)的回合。游戲的每一步都需要通過網(wǎng)絡(luò)來收集所有玩家的操作輸入,然后再往下執(zhí)行。當(dāng)然,一提到“回合”這個(gè)詞,大家想到往往是所謂的回合制游戲,但事實(shí)上只要回合的頻率足夠快,仍然是可以做出即時(shí)游戲的感覺。

當(dāng)然,由于沒有同步游戲的狀態(tài),而是同步玩家在游戲內(nèi)的輸入操作,因此實(shí)現(xiàn)完全同步還是有一些事情需要注意的。因?yàn)橐坏┮粋€(gè)小小的不同步發(fā)生,就會(huì)產(chǎn)生蝴蝶效應(yīng),從而引起很明顯的不同步。一個(gè)典型的例子便是我以前在開發(fā)一個(gè)戰(zhàn)斗回放系統(tǒng)時(shí),發(fā)現(xiàn)由于一個(gè)士兵在尋路的時(shí)候稍微走到有點(diǎn)不一樣的地方,就導(dǎo)致了一場(chǎng)戰(zhàn)斗的結(jié)果大不相同。

雖然我們目前的項(xiàng)目并沒有采用幀同步的方案,但是還是想和大家分享一點(diǎn)教訓(xùn)。例如不要使用浮點(diǎn)型數(shù)據(jù),這是由于舍入會(huì)造成誤差,所以建議各位使用整形數(shù)據(jù)。同樣,另一個(gè)又被重視又被忽略的是隨機(jī)數(shù)的問題。大家都知道幀同步要保證隨機(jī)數(shù)也完全一致。因此,大家都會(huì)去同步隨機(jī)數(shù)生成器的種子和它們的使用方式。但是一個(gè)潛在的可能性是某一方的非游戲邏輯對(duì)象使用了隨機(jī)數(shù)生成器,從而造成不同步。例如某一方的移動(dòng)設(shè)備性能更好,也因此屏幕上有一些額外粒子特效,這些粒子特效是有可能會(huì)使用隨機(jī)數(shù)發(fā)生器的,如果這些游戲邏輯之外的對(duì)象使用了隨機(jī)數(shù)發(fā)生器就會(huì)造成不同步的發(fā)生。

哦,對(duì)了,最后需要說明的一點(diǎn)是幀同步還可以和C/S模型組合使用,我們可以通過服務(wù)器來轉(zhuǎn)發(fā)客戶端的操作數(shù)據(jù),而不必讓各個(gè)客戶端直接通訊。公司內(nèi)有項(xiàng)目組采用的就是這種方案。

后記

當(dāng)然,以上只是一些基本的同步模型。在這里只是結(jié)合我們的項(xiàng)目經(jīng)驗(yàn)和大家做一個(gè)簡(jiǎn)單的分享,我想基于這些基本的模型還會(huì)衍生出一些別的方案。也歡迎大家來一起交流。

via:GAD

聲明:游資網(wǎng)登載此文出于傳遞信息之目的,絕不意味著游資網(wǎng)贊同其觀點(diǎn)或證實(shí)其描述。

銳亞教育

銳亞教育,游戲開發(fā)論壇|游戲制作人|游戲策劃|游戲開發(fā)|獨(dú)立游戲|游戲產(chǎn)業(yè)|游戲研發(fā)|游戲運(yùn)營(yíng)| unity|unity3d|unity3d官網(wǎng)|unity3d 教程|金融帝國(guó)3|8k8k8k|mcafee8.5i|游戲蠻牛|蠻牛 unity|蠻牛