遊戲中的技能系統設計

遊資網發表於2019-10-17
遊戲中的技能系統設計

在絕大多數包含戰鬥要素的遊戲中,技能系統是相對比較複雜和關鍵的系統,尤其是在某些強調豐富的技能、種類繁多的武器裝備以及爽快的打擊感為主的遊戲中,如何讓玩家體驗到震撼的攻擊場面,技能系統設計的好壞直接會影響遊戲的遊玩體驗。從巨集觀來看,遊戲技能系統就是程式、美術、音效、策劃數值的綜合表現。但如何設計出一個易於擴充套件、安全健壯的技能系統,卻又是一個複雜而又系統的工程。如何通過技能系統實現《鬼泣》、《獵天使魔女》這種爽快打擊感的ACT遊戲,如何通過技能系統實現《DOTA2》、《英雄聯盟》這類易於擴充套件的MOBA遊戲的技能和裝備系統,如何實現《星際爭霸》、《命令與征服》這類RTS遊戲中大規模群體戰鬥的技能機制?

Dota2:資料驅動類技能

得益於Dota2自帶的編輯器,通過玩家的手在DOTA2的創意工坊中有很多有趣有好玩的Mod,比如《進化島》、《大亂鬥》等等,這其中更是誕生了風靡全球的《DOTA自走棋》。這些Mod的誕生也從另一個角度證明了DOta2的技能系統和編輯器設計的優秀。

從DOTA2的開發者文件中可以看出其技能系統採用的是”資料驅動“的方式,資料驅動技能是一組鍵值KeyValue資料,這是一種簡單的樹狀結構,來儲存包含了一組組可巢狀的鍵及其對應值的資料。Dota2通過C++編寫的介面來讀取技能描述檔案,這些描述檔案是一種KV(Key-Values)結構的資料,開發者通過編寫這些KV(Key-Values)結構的資料來實現不同技能效果的組合。

遊戲中的技能系統設計
Dota2地圖編輯器

Dota2中定義的基本鍵值如下:

  1. "datadriven_skeleton"
  2. {
  3.     // General  
  4.     // ----------------------------------------------------------------------------------------
  5.     "BaseClass"              "ability_datadriven"
  6.     "AbilityBehavior"        "DOTA_ABILITY_BEHAVIOR_UNIT_TARGET"
  7.     "AbilityTextureName"     "spellicon"
  8.     "AbilityUnitTargetTeam"  "DOTA_UNIT_TARGET_TEAM_ENEMY"
  9.     "AbilityUnitTargetType"  "DOTA_UNIT_TARGET_HERO | DOTA_UNIT_TARGET_BASIC"
  10.     "AbilityUnitTargetFlags" "DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES"
  11.     "AbilityUnitDamageType"  "DAMAGE_TYPE_MAGICAL"
  12.     "AbilityType"            "DOTA_ABILITY_TYPE_BASIC"
  13.     "MaxLevel"               "7"
  14.     "RequiredLevel"          "-4"
  15.     "LevelsBetweenUpgrades"  "7"
  16.     "AbilityCastPoint"       "0.0"
  17.     "AbilityCastAnimation"   "ACT_DOTA_ATTACK"
  18.     "AnimationPlaybackRate"  "1"
  19.     "AnimationIgnoresModelScale" "1"
  20.     // Stats
  21.     //----------------------------------------------------------------------------------------
  22.     "AbilityDamage"           "0 0 0 0"
  23.     "AbilityManaCost"         "0 0 0 0"
  24.     "AbilityCooldown"         "0.0 0.0 0.0 0.0"
  25.     "AbilityCastRange"        "0"
  26.     "AbilityCastRangeBuffer"  "250"
  27.     "AbilityChannelTime"      "0.0 0.0 0.0 0.0"
  28.     "AbilityChannelledManaCostPerSecond" "30 35 40 45"
  29.     "AbilityDuration"         "0.0 0.0 0.0 0.0"
  30.     "AoERadius"               "250"

  31.     // ...
  32. }
複製程式碼

  • Base Class:基類必須是任意原版dota技能或者"ability_datadriven"
  • AbilityBehavior:技能行為,技能型別描述了技能如何生效,生效後具體如何執行。可以同時使用多個不同型別,使用空格和|符號分割。
  • AbilityTextureName:技能圖示,用於在UI上展示。
  • AbilityUnitTargetTeam:目標隊伍,全部、友軍、敵人等等。
  • AbilityUnitTargetType:目標型別,隱藏單位、召喚單位、建築等等。
  • AbilityUnitTargetFlags:目標標籤,標籤允許對預設被忽略的目標單位(例如魔法免疫敵人)施法,或者忽略特定的單位型別(例如遠古單位和魔免友軍)來允許對其施法。
  • AbilityUnitDamageType:傷害型別,魔法傷害、物理傷害、純粹傷害。
  • AbilityType:技能型別,用於區分“普通技能”、“終極技能”、“獎勵技能”等等。
  • MaxLevel:最大等級。
  • RequiredLevell:第一次可以學習技能的英雄等級。這個值設定為負值可以讓技能在任意等級開始被學習。
  • LevelsBetweenUpgrades:升級下一級技能需要提升多少英雄等級。
  • AbilityCastPoint:技能釋放的中心點。
  • AbilityCastAnimation:技能釋放動畫。
  • AnimationPlaybackRate:動畫播放速度。
  • AnimationIgnoresModelScale:
  • AbilityDamage:技能傷害,對應每一個提升等級。
  • AbilityManaCost:魔法消耗,對應每一個提升等級。
  • AbilityCooldown:冷卻時間,對應每一個提升等級。
  • AbilityCastRange:技能釋放範圍。
  • AbilityCastRangeBuffer:技能釋放範圍緩衝,當目標離開釋放範圍+這個值時,法術就會取消。
  • AbilityChannelTime:施法時間,
  • AbilityChannelledManaCostPerSecond:每秒魔法消耗,用於在持續施法時新增一個額外的魔法消耗。
  • AbilityDuration:持續時間。
  • AoERadius:AOE範圍。
  • 其他一級鍵值:技能共享冷卻時間AbilitySharedCooldown、隊友共享技能AbilitySharedWithTeammates、技能黃金消耗AbilityGoldCost、技能升級黃金消耗AbilityUpgradeGoldCost,等等。


以下是一個簡單的Dota2技能,技能被新增之後,將會等到擁有者死亡之後觸發,當擁有者死亡的時候,一個帶有酸霧特效和一個降低目標區域的單位護甲並施加傷害的計時器將會被建立。

  1. //=================================================================================================================
  2. // Creature: Acid Spray
  3. //=================================================================================================================
  4. "creature_acid_spray"
  5. {
  6. // General
  7. //-------------------------------------------------------------------------------------------------------------
  8. "BaseClass"                                         "ability_datadriven"
  9. "AbilityBehavior"                                "DOTA_ABILITY_BEHAVIOR_AOE"
  10. "AbilityUnitDamageType"                        "DAMAGE_TYPE_COMPOSITE"
  11. "AbilityTextureName"                        "alchemist_acid_spray"
  12. // Casting
  13. //-------------------------------------------------------------------------------------------------------------
  14. "AbilityCastPoint"                                "0.2"
  15. "AbilityCastRange"                                "900"
  16. "OnOwnerDied"
  17. {
  18.    "CreateThinker"
  19.    {
  20.     "ModifierName" "creature_acid_spray_thinker"
  21.     "Target" "CASTER"
  22.    }
  23. }
  24. "Modifiers"
  25. {
  26.   "creature_acid_spray_thinker"
  27.   {
  28.    "Aura" "create_acid_spray_armor_reduction_aura"
  29.    "Aura_Radius" "%radius"
  30.    "Aura_Teams" "DOTA_UNIT_TARGET_TEAM_ENEMY"
  31.    "Aura_Types" "DOTA_UNIT_TARGET_HERO | DOTA_UNIT_TARGET_CREEP | DOTA_UNIT_TARGET_MECHANICAL"
  32.    "Aura_Flags" "DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES"
  33.    "Duration" "%duration"
  34.    "OnCreated"
  35.    {
  36.     "AttachEffect"
  37.     {
  38.       "EffectName" "alchemist_acid_spray"
  39.       "EffectAttachType" "follow_origin"
  40.       "Target" "TARGET"
  41.       "ControlPoints"
  42.       {
  43.        "00" "0 0 0"
  44.        "01" "%radius 1 1"
  45.       }
  46.      }
  47.     }
  48.    }
  49.    "create_acid_spray_armor_reduction_aura"
  50.    {
  51.     "IsDebuff" "1"
  52.     "IsPurgable" "0"
  53.     "EffectName" "alchemist_acid_spray_debuff"                               
  54.     "ThinkInterval" "%tick_rate"
  55.     "OnIntervalThink"
  56.     {
  57.       "Damage"
  58.       {
  59.        "Type" "DAMAGE_TYPE_COMPOSITE"
  60.        "Damage" "%damage"
  61.        "Target" "TARGET"
  62.       }
  63.      }
  64.      "Properties"
  65.      {
  66.        "MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS" "%armor_reduction"
  67.      }
  68.     }
  69.    }
  70. // Special       
  71. //-------------------------------------------------------------------------------------------------------------
  72. "AbilitySpecial"
  73. {
  74.   "01"
  75.   {
  76.    "var_type"                                "FIELD_INTEGER"
  77.    "radius"                                "250"
  78.   }
  79.   "02"
  80.   {
  81.    "var_type"                                "FIELD_FLOAT"
  82.    "duration"                                "16.0"
  83.   }
  84.   "03"
  85.   {
  86.    "var_type"                                "FIELD_INTEGER"
  87.    "damage"                                "118 128 138 158"
  88.   }
  89.   "04"
  90.   {
  91.    "var_type"                                "FIELD_INTEGER"
  92.    "armor_reduction"                        "-3 -4 -5 -6"
  93.   }
  94.   "05"
  95.   {
  96.    "var_type"                                "FIELD_FLOAT"
  97.    "tick_rate"                                "1.0"
  98.   }
  99. }
  100. }
複製程式碼

從以上程式碼中可以看出,一個典型的DOTA2技能資料包括以下幾個部分:

1.技能行為:使技能有不用的釋放方式,如:持續性施法、被動技能、指向性技能等等能。

2.技能觸發的事件和操作:技能可以有各種遊戲中的事件,這些事件可以觸發操作,如:當技能施法開始、當持續施法完成、當施法者死亡等等。

3.操作目標:技能釋放的目標,如:單體目標、多目標等等。

4.Modifiers:該屬效能夠改變對應Modifier影響的單位的遊戲相關數值,如:所有魔法攻擊無效、所有物理攻擊無效、修改基礎攻擊力、修改攻擊速度等等。

5.AbilitySpecial:技能特殊定義,這個部分有兩個作用:1.定義隨著技能升級改變的值,基於"%value";2.格式化的文字提示,可以顯示此處定義的值,用於滑鼠懸停時的提示資訊。

其中Modifiers、AbilitySpecial並不是必須的,有些技能並沒有這兩塊的定義。通過Dota2定義好的技能鍵值和開放出來的API,玩家可以使用Lua重新設計Dota2的技能和英雄行為。不僅是Mod作者可以利用這些方法制作出各種地圖,Dota2本身的許多技能和英雄也是使用這種方式製作的。

星際爭霸2:ABE結構的技能系統

《星際爭霸2》作為一款風靡一時的RTS遊戲,其自帶的地圖編輯器也同樣出名,這款編輯器也稱為“銀河引擎”,得益於暴雪專門為其開發了一套指令碼語言,稱為基於C的Galaxy,似乎所有GUI介面上的編輯器操作,都可以完整的對應成一段Galaxy指令碼。通過這款編輯器玩家甚至還原了“暗黑破壞神”,這其中也誕生了《沙漠風暴》這樣擁有一大批忠實玩家的地圖。

遊戲中的技能系統設計
銀河引擎的資料編輯器

星際2的整個資料物件都是通過XML進行配置的,編輯器讀取這些XML檔案,在檢視介面以樹狀形式。

遊戲中的技能系統設計
女妖隱形的XML

遊戲中的技能系統設計
物件檢視(女妖的隱形)

一個典型的星際2技能包含以下幾個部分:

  • Abilities(能力):Ability就是一個單位可以做的事情。比如:攻擊,移動,建造之類。
  • Effects(效果):Effect是讓一件事情發生。它是Aiblity幕後的實現,可以增加Buff,產生傷害,治療單位等。
  • Behaviors(行為):效果產生的行為,常見的是“Buff”,是附加到單位並以某種方式影響它的東西。諸如:提高移動速度,禁用武器,有機會阻擋傳入的傷害等等。


Abilities中定義了技能的基礎資料,這些基礎資料最終提供給Effects,而Effects又會產生其他的Effects或Behaviors,可以看出星際2的技能是一種樹狀結構。

UE4:Gameplay Ability System

對於大多數RPG或MOBA類遊戲遊戲,無論是Dota2中釋放一個技能,然後該技能會擊中單位,造成一定量的傷害,並對目標半徑內的所有單位隨時間造成傷害,同時,釋放技能的的玩家會失去一些法力並處於冷卻狀態;還是在星際爭霸2中高階聖堂釋放靈能風暴對某一區域持續性產生傷害,該傷害又會產生其他效果。這些都需要一個高效靈活的技能框架,而UE4中的Gameplay Ability System正是為此而設計的,EPIC的多款3A級的遊戲中都得到過應用,如Paragon和Fortnite等。

以下是官方解釋:

Gameplay技能系統是一個高度靈活的框架,可用於構建你可能會在RPG或MOBA遊戲中看到的技能和屬性型別。你可以構建可供遊戲中的角色使用的動作或被動技能,使這些動作導致各種屬性累積或損耗的狀態效果,實現約束這些動作使用的“冷卻”計時器或資源消耗,更改技能等級及每個技能等級的技能效果,啟用粒子或音效,等等。

該外掛主要有以下幾個類:

  • GameplayAbility:能力,定義C++程式碼或藍圖指令碼中技能的實際作用,並建立處理技能的元素,如複製和例項化行為。
  • GameplayTask:任務,在定義技能的邏輯過程中,gameplay技能中的邏輯通常會呼叫一系列被稱為技能任務非同步編譯塊。技能任務衍生自抽象UAbilityTask類,以C++編寫。其完成操作時,會基於最終結果頻繁呼叫委託(C++中)或輸出執行引腳(藍圖中)(例如,需要目標的技能需進行“瞄準”任務,將呼叫一個委託或輸出引腳確認目標,並呼叫另一引腳取消技能)。
  • GameplayAttribute:屬性,Gameplay屬性是儲存在FGameplayAttribute結構中的“浮點”值,將對遊戲或Actor產生影響;其通常為生命值、體力、跳躍高度、攻擊速度等值。
  • GameplayEffect:效果,Gameplay效果可即時或隨時間改變Gameplay屬性(通常稱為“增益和減益”)。例如,施魔法時減少魔法值,啟用“衝刺”技能後提升移動速度,或在治療藥物的效力週期內逐漸恢復生命值


該外掛在單人和多人遊戲中提供了開箱即用的解決方案:

  • 通過可選的消耗和冷卻時間來實施基於等級的角色能力或技能(GameplayAbilities)
  • 處理Attributes中的數值到Actors(Attributes)
  • 將GameplayEffects應用於Actors(GameplayEffects)
  • 應用於GameplayTags應用於Actors(GameplayTags)
  • 產生視覺或聲音效果(GameplayCues)
  • 網路同步,將資料同步到其他客戶端


在多人遊戲中,GAS支援以下方面的客戶端預測:

  • 啟用能力:啟用某一個技能。
  • 播放動畫蒙太奇:播放技能動畫。
  • 改變Attributes:改變角色身上的屬性,如:增加攻擊、增加血量。
  • 應用GameplayTags:展示技能釋放後的狀態,如:冷卻時間、魔法消耗。
  • 生成GameplayCues:顯示技能釋放後的表現,如:施法特效、聲音。
  • 通過RootMotionSource連線到帶有CharacterMovementComponent功能的Actor控制其移動。


以下是GAS的UML圖,可以看出其結構還是很清晰的,主要功能需要在C++中設定,GameplayAbilities和GameplayEffects可以通過藍圖擴充套件。

遊戲中的技能系統設計
GAS的UML

參考文件:

1.Valve Developer Community:https://developer.valvesoftware.com/wiki/Dota_2_Workshop_Tools:zh-cn/Scripting:zh-cn/Abilities_Data_Driven:zh-cn

2.Dota2 Wiki-資料整理版:http://nobuoldman.github.io/#Accessing_the_DOTA_2_Scripting_API_from_Lua

3.Unity3D自學筆記——星際2技能系統分析(三)Ability(Effect):https://blog.csdn.net/alistair_chow/article/details/53325404

4.GASDocumentation:https://github.com/tranek/GASDocumentation#concepts-asc

作者:木林
專欄地址:https://zhuanlan.zhihu.com/p/83817526

相關文章