網路遊戲編程中如何應對並數據處理上的並發?

網路遊戲對數據的即時性要求非常高,尤其是以競技為導向的遊戲。那麼在遊戲編程中,如何應對數據並發操作?

以一個情景為例,AB玩家一個隊伍,CD玩家一個隊伍,在某一個時間範圍非常小的區間里,C給A玩家造成了100的傷害,同時B為A玩家減少了100傷害,D通過技能阻止了B對A的治癒,A擊殺了C玩家。那麼該情境下的數據並發如何進行判斷?


遊戲不存在並發,總是單線程一個個裁決


區分兩種情況

1、對於開放式地圖,比如大部分的MMORPG,傳奇,WOW,這種類型的,客戶端的操作指令,或者叫客戶端數據包(攻擊/移動/釋放技能)到伺服器端之後,是由同一個線程按先來後到的順序處理的(比如有線程可能是專門處理戰鬥邏輯的,有線程是專門處理背包倉庫邏輯的,有線程是專門處理強化打造合成的;或者對於分散式的服務端架構來說,可能就是一個單獨的進程在專門處理戰鬥)。

這個線程/進程有一個唯一的客戶端指令隊列的,每一個客戶端上來的指令都被push_back,並且push_back裡面是有鎖的,保證多線程寫隊列是安全的。那麼C攻擊A(具體造成多少點傷害這個一般是由伺服器收到攻擊指令後計算的,客戶端發包的時候一般是不知道這一次攻擊該造成多少點傷害的,當然也可以客戶端提前預算然後飄字,然後伺服器計算出真實結果後修正血條,但一般還是以服務端的最終計算結果為準),B給A加血(最終能加多少同上),D對B釋放技能(能不能釋放成功,魔法值夠不夠,會不會miss這些判斷同樣一般也是以伺服器為準),A擊殺了C這種屬於攻擊的計算結果,不屬於客戶端指令。這3條指令伺服器假定是「同時」接收到,因為網路接收數據可能是多線程的,指令在push_back隊列的時候,因為隊列只有一個,並且加鎖了,所以是不存在「同時」這種情況出現的,必定是有先有後的。只是誰先誰後不保證順序,最終的結果可能是:

C攻擊A被排在第1位,B給A加血排在第2位,D對B釋放技能排在第3位

C攻擊A被排在第1位,D對B釋放技能排在第2位,B給A加血排在第3位

B給A加血排在第1位,D對B釋放技能排在第2位,C攻擊A被排在第3位

B給A加血排在第1位,C攻擊A被排在第2位,D對B釋放技能排在第3位

D對B釋放技能排在第1位,C攻擊A被排在第2位,B給A加血排在第3位

D對B釋放技能排在第1位,B給A加血排在第2位,C攻擊A被排在第3位

對於第1種情況:那麼先計算攻擊傷害扣血,可能還有閃避計算,如果A沒死,再計算B加血,因為加血已經釋放,此時D釋放技能無效,如果加血是引導性技能或持續性技能,一般D釋放一個沉默或者禁言之類的技能那就屬於有效,可以造成打斷。

對於第2種情況:那麼先計算攻擊傷害扣血,可能還有閃避計算,再計算D釋放技能,沉默或者禁言生效,然後計算B加血,因為沉默或者禁言,所以無效。

其他4中情況題主可自行推理了。

2、對於開房間式的地圖,比如MOBA類的,或者包括夢幻的回合制這種類型的,服務端是按一局戰鬥為一個單位來處理,同一局戰鬥的指令由唯一一個線程/進程處理,不同局的戰鬥由多線程/多進程並行處理,一個線程/進程對應一個唯一的指令隊列,之後的處理方式同上


取決於你是在伺服器判斷然後同步到玩家,還是玩家自己做判斷然後同步到其他玩家。伺服器的話好說,保證這個房間的的計算全部是單線程的就好,p2p的話需要以一個玩家的計算結果作為標準,其他玩家計算的結果如果不一致將會被回退。詳見《網路遊戲核心技術與實踐》。伺服器端處理所有邏輯的例子可以看我github的一個例子:https://github.com/psionic12/AGES


需要保持一致性的一般放伺服器咯,要麼多線程加鎖,要麼丟到一個線程中串列處理。


推薦閱讀:

LOL會像暴雪製作WOW一樣的角色扮演類大型網遊嗎?
爐石傳說這麼燒錢,為什麼沒有其他的公司開發類似爐石的遊戲呢?按理來說中國不是最擅長複製了嗎?
eve有沒有知乎軍團?
如何評價坦克世界的個人任務?
如何評價新門派長歌門?蒼雲就此就輝煌不再了嗎?

TAG:網路遊戲 | 遊戲編程 | 數據處理 |