導語:
表現豐富、機制多變的技能作為MMORPG遊戲戰鬥體驗的核心組成部分,是吸引玩家的一大亮點,本文總結了在MMORPG技能系統設計上的一些經驗,供大家參考。
1、設計思路
早期的MMORPG手遊中,技能的表現相對簡單,因此技能流程被分為幾個固定的階段(如準備階段、攻擊階段、受擊階段),可以實現成一個簡單的由伺服器訊息驅動的狀態機,策劃只需要配置一下切換狀態的條件和不同狀態的表現(特效、動畫、音效等)。這種方式實現比較簡單,但由於流程固化,對於實現機制複雜的技能時,往往需要進行編碼實現,效率不高。因此一個好的技能系統應該是由資料驅動的,能讓策劃能自由組合配置。
當前資料驅動的技能系統的有以下幾個例子:
1.1 Dota2技能系統
Dota2技能系統定義了Event、Action、Modifier等技能行為,由策劃配置Key-Value的Json或Lua來自由組合,遊戲執行時會將策劃配置的檔案解析成技能樹。這種實現可以透過Key進行復用,但是當策劃定義的Key數量過多時,學習成本將會比較高,而且技能流是文字型,不易於理解技能流程。
1.2 守望先鋒技能系統
守望先鋒使用暴雪的指令碼系統Statescript來實現技能系統。Statescript是一個視覺化的指令碼語言;每一個指令碼都是一組互相連線的節點(node)形成的圖(graph),代表了一段遊戲邏輯的實現。當一個指令碼執行時,它會建立一個執行時物件,這裡稱之為指令碼例項(instance),每一個例項都被一個實體(entity)所擁有。實體上的指令碼例項可以被動態地新增和刪除,同一個實體上可以同時執行同一個指令碼的多個例項。
如上圖所示,Statescript節點包括入口(Entry)、條件(Condition)、動作(Aciton)、狀態(State),由程式設計師來實現這些具體的Action或State,然後策劃就可以使用Statescript來自由組合自己想要的技能。
可以看出Statescript其實並不是單獨為了技能實現的,而是一個通用的指令碼系統,只要提供的節點型別足夠多的話,策劃可以用來實現很多邏輯。這對於策劃對各種節點的熟悉程度和程式設計能力有一定的要求。
1.3 UE4 Gameplay Ability System
UE4 GAS是官方提供的依賴UE4 Gameplay框架的一個技能系統。基本構成如下:
1. Ability SystemComponent:技能執行時元件,控制技能的執行和相關屬性的改變;
2. Ability:技能,透過藍圖配置技能例項,包含較完整的技能邏輯,執行時可以動態地新增給角色的技能系統,或從技能系統中刪除;
3. Attribute和AttributeSet,屬性和屬性集。Attribute代表角色的某種屬性,如血量、能量等,屬性集表示一組屬性的集合;
4. Tags,標籤,代表了某種狀態。透過不同的Tag來表示角色當前的狀態,如燃燒、虛弱等,類似角色身上的Buff;
5. Gameplay Effect,技能效果,表示對某些Attribute和Tag的修改,例如一個火球術造成的GE可以是造成血量減50,同時將角色變成燃燒狀態;
6. Ability Tast,技能任務,表示技能過程中要執行的一個邏輯,例如播放動作等。
GAS系統也可以透過實現特定的Task和Effect,然後由策劃自由組合,由於藍圖編輯器的視覺化,可以清晰地看出技能的流程。
1.4 MMORPG技能系統的特點
以上列舉了三種優秀的資料驅動的技能系統的實現方案,透過對技能基礎組成部分的抽象來實現技能流程的原子化,並基於此提供了自由組合、資料驅動的能力,大大提高了策劃開發新技能的效率和自由度。上述三個技能方案來源於MOBA和射擊遊戲,這類遊戲技能成長性相對簡單。但是對於MMORPG遊戲而言,技能數值的成長性也是技能系統的重要組成部分,因此在資料驅動、自由組合的設計原則上,技能成長數值的配置的便捷性也需要考慮進去。
2、MMORPG技能系統分析
明確了資料驅動的設計思路後,首先需要分析下技能資料的組成。對於成長性的技能數值,例如不同等級傷害不同,我們可以繼續按照數值策劃的習慣,將它們保留在Excel裡。而對於相同的技能,不管多少級,技能的流程和機制是一樣的,這一部分我們就可以參考上述例子,將技能流程進行抽象,並交給策劃自由組合搭配。
2.1 技能流程抽象
一般MMORPG遊戲的技能可以定義為透過特定的規則修改技能選點/目標後,執行技能表現並結算技能效果,流程可以總結如下:
以一個常見的火球術為例,代入到上述流程圖,技能過程可以描述為玩家釋放技能時,首先檢測目標是否在射程範圍內,如果在範圍內,且未被打斷,則開始播放施法動畫並朝目標發射火球,火球命中目標後,進行傷害結算,並播放目標的受擊表現。
將技能流程進一步抽象,可以得到三種型別的流程節點:
1. 規則型別:例如選目標規則、結算規則、條件判斷等
2. 流程型別:分支流程、並行流程、迴圈流程等
3. 表現型別:動作、音效、特效等
類似第一部分的三個例子,可以由開發實現不同Action或Task,交由策劃自由組合,即可實現技能流程的資料驅動。但是這裡如何確定抽象粒度呢?對於程式來說,將這些節點全部原子化的話,是最簡單的,類似UE的GAS的設計思路,可以設計很多的Task,例如播放蒙太奇、播放特效等,搭配上很多的Effect,那功能就足夠強大足夠靈活。這樣帶來的一個問題就是,當節點實現的功能足夠細的情況下,對於大致相同的技能流程,會出現“一千個讀者心中有一千個哈姆雷特”的情況(如果大家的專案使用過UE藍圖進行開發,就能大致理解),也就是不同的策劃完全能組合出看起來完全不同的流程圖,這樣既不方便學習,也不方便除錯。因此我們嘗試從業務層上進行抽象,抽象的原則是理解直觀,學習門檻低,且型別可收斂。
回到上面的流程圖,我們和策劃一起梳理了我們已經上線的一個MMORPG專案現存的幾百個技能,從業務側總結出了這樣的一組節點:
我們將節點分為入口、同步、流程控制和表現等幾個型別。開始節點裡的配置內容主要是技能的一些釋放條件;請求節點比較特殊,裡面配置的是選點/選目標邏輯和結算效果,主控客戶端會計算選點/選目標結果,同步後服務端會進行校驗和結算,然後廣播結算結果;流程控制節點裡配置的是判斷技能流程走向的條件;表現節點裡配置動畫、特效等表現資料。
這一類策劃易於理解的業務節點實際上是由一系列的原子化功能的組合,例如在動作節點裡,除了動畫配置外,還會有特效、音效、震屏等表現的配置。這樣抽象的話,不僅可以收斂型別,還可以保證對於相同機制的技能,不同策劃配置出來的流程圖基本一致,開發除錯的時候也易於理解這個技能的整體流程(對於如何確定抽象粒度,其實每個專案組都有各自的取捨,這裡並沒有一個通用的標準,只是看是否適合當前專案)。例如一個火球術就可以表現為:
第一個請求節點通知服務端技能開始了,主控端開始預表現,服務端校驗目標合法性並廣播,收到訊息的客戶端執行後續動作和彈道表現,主控端彈道終點會再次通知服務端,服務端結算並廣播結算結果。
至此我們可以確定一個技能資料分為技能表裡的成長性數值資料加上技能藍圖資料,技能表裡一個技能可以索引一個技能藍圖配置(多對一,例如不同等級的火球術索引同一個技能藍圖)。對於抽象出來的節點,我們使用protobuf定義,並儲存成Json檔案,執行時透過技能ID索引到對應的技能藍圖來構造一棵樹,並根據伺服器同步的動態資料來Tick這棵樹的執行。除了配置好的靜態資料之外,技能執行時過程中會產生目標、選點等動態資料。我們的請求節點客戶端側的主要工作是同步這些發生變化的動態資料(這裡稱為技能上下文),客戶端在每個請求節點收到服務端廣播的上下文變更後,後續的表現節點就會基於新的上下文進行表現。
2.2 技能執行時設計
技能執行時我們採用了類似GAS的設計,核心是角色身上掛載的技能元件。技能元件負責維護技能例項,並管理技能例項的生命週期。
技能執行時針對上述抽象出來的每個技能流程節點,實現了一個對應的執行時SkillAction。這些Action的建立由伺服器同步的技能上下文來驅動建立。前一節簡單介紹了上下文的概念,它包含了經過伺服器驗證的動態資料,如新選點、新目標、結算效果等。客戶端收到一個新的上下文後,會建立一個Action組,每個Action組維護該上下文後續表現節點的執行。一個技能如果有多個請求同步節點的話,會建立多段上下文,每個上下文驅動它後續節點的執行。
技能的同步發生於技能流程的請求節點處,一般需要同步的原因是動態資料的變更。例如一個彈射技能,在多個目標間彈射時會發生多次目標變更,這就需要多次同步。同步方式是主控端發起並預表現,伺服器校驗並廣播,主控端收到經校驗的資料後會進行修正,模擬客戶端收到廣播包後進行後續表現。
為了主控客戶端的體驗,技能開始後,會預測下一次同步時間,並在下次同步點之前傳送同步包,保證收到伺服器回包時剛好執行到同步點可以無縫執行後續邏輯。弱網環境下走到同步點未收到同步包的情況下,會預表現動畫、特效等,收到回包後會對預表現進行修正:若伺服器同步資料和當前一致,則繼續當前表現;若不一致,例如預表現的位移和伺服器下發的不同,在閾值範圍內,根據時間戳向新位置加速插值表現,超過閾值的話則直接拉到新位置,防止和伺服器位置差距過大。這個預發包的方式是在客戶端實現了個技能中間層,主要功能是轉發上下行的技能包,並預測下一個同步時間。
技能的結算部分被抽象成效果,效果ID表示效果的功能(如修改屬性、增刪Buff等),一個效果裡可以配置引數、條件、機率等,且可以被技能、Buff等多個數值系統複用。
3、工具鏈支援
確定了技能資料和執行時結構後,就需要提供配套的工具鏈支援:一個方便易用的技能編輯器。對於不同的使用者,對編輯器的要求是不一樣的:
1. 對於策劃/美術:編輯器需要易於配置,即改即用,因此我們需要提供一個易於上手和使用的配置介面,且需要熱更新功能;
2. 對於開發:針對技能系統出現的bug,需要能迅速定位問題,因此我們需要提供執行時流程視覺化和網路訊息日誌功能。
3.1 技能編輯器介紹
我們專案經歷過換引擎的過程,在Unity上,我們開發了基於GraphView節點編輯器的技能配置介面,轉到UE4後,使用藍圖的底層框架UEdGraph將這個配置介面移植了過來,如上圖所示。這個編輯器左邊展示了技能的基礎資訊,上面是技能關聯的Excel表格資訊預覽,中間是節點配置介面,右側是選中某個節點後的詳情配置皮膚。
策劃在可以選擇基於一個已有的技能模板或者新建一個技能藍圖,進行技能流程的配置。當策劃只想預覽技這個技能的動畫、特效等客戶端表現時,可以使用離線預覽模式,直接在編輯器中看技能的表現效果。
如果策劃想看遊戲中的實時表現,也可以在PIE執行模式下登入到伺服器,修改完成後將當前技能配置熱更新到伺服器,同時替換當前遊戲記憶體,並裝配到主角或者目標,然後就可以實時地預覽遊戲內效果,不僅包含了技能表現,也包含了結算等數值結果。同時開啟技能編輯器的除錯資訊開關,還可以繪製出技能結算的碰撞檢測範圍和技能位移路徑,將選點、結算範圍、路徑等資料視覺化,讓策劃一眼看出技能配置是否符合預期
另外,我們還提供了技能流程的視覺化能力,當繫結到施法角色時,技能執行過程中會高亮當前正在執行的技能節點,同時將客戶端和服務端通訊的網路訊息日誌列印出來,可以幫助開發快速定位技能bug。
3.2 工具開發總結
工具開發對於提高效率的幫助是巨大的。對於一個設計好的資料驅動的系統,雖然新功能的開發可以完全交給策劃去配置驗證,但是如果配置完的資料需要重新啟動載入,重新走登入流程看效果,那麼除錯的成本會非常高。方便快捷的熱更新功能和遊戲內視覺化能力,對於技能系統這樣的實時模組而言重要性不言而喻。在新專案中應用的這一套技能製作管線,對比我們專案組已上線的一款MMORPG手遊中傳統的技能製作方式,效率有了數量級的提升。
四、總結
對於Gameplay程式設計師而言,如何將策劃的需求抽象成一個資料驅動的系統,並配套開發相應的製作管線,將成為一種核心能力。