最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

作為一個程序員!你有沒有想象過:多人游戲是如何實現(xiàn)的?

2021-04-09 14:44 作者:C語言編程__Plus  | 我要投稿

作為一個程序員,你有沒有想象過多人游戲是如何實現(xiàn)的?

在外行人看來游戲很神奇:兩個或者更多的玩家在網(wǎng)絡(luò)上分享共同的經(jīng)歷,就像他們真實的存在于相同的虛擬的世界一樣。游戲看起來猶如一個巨大的魔術(shù),奇妙而又刺激,但作為一個開發(fā)人員我們知道,真實的情況和我們所看到的并不一樣,那只是一種錯覺。你感受到的共享現(xiàn)實,實際上是在那個時刻內(nèi),由你自己的獨特視角和位置所感知的近似情況。


文章來源:思否技術(shù)圈

一、Peer-to-Peer 幀同步

最初的游戲是通過peer-to-peer來聯(lián)網(wǎng)的,每個計算機通過網(wǎng)狀拓?fù)涞慕Y(jié)構(gòu)的彼此連接并交換信息。你仍然可以看到這種模型存在于RTS游戲中,而且基于某些原因它還很有趣,也許是因為它是大多數(shù)人認(rèn)為游戲網(wǎng)絡(luò)工作方式的第一種方式。

處理游戲信息的基本思想就是把游戲的數(shù)據(jù)抽象并轉(zhuǎn)換成一系列命令消息,當(dāng)處理每個轉(zhuǎn)換的時候就直接演變?yōu)橛螒虻臓顟B(tài)。比如:移動單位、攻擊物體、建造建筑。這一切都需要在線的每個玩家機器,從一個初始化命令開始之后,都運行完全相同的命令和轉(zhuǎn)換數(shù)據(jù)。

當(dāng)然了,這只是一個過于簡單的解釋,同時也隱去了很多細(xì)節(jié),不過我們通過這個基本的思路可以知道RTS游戲的網(wǎng)絡(luò)是如何工作的。

這些看起來是如此簡單和優(yōu)雅,但不幸的它們有幾個因素限制者我們。

第一個限制,要保證游戲狀態(tài)完全確定一致的是異常困難,特別是保持每臺機器上每個轉(zhuǎn)換輸出都保持相同。比如,一個單位在兩臺機器上有略微不同的路徑,在一臺機器上早一些到達并開始了戰(zhàn)斗,結(jié)果反敗為勝,而在另一臺機器上,由于稍微晚一些到達而失敗。就像一只蝴蝶扇動了翅膀,然后在世界的另一邊導(dǎo)致了颶風(fēng)的出現(xiàn),隨著時間的推移,一個微小的區(qū)別就會導(dǎo)致兩邊完全的不同步。


第二個限制,為了保證游戲的所有玩家輸出一致,這就需要等到所有玩家的當(dāng)前回合數(shù)據(jù)都到達之后才可以模擬播放這一回合動作。這就意味著游戲中的每一個玩家都需要等待網(wǎng)絡(luò)延遲最高的那個玩家。RTS游戲通常代表性地通過立即提供音頻反饋與(或是)播放吟唱(過渡)動畫來掩蓋這段延遲,但是最終真正影響游戲的動作要在這段延遲過去之后才能進行。

第三個限制,因為游戲中狀態(tài)改變的同步是通過發(fā)送命令信息來同步的。所以為了游戲中玩家狀態(tài)都一致,需要所有的玩家都要從相同的初始狀態(tài)來開始游戲。這意味著每個玩家必須在開始游戲之前先加入房間然后一起開始游戲,盡管理論上也可以支持讓某些玩家晚些加入游戲,但是在一場進行中的游戲中獲得一個完全確定的起始點的難度相當(dāng)大,所以這種情況并不常見。

盡管有這些因素限制困擾者我們,不過這個模型還是很適合RTS游戲的,并且它仍然存在于今天的游戲當(dāng)中,例如“Command and Conquer”、“Age of Empires”與“Starcraft”等。原因就是在RTS游戲中,里面包含了上千多的單位,這些單位都有自己的狀態(tài)需要同步,而且他們數(shù)據(jù)量都太大了,很難用來在玩家之間交換。別無選擇,我們只能通過這些游戲狀態(tài)改變的命令來同步。所以以上這些就是 peer-to-peer 幀同步的網(wǎng)路游戲模型的介紹了,對于其他類型的游戲,最先進的技術(shù)已經(jīng)開始出現(xiàn)了。讓我們現(xiàn)在從Doom, Quake 以及 Unreal經(jīng)典游戲中開始一起觀察動作游戲的技術(shù)演化。


二、客戶端/服務(wù)器(c/s架構(gòu))

在動作游戲的時代,以上幀同步的限制在Doom?游戲中變得更加明顯,盡管在局域網(wǎng)中體驗還不錯,但在對于互聯(lián)網(wǎng)的用戶來說它體驗太糟糕了:

盡管可以使用一個貓(調(diào)制解調(diào)器)把兩個Doom?機器通過互聯(lián)網(wǎng)連接在一起,但他們一起游戲會異常緩慢。范圍從無法游戲(例如:14.4Kbps PPP 連接)到稍微可以玩(例如 :28.8Kbps 貓運行一個被SLIP驅(qū)動壓縮的數(shù)據(jù))之間游戲聯(lián)機都異常緩慢。由于這些連接方式只是邊際效用,本文將僅關(guān)注直接的網(wǎng)絡(luò)連接。

這個問題是因為Doom網(wǎng)絡(luò)部分本來就是只為局域網(wǎng)而設(shè)計的,并且使用了前面介紹的peer-to-peer 幀同步模型。每一回合每個玩家的輸入的信息(比如關(guān)鍵按鍵等)都與其他人進行同步通知,并且任何玩家在播放這一幀動畫之前,必須得等到所有其他玩家的關(guān)鍵按鍵信息都被接收到,才可以去模擬播放。

也就是說,在你可以轉(zhuǎn)身(轉(zhuǎn)換),移動或者射擊之前,你必須等待延遲最大的貓(調(diào)制調(diào)解器)玩家的輸入。只是想想上述那個人所寫的“這些連接方式只是邊際效用”就會讓人咬牙切齒和沮喪了。

為了改變這種現(xiàn)狀,只能在局域網(wǎng)以及大學(xué)網(wǎng)絡(luò)和大型企業(yè)才能獲得良好連接而進行游戲,是需要改變這種網(wǎng)絡(luò)模型了。在1996年,這變成了現(xiàn)實并被實現(xiàn)了,John Carmack當(dāng)時 發(fā)布雷神之錘,他采用客戶端/服務(wù)器(C/S)架構(gòu)代替了P2P模型。

如今游戲中的玩家可以不必再運行相同的代碼以及直接相互通信,每個玩家的機器是都是一個“客戶端”,他們都通過一臺叫做“服務(wù)器”的機器進行通信交互。游戲的最終狀態(tài)確定不再依賴于每臺客戶端機器來共同確認(rèn),而是由服務(wù)器來確定最終結(jié)果。每個客戶端如同一個啞終端,用來展示一個近似值的表演,真是的游戲狀態(tài)是運行于服務(wù)器之上。

在一個純粹的c/s架構(gòu)中,你不必在本地運行游戲代碼,而是把一些例如按鍵、鼠標(biāo)移動,點擊等輸入信息發(fā)送到服務(wù)器。服務(wù)器會在游戲世界中更新你的玩家狀態(tài),然后再封包一個包含你角色信息以及臨近玩家數(shù)據(jù)的包回復(fù)給你的客戶端。所有的客戶端在每個消息更新的間隙做一個插值預(yù)測,以改善在每個狀態(tài)更新期間,物體可以平滑的移動,如此,你就有一個可以聯(lián)網(wǎng)的客戶端/服務(wù)器架構(gòu)的游戲了。

這已經(jīng)是向前邁出了極大的一步。游戲的體驗依賴于客戶端和服務(wù)器的連接,而不是游戲中延遲最大的那個玩家。如此可以支持玩家在游戲中自由的進入和退出,同時由于客戶端/服務(wù)器降低了平均每位玩家的帶寬,從而可以增加更多的在線玩家。


但是這里仍然有一些問題存在于 c/s 架構(gòu)中:

我記得我交代了所有從DOO到Quake中關(guān)于網(wǎng)絡(luò)的決策,但是重要的是我正在使用錯誤的假設(shè)來做一個好的網(wǎng)絡(luò)游戲。我原先設(shè)計的目標(biāo)是網(wǎng)絡(luò)延遲<200ms。人們通過一個好的網(wǎng)絡(luò)供應(yīng)商連接互聯(lián)網(wǎng),從而可以獲得一個好的游戲體驗。但事與愿違,世界上99%的用戶使用貓(調(diào)制調(diào)解器)通過 slip或者ppp 進行連接,而他們常常都會通過槽糕而又擁擠的ISP。這會帶來最低300+ms 的 網(wǎng)絡(luò)延遲。一個消息要經(jīng)過,客戶端>用戶貓>ISP貓>服務(wù)器>ISP貓>用戶貓>客戶端。上帝,這太遜了。

OK,我做了一個錯誤的設(shè)定。我在家里使用T1 寬帶,所以我只是不了解在PPP網(wǎng)絡(luò)下的生活。我現(xiàn)在就解決它。

這個問題當(dāng)然是延遲。

接下來John在他發(fā)布QuakeWorld的時候?qū)⒏淖冞@個行業(yè)。


三、客戶端預(yù)測(Client-Side Prediction)

在原來的Quake游戲中,你會感覺到電腦與服務(wù)器之間的延遲。比如,你按鍵向前移動,在你真正移動之前,你需要等到數(shù)據(jù)包發(fā)送服務(wù)器然后再回復(fù)到你的客戶端,你才可以真正的移動。按鍵開火,在你的射擊之前同樣需要相同的等待。

如果你玩過任何FPS游戲,比如:Modern Warfar,你會發(fā)現(xiàn)并沒有延遲發(fā)生。那么fps游戲是如何做到在多人情況下,你的動作看起來并沒有延遲?

這個問題被分為兩個部分來解決。第一個部分是客戶端移動預(yù)測,這事John Carmack 為 QuakeWorld游戲多開發(fā)的,后來被合并到了Tim Sweeney的虛幻網(wǎng)絡(luò)模塊。第二個部分就是延遲補償,它是有Valve公司的Yahn Bernier在Counterstrike所開發(fā)。那么在這個章節(jié),我們把焦點放在第一部分——隱藏用戶移動的延遲。

當(dāng)寫到關(guān)于他即將發(fā)布的QuakeWorld計劃的時候,John Carmack 講到:

我現(xiàn)在允許客戶端可以預(yù)測用戶的移動,直到服務(wù)器的權(quán)威信息回復(fù)之前。這是一個重大的結(jié)構(gòu)變更??蛻舳诵枰狸P(guān)于對象的硬度、摩擦力、重力等一系列基礎(chǔ)屬性。我很傷心的看到,客戶端僅作為一個終端存在將會離開,但作為一個實用主義者,我必須超越這種理想情懷。

那么現(xiàn)在我們?yōu)榱讼舆t,客戶端需要運行更多的代碼。它現(xiàn)在不再是一個只把輸入發(fā)送給服務(wù)器然后再把返回信息進行插入的啞終端。現(xiàn)在客戶端的機器可以運行一部分游戲代碼,它可以在本地預(yù)測你的角色移動并且可以即時響應(yīng)你的輸入。

現(xiàn)在當(dāng)你即刻按鍵向前,你的游戲會立刻向前移動,不會再去等待數(shù)據(jù)往返一次客戶端和服務(wù)器之間才來回應(yīng)你的操作。

這種方式的難點不在于預(yù)測,這種預(yù)測工作,就像正常的游戲代碼一樣 —— 根據(jù)玩家的輸入,及時地更新游戲角色的狀態(tài)。而難點在于,當(dāng)客戶端和服務(wù)器對于玩家角色所做的事情(動作)核檢不一致的時候,客戶端如何基于服務(wù)器信息進行更正。

現(xiàn)在你會想,hey,如果代碼運行在客戶端——為何不以客戶端的信息為準(zhǔn)?客戶端可以自己的為角色模擬運行代碼,并且只需要在每次發(fā)送數(shù)據(jù)包時告知服務(wù)器這些信息。如果每個客戶端都對服務(wù)器發(fā)送相同的信息,告訴服務(wù)器“這是我現(xiàn)在的位置信息”,那么將會帶來這樣的問題??蛻舳藭苋菀妆缓诳凸舨⒖刂?,這樣在RPG游戲中,一個作弊便可以立即躲避對方技能擊中,或者當(dāng)你射擊的時候瞬間移動到你的身后。


所以在FPS游戲中,盡快每個玩家的客戶端可以預(yù)測他們自己的角色進行操作移動,但最終每個玩家的角色狀態(tài)絕對以服務(wù)器為準(zhǔn)。

這就是有趣的地方。如果客戶端和服務(wù)器產(chǎn)生了不一致,客戶端必須基于服務(wù)器的信息為準(zhǔn)并更新,但是由于客戶端和服務(wù)器之前有延遲,服務(wù)器的修正必然是過去的動作。比如,如果信息從客戶端到服務(wù)器耗時100ms,然后返回又耗時100ms,那么任何服務(wù)器的的修正都是客戶端200ms之前的行為動作,這個時間正好是客戶端預(yù)測角色移動的時間。

如果客戶端每個動作都會被服務(wù)器修正,那么你將會看客戶端被拉回了原先的位置,如此客戶端將做不了任何預(yù)先預(yù)測的運算。那么我們?nèi)绾谓鉀Q這個問題,依然可以保持客戶端提前預(yù)測?

解決方案就是在客戶端創(chuàng)建一個buffer,然后用來循環(huán)保持角色的狀態(tài)以及本來玩家的輸入。當(dāng)客戶端收到了服務(wù)器的更正信息時候,它首先丟棄掉buffer里面比(服務(wù)器回復(fù)的)更正狀態(tài)要老的狀態(tài)信息,然后基于(更正的)正確的狀態(tài)重放存儲在buffer里面的輸入信息,重發(fā)的這些輸入信息的范圍是從正確狀態(tài)到當(dāng)前預(yù)測時間之間。如此實際上,客戶端只是看似無形中“倒帶和重放”當(dāng)?shù)赝婕医巧\動的最后n幀,同時保持世界其他地方?jīng)]有變化。

這種方法可以讓玩家感覺在控制游戲的時候沒有延遲,同時也改善了客戶端和服務(wù)器之間代碼運行的一致性——在同等輸入的情況下保持一致的結(jié)果。


當(dāng)然了,修正的情況很少發(fā)生,Tim Sweeney 如此描述:

…對于客戶端和服務(wù)器最好的是:所有情況下,服務(wù)器都是權(quán)威的。幾乎所有的時間,客戶端模擬的和服務(wù)器的數(shù)據(jù)都是一致,所以客戶端的位置很少被修正。只有的少數(shù)罕見的情況下,例如一個玩家被火箭擊中,或者和一個敵人(怪物)碰撞上,那么客戶端本地的情況有可能需要被修正。

也就是說,只有當(dāng)玩家的角色被一些外部事件影響玩家的輸入,并且這些不能被客戶端預(yù)測時,玩家的位置(行為)需要被服務(wù)器修正。當(dāng)然,如果玩家試圖作弊,必然會被服務(wù)器修正。

PS:另外對于學(xué)習(xí)編程或者正在工作的朋友,如果你想更好的提升你的編程能力乃至轉(zhuǎn)行,彎道超車,快人一步!筆者這里或許可以幫到你~

微信公眾號:C語言編程學(xué)習(xí)基地

分享(源碼、項目實戰(zhàn)視頻、項目筆記,基礎(chǔ)入門教程)

歡迎轉(zhuǎn)行和學(xué)習(xí)編程的伙伴,利用更多的資料學(xué)習(xí)成長比自己琢磨更快哦!


作為一個程序員!你有沒有想象過:多人游戲是如何實現(xiàn)的?的評論 (共 條)

使用qq登录你需要登录后才可以评论。
牡丹江市| 奎屯市| 洛阳市| 嵩明县| 芒康县| 霸州市| 南丹县| 临澧县| 苍山县| 滁州市| 宽城| 绵阳市| 宝丰县| 余姚市| 贺兰县| 双流县| 临泉县| 那坡县| 桐乡市| 宁国市| 阳信县| 宝丰县| 武鸣县| 南城县| 和硕县| 西乌珠穆沁旗| 乐业县| 大同县| 巴南区| 吉木萨尔县| 平乐县| 辽阳县| 色达县| 保定市| 商城县| 连山| 邹城市| 凌源市| 南部县| 新闻| 金寨县|