前两周写完了新游戏的技能系统。虽然也算灵活,但是跟Dota2的技能系统设计比起来,就差了很多。无论从灵活性还是功能实现上,其技能系统设计的都相当漂亮。如果早一些分析它的技能系统的话,我想我可以实现的更快更好。
与之类比还有一些游戏,其技能系统设计的也很漂亮,比如魔兽争霸3 火炬之光2 星际争霸2,它们都很灵活,从其众多的MOD就可以看出来,甚至MOD的作者可以做出游戏开发者想象不到的华丽效果。它们也有对应的编辑器可以进行分析和研究。
Dota2的技能系统是数据和脚本来驱动的。配置文件是v社自己定义的格式,我们可以用json来替代。脚本是lua,这个其实要比暴雪自己创作一个新的脚本语言要简单和清晰的多。
"bounty_hunter_wind_walk_2" { "BaseClass" "ability_datadriven" "AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IMMEDIATE | DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL" "AbilityUnitDamageType" "DAMAGE_TYPE_PHYSICAL" "AbilityTextureName" "bounty_hunter_wind_walk" // Time //------------------------------------------------------------------------------------------------------------- "AbilityCooldown" "15.0 15.0 15.0 15.0" "AbilityCastPoint" "0.0 0.0 0.0 0.0" // Cost //------------------------------------------------------------------------------------------------------------- "AbilityManaCost" "50 50 50 50" "OnSpellStart" { "AttachEffect" //创建特效 { "EffectName" "particles\units\heroes\hero_bounty_hunter\bounty_hunter_windwalk.vpcf" "EffectAttachType" "follow_origin" "Target" "CASTER" } "FireSound" //播放声音 { "EffectName" "Hero_BountyHunter.WindWalk" "Target" "CASTER" } "ApplyModifier" //添加去除隐身的触发modifier { "Target" "CASTER" "ModifierName" "modifier_bounty_hunter_wind_walk_2" } "RunScript" //在脚本里面启动隐身 { "ScriptFile" "scripts/vscripts/ability.lua" "Target" "CASTER" "Function" "bounty_hunter_wind_walk_2" } } "Modifiers" { "modifier_bounty_hunter_wind_walk_2" { "Duration" "%duration" "IsHidden" "1" "OnAttack" //攻击就去除隐身并且造成额外伤害 { "RunScript" { "ScriptFile" "scripts/vscripts/ability.lua" "Target" "UNIT" "Function" "bounty_hunter_wind_walk_2_attack" } } "OnAbilityExecuted" //施放技能就去除隐身 { "RunScript" { "ScriptFile" "scripts/vscripts/ability.lua" "Target" "UNIT" "Function" "bounty_hunter_wind_walk_2_attack" } } } } // Special //------------------------------------------------------------------------------------------------------------- "AbilitySpecial" { "01" { "var_type" "FIELD_FLOAT" "duration" "20.0 25.0 30.0 35.0" } "02" { "var_type" "FIELD_FLOAT" "fade_time" "1.0 0.75 0.5 0.25" } "03" { "var_type" "FIELD_INTEGER" "bonus_damage" "30 60 90 120" } } }
技能配置是可以override的。通过AbilityCooldown等字段可以描述技能的基本信息,如它的目标是什么类型的,冷却时间多少,消耗魔法多少。
"OnSpellStart"是一系列的事件回调,其他如OnAttack OnProjectileHit等等,他们可以在特定的事件回调。
在事件回调内部可以通过一些列Action来描述具体行为,如AttachEffect就是添加光效, FireSound就是播放声音, Damage就是造成伤害, Stun就是眩晕。 Damage和Stun中又可以指定目标是施法者还是受击者,范围是什么,伤害值和眩晕时间多少等等。
比较重要的还有AddModifier,Modifier可以理解为Buff,它可以包含一组Properties,它们是具体的行为,如攻击速度增加50%,伤害增加100等等。 Modifier内部也可以有一系列回调,如OnCreate,可以在合适的时机执行更加复杂的组合效果。
另一个重要的部分是RunScript,通过lua脚本,可以轻易实现程序默认没有实现的行为。比如每秒造成xx伤害,或者受击目标越多,伤害越大。
通过EventCallback----Action----Modifier----Script的体系来实现的技能系统,具备非常强的扩展性。添加新技能就是一些列这些元素的组合。而添加新的效果也不会对整个技能系统造成影响。 其他的东西都是在此基础上的元素,比如发射抛射物就是一个Action,抛射物如果击中使人眩晕就加一个Stun的动作或者是一个Modifier。如果需要特殊的判定如每击中一个人伤害增加10%,那么就添加对应的Script,在OnProjectileHit里面进行调用。