技能系統的同步機制

此篇文章基於之前文章介紹的技能系統,主要介紹了如何實現MMO中的技能系統的同步。閱讀此文章之前,推薦首先閱讀前一篇文章:一個MMORPG的常規技能系統 - 知乎專欄。

此外,我將在下一篇文章中介紹技能系統同步機制的優化,以及防外掛的相關內容,歡迎關注專欄。

這裡所說的技能系統包括:技能流程和技能創生體(法術場、彈道和buff)

首先介紹authority和proxy的概念,這兩個概念是基於單位unit的基礎上進行的區分。

authority表示單位的主控端,即此單位是由客戶端和還是服務端控制。對於玩家avatar,玩家本地的客戶端就是主控端。而對於怪物,他們的行為由服務端控制,主控端就是服務端。

proxy表示代理端,表示被主控端控制。如對於怪物來說,所有的客戶端都是proxy;對於玩家A來說,服務端和其他玩家的客戶端都是proxy。

0 技能同步的原則

1.客戶端先行

對於玩家控制的單位來說,玩家點擊按鈕釋放一個技能,客戶端首先響應,單位播放動作以及相應的技能特效。

據我了解,有的已上線遊戲並沒有做客戶端先行,而是所有的技能執行請求都發給服務端,然後由服務端發起。

這種模式技能流程式控制制會比較簡單,但是在網路環境差的情況下,體驗可能差一些。但是,目測也是可以接受的。

2.技能流程以authority為發起端

玩家單位技能發起是由她的客戶端,怪物的技能發起是由AI也就是服務端。

3.技能結算在服務端發起。

技能真正的結算,比如法術場檢測、buff結算、傷害計算以及扣血等,統一在服務端處理。

1 技能執行流程的同步

這裡所說的技能執行流程指的是技能樹的一個執行節點的流程。

技能流程負責動作、特效以及技能結算,其中技能結算包括:釋放法術場、彈道或buff。

一個技能執行節點的執行流程中,需要同步的有兩個時間點:

  • 技能開始:技能開始播放動作
  • 技能結算:前搖結束,即能進入結算邏輯。這類同步消息往往並不是由技能本身去同步,而是技能生成了法術場、彈道等,他們去做相應的同步。

以玩家點擊技能按鈕開始釋放技能為例介紹技能同步流程,如圖所示:

1.主控端點擊技能按鈕,技能開始播放動作,主控端告訴服務端技能開始。

2.服務端廣播給所有的客戶端(多玩家場景),告知其他所有的客戶端此玩家開始執行技能。其他客戶端收到指令後可是播放技能表現。

3.服務端延遲一段時間後,服務端開始進行技能結算,並且將結算結果通知客戶端。

延遲時間=技能前搖時間-上行-下行,下行一半不能確定,所以默認為上行=下行

另一種中庸的計算方式是:延遲時間=技能前搖時間-上行,防止要求技能前搖時間過長

使用此同步流程的表現為:

1.要求技能前搖時間>2*網路延遲,若前搖時間短,則延遲時間=0,效果可能差一些

2.authority客戶端表現完美。

3.proxy client表現一般,即玩家A看玩家B的效果為:玩家B剛開始執行技能動作,沒到前搖時間就進行了技能結算。但是因為玩家一般也不會過分關注其他玩家的動作,所以是可以接受的。

2 技能樹的同步

我上篇文章一個MMORPG的常規技能系統 - 知乎專欄已經介紹,我們遊戲使用的是技能樹來管理技能流程。那麼就面臨一個問題,技能樹如何同步。

最簡單最暴力的方式,是客戶端和服務端同時管理技能樹,並且將其狀態同步。這樣,客戶端和服務端的技能樹狀態統一、完備。

後來發現,對於proxy端,並不需要完備的技能樹信息,最節省的方式是proxy根本不接受技能樹同步信息,只是接受播放動作、技能結算等信息。但這樣需要告訴其他proxy播放什麼動作、特效等。

在我們系統中,技能同步包括三類同步消息:

  • 技能根節點enter (root_enter): 表示一個大技能的進入
  • 技能葉子節點enter(action_enter): 表示一個技能樹的執行節點的進入。
  • 根節點exit(root_exit) :表示大技能結束

根節點保存一個完整技能的信息,需要和技能模塊外部交互,因此需要知道技能的開始和結束。

葉子節點的執行代表著技能真正的執行邏輯,也需要同步。

而對於其他節點,作為流程式控制制節點,只需要在主端確保技能流程無誤即可

後來這裡進行了進一步的優化,對於純根節點,主控端(玩家控制的客戶端)將信息同步給服務端,服務端不再同步給其他客戶端。有的技能樹只有一個節點,那麼按照葉子節點的策略,主控端同步給服務端,服務端廣播給所有的其他客戶端。

3 技能結算的同步

技能結算包括創建法術場、buff、彈道、技能直接傷害等。

法術場、彈道的同步

法術場、彈道的同步比較類似,他們都作為一個entity(網路同步單元)在服務端創建,創建以後使用entity管理機制服務端通知客戶端他們的創建和銷毀。

以法術場為例,法術場的執行和同步流程:

  1. 服務端發起創建一個法術場,並且通知客戶端
  2. 法術場每隔一段時間結算一次,注意,法術場結算並不需要同步,每隔一段時間服務端執行檢測邏輯,客戶端播放結算特效等。兩個邏輯互不依賴,也不要求時間一致。
  3. 當法術場結算時檢測到攻擊目標時,服務端計算攻擊傷害等信息,並將攻擊信息發給客戶端。
  4. 客戶端收到傷害信息,客戶端播放相應的表現,如法術場受擊特效等。此處還包括屬於通用模塊的跳字等。
  5. 當服務端的法術場時間到了進行destroy時,使用entity的管理機制通知所有客戶端destroy法術場。

彈道的同步類似,唯一的區別就是法術場在某一位置使用攻擊盒檢測目標,而彈道是一個移動的子彈,客戶端表現是一個特效在飛,而服務端每隔一段時間根據飛行速度等使用膠囊攻擊盒去檢測目標碰撞。

由以上可以發現,法術場作為一個entity他的管理成本是比較高的,所以若策劃想出一些需求需要使用多個法術場實現,一般通過拓展法術場功能使用一個法術場來實現。

比如,策劃要做一個冰火兩重天法術場,即法術場在每次結算時使用不同的參數,第一次結算使用火焰,第二次結算是冰霜。若這種需求較少,可以使用兩個法術場,但是如果要冰火雷毒水電風魔奧術神聖*N重天,則代價太大。一般可以讓法術場支持每次使用不同的結算參數來結算即可。

buff同步

buff是附加在unit身上的東西(沒有unit就沒有buff,但是沒有unit可能有法術場),所以不需要使用entity來同步。

  1. 服務端確定buff是否可以掛在unit上面。
  2. 客戶端和服務端都維護一個buff管理器,掛buff的消息通知所有客戶端,客戶端負責表現,服務端負責結算即可。

4 傷害、屬性的同步

主要介紹下傷害的同步,順便附帶介紹下屬性同步。

對於傷害結算來說,技能、buff、法術場和彈道都可能造成傷害,當服務端發現造成傷害時,服務端首先根據技能信息計算傷害值,計算以後將傷害信息發送給所有客戶端,所有客戶端接到信息後首先播放技能傷害相關的表現,如受擊特效等,然後播放跳字等通用傷害客戶端表現。

也就是說,傷害值的同步其實就是簡單的rpc消息。

buff可能修改單位屬性,如攻擊力、攻擊速度等。這些屬性值的同步一般使用屬性同步屬性同步的意思是當一個值改變了,底層自動把這個值同步給客戶端。

血量等信息值都是用屬性同步方式。

傷害計算和屬性模塊是一個重要且比較複雜的模塊(當然,若遊戲數值非常簡單也可以很簡單),後面我會寫文章詳細介紹這個模塊。

配圖:守望先鋒 - 天使


推薦閱讀:

PSV 開發包已經出現了,PSV 的應用市場是否會像 App Store 一樣火起來,國內是否會出開發 PSV 應用或遊戲的專業團隊?
文字播報型的自動戰鬥系統該如何保障不出現漏洞?
有沒有辦法把整個遊戲框架架設在伺服器上,客戶端不參與任何運算?
中國遊戲行業各階層逼格分析

TAG:游戏开发 | 编程 | 游戏引擎 |