這裏所說的技能系統包括:技能流程和技能創生體(法術場、彈道和buff)網絡
首先介紹authority和proxy的概念,這兩個概念是基於單位unit的基礎上進行的區分。優化
authority表示單位的主控端,即此單位是由客戶端和仍是服務端控制。對於玩家avatar,玩家本地的客戶端就是主控端。而對於怪物,他們的行爲由服務端控制,主控端就是服務端。代理
proxy表示代理端,表示被主控端控制。如對於怪物來講,全部的客戶端都是proxy;對於玩家A來講,服務端和其餘玩家的客戶端都是proxy。blog
0 技能同步的原則 遊戲
1.客戶端先行 rpc
對於玩家控制的單位來講,玩家點擊按鈕釋放一個技能,客戶端首先響應,單位播放動做以及相應的技能特效。同步
據瞭解,有的已上線遊戲並無作客戶端先行,而是全部的技能執行請求都發給服務端,而後由服務端發起。it
這種模式技能流程控制會比較簡單,可是在網絡環境差的狀況下,體驗可能差一些。可是,目測也是能夠接受的。io
2.技能流程以authority爲發起端 class
玩家單位技能發起是由她的客戶端,怪物的技能發起是由AI也就是服務端。
3.技能結算在服務端發起。
技能真正的結算,好比法術場檢測、buff結算、傷害計算以及扣血等,統一在服務端處理。
1 技能執行流程的同步
這裏所說的技能執行流程指的是技能樹的一個執行節點的流程。
技能流程負責動做、特效以及技能結算,其中技能結算包括:釋放法術場、彈道或buff。
一個技能執行節點的執行流程中,須要同步的有兩個時間點:
技能開始:技能開始播放動做
技能結算:前搖結束,即能進入結算邏輯。這類同步消息每每並非由技能自己去同步,而是技能生成了法術場、彈道等,他們去作相應的同步。
以玩家點擊技能按鈕開始釋放技能爲例介紹技能同步流程,如圖所示:
主控端點擊技能按鈕,技能開始播放動做,主控端告訴服務端技能開始。
服務端廣播給全部的客戶端(多玩家場景),告知其餘全部的客戶端此玩家開始執行技能。其餘客戶端收到指令後但是播放技能表現。
服務端延遲一段時間後,服務端開始進行技能結算,而且將結算結果通知客戶端。
延遲時間=技能前搖時間-上行-下行,下行一半不能肯定,因此默認爲上行=下行
另外一種中庸的計算方式是:延遲時間=技能前搖時間-上行,防止要求技能前搖時間過長
使用此同步流程的表現爲:
要求技能前搖時間>2*網絡延遲,若前搖時間短,則延遲時間=0,效果可能差一些
authority客戶端表現完美。
proxy client表現通常,即玩家A看玩家B的效果爲:玩家B剛開始執行技能動做,沒到前搖時間就進行了技能結算。可是由於玩家通常也不會過度關注其餘玩家的動做,因此是能夠接受的。
2 技能樹的同步
咱們遊戲使用的是技能樹來管理技能流程。那麼就面臨一個問題,技能樹如何同步。
最簡單最暴力的方式,是客戶端和服務端同時管理技能樹,而且將其狀態同步。這樣,客戶端和服務端的技能樹狀態統1、完備。
後來發現,對於proxy端,並不須要完備的技能樹信息,最節省的方式是proxy根本不接受技能樹同步信息,只是接受播放動做、技能結算等信息。但這樣須要告訴其餘proxy播放什麼動做、特效等。
在咱們系統中,技能同步包括三類同步消息:
技能根節點enter (root_enter): 表示一個大技能的進入
技能葉子節點enter(action_enter): 表示一個技能樹的執行節點的進入。
根節點exit(root_exit) :表示大技能結束
根節點保存一個完整技能的信息,須要和技能模塊外部交互,所以須要知道技能的開始和結束。
葉子節點的執行表明着技能真正的執行邏輯,也須要同步。
而對於其餘節點,做爲流程控制節點,只須要在主端確保技能流程無誤便可
後來這裏進行了進一步的優化,對於純根節點,主控端(玩家控制的客戶端)將信息同步給服務端,服務端再也不同步給其餘客戶端。有的技能樹只有一個節點,那麼按照葉子節點的策略,主控端同步給服務端,服務端廣播給全部的其餘客戶端。
3 技能結算的同步
技能結算包括建立法術場、buff、彈道、技能直接傷害等。
法術場、彈道的同步
法術場、彈道的同步比較相似,他們都做爲一個entity(網絡同步單元)在服務端建立,建立之後使用entity管理機制服務端通知客戶端他們的建立和銷燬。
以法術場爲例,法術場的執行和同步流程:
服務端發起建立一個法術場,而且通知客戶端
法術場每隔一段時間結算一次,注意,法術場結算並不須要同步,每隔一段時間服務端執行檢測邏輯,客戶端播放結算特效等。兩個邏輯互不依賴,也不要求時間一致。
當法術場結算時檢測到攻擊目標時,服務端計算攻擊傷害等信息,並將攻擊信息發給客戶端。
客戶端收到傷害信息,客戶端播放相應的表現,如法術場受擊特效等。此處還包括屬於通用模塊的跳字等。
當服務端的法術場時間到了進行destroy時,使用entity的管理機制通知全部客戶端destroy法術場。
彈道的同步相似,惟一的區別就是法術場在某一位置使用攻擊盒檢測目標,而彈道是一個移動的子彈,客戶端表現是一個特效在飛,而服務端每隔一段時間根據飛行速度等使用膠囊攻擊盒去檢測目標碰撞。
由以上能夠發現,法術場做爲一個entity他的管理成本是比較高的,因此若策劃想出一些需求須要使用多個法術場實現,通常經過拓展法術場功能使用一個法術場來實現。
好比,策劃要作一個冰火兩重天法術場,即法術場在每次結算時使用不一樣的參數,第一次結算使用火焰,第二次結算是冰霜。若這種需求較少,可使用兩個法術場,可是若是要冰火雷毒水電風魔奧術神聖*N重天,則代價太大。通常可讓法術場支持每次使用不一樣的結算參數來結算便可。
buff同步
buff是附加在unit身上的東西(沒有unit就沒有buff,可是沒有unit可能有法術場),因此不須要使用entity來同步。
服務端肯定buff是否能夠掛在unit上面。
客戶端和服務端都維護一個buff管理器,掛buff的消息通知全部客戶端,客戶端負責表現,服務端負責結算便可。
4 傷害、屬性的同步
主要介紹下傷害的同步,順便附帶介紹下屬性同步。
對於傷害結算來講,技能、buff、法術場和彈道均可能形成傷害,當服務端發現形成傷害時,服務端首先根據技能信息計算傷害值,計算之後將傷害信息發送給全部客戶端,全部客戶端接到信息後首先播放技能傷害相關的表現,如受擊特效等,而後播放跳字等通用傷害客戶端表現。
也就是說,傷害值的同步其實就是簡單的rpc消息。
buff可能修改單位屬性,如攻擊力、攻擊速度等。這些屬性值的同步通常使用屬性同步,屬性同步的意思是當一個值改變了,底層自動把這個值同步給客戶端。
血量等信息值都是用屬性同步方式。
傷害計算和屬性模塊是一個重要且比較複雜的模塊(固然,若遊戲數值很是簡單也能夠很簡單)