如何实现一个强大的MMO技能系统——技能
图文教程技术文章技术文库技术综合 1807 1
实名

通过了实名认证的内容创造者

发布于 2021-4-30 10:28:54

您需要 登录 才可以下载或查看,没有账号?注册

x
前言
一个完整的技能系统逻辑层主要包括三个模块:技能模块,buff模块,projectile(子弹)模块。然而在很多项目中,这三个模块可能并不是同一个人负责的,所以会发现这些模块间的联系并不够紧密,然而技能的需求是非常复杂的,这样就有可能随着技能需求的越来越复杂,每个模块都搞了一套自己的脚本化的逻辑,最后维护难度急剧增加,导致开发成本大大提高。本章将主要讲述一个高扩展性的技能模块该如何设计,使得技能支持尽可能多的效果,同时又能够保持架构的精简和高扩展性。
v2-746b8d3fc8c2e75ac9ec8fad98405b7f_1440w.jpg
正文
首先,我们大致思考一下平常玩的游戏,大致会发现有如下几种技能类型:
  • 被动类型的技能(PassiveAblity)
  • 主动施法技能(最常见的通用主动施法类技能,如普通攻击等一次性触发效果类技能(GeneralAbility),引导类持续施法技能(ChannelAbility),如大法师暴风雪)
  • 开关类技能((ToggleAbility)点击技能开启/关闭效果,类似于恶魔猎手献祭)
  • 激活类技能((ActivateAbility)点下右键激活/停止,一般是给普通攻击附加特殊效果)
在这里我们采用标记位(可进行或操作)的形式来表明这些技能的类型。这意味着一个技能可能被检测既是被动又是引导类技能(我们将在最后的示例部分讲述为什么需要这样设计)。
下面我们一步步讲解这些技能类型该如何设计。在我们的技能系统中,所有的技能里面不包含任何具体技能效果及逻辑,每个技能根据其类型提供若干抽象接口,具体执行效果由策划去配置。
当一个技能标记为被动技能时,则它是被动技能,被动技能一般会在技能初始化时生效,技能初始化时会有抽象行为接口Ability::OnAbilityInit()。那么被动技能就可以在这个接口中执行一些行为,具体执行那些功能由策划配置,一般情况下策划会配置给角色添加Buff来监听各种事件以触发各种效果。那么技能的各种效果该如何实现呢?我们将在下一章buff系统中讲到。
当一个技能标记为主动施法的技能时,它可手动释放,同时在施法前需要有目标信息,这里一般有三种情况:
  • 技能释放时不需要目标即可释放(如群疗,踩地板技能) -> 1 << 1
  • 技能释放时需要选定目标(单体指向性技能) -> 1 << 2
  • 技能释放时需要以指定地点为目标(常用于AOE技能) -> 1 << 3
虽然技能系统千变万化,但是初始阶段选择目标就是这三种情况的组合。有些复杂的技能会有两种组合情况:
比如策划有个需求是闪现技能,如果当前没有选择目标就朝前方闪现五米,有目标时则闪现到目标身后。则我们的目标选择配置项就是1|2,当释放技能的时候我们保存下当前的目标信息(有无目标),后续在技能效果执行的时候去获取目标是否存在,然后实现不同的效果。(Dota2中Lion的穿刺和先知的招树就是2|3。)
如果标记为普通施法技能,我们将技能划分为如下几个阶段:
v2-dab99247f856a3a9a2f4903e6214e70e_720w.jpg
当我们满足技能释放的各种前置条件检查后,会进入如下几个阶段:
  • 技能起手Ability::OnAbilityStart(),这个时候通常情况下策划一般配置为播放动画,技能开始转CD,执行完成后技能进入前摇阶段。
  • 技能前摇阶段不允许其他技能释放,除非技能可强制立即释放(bImmediately=true)(如有些游戏要求滚动还有解控技可以立即打断当前技能)。前摇阶段提供一个配置时长CastPoint(Spell时间点),一般为动画抬手到攻击帧时长。比如说播放一个挥刀动画0.3秒后动画到攻击点,这时策划就配置CastPoint为0.3秒。
  • Spell阶段一般为技能具体逻辑执行阶段。通常会根据配置选择相应目标造成相应效果。当执行完操作之后进入后摇阶段。
  • 后摇阶段一般不能被其他技能打断,除非是连招或者强制立即释放类技能。我们的技能系统不需要引入公共CD这个概念,通过前摇后摇阶段的划分就足够满足各种需求了。
如果标记为持续施法类技能(Channel),我们将技能分为如下几个阶段:
  • 起手前摇阶段同普通技能。
2. 引导阶段提供3个接口供策划配置逻辑(ChannelStart, ChannelThink, ChannelFinish),提供两个时间参数以供配置:ThinkInterval (引导触发间隔)及 ChannelTime(引导阶段总时长)。如策划配置CastPoint为0.1秒,ThinkInterval为0.3秒,ChannelTime为1.4秒时。则技能将会在AbilityStart0.1秒后调用ChannelStart,将在第0.4秒->0.7秒->1.0秒->1.3秒调用ChannelThink,将在第1.5秒调用ChannelFinish。这样的接口设计在保证简洁的情况下基本能覆盖几乎所有的需求。
3.后摇阶段同普通技能。
如果标记为开关类技能,我们提供两个接口:OnAbilityToggleOn和OnAbilityToggleOff,一般通过调用添加/移除buff实现具体效果。
如果标记为激活类技能,我们提供两个接口:OnAbilityActivate和OnAbilityDeactivate,一般通过调用添加/移除buff实现具体效果。
总结
本章主要讲述技能的类型和阶段划分。通过良好的阶段划分和逻辑抽象就可以让技能有非常高的扩展性,这样在后续的开发中仅仅只需要做一些功能的扩展,而不会影响整体的架构。
示例
我会举出一些常见而特殊的技能例子,以便让读者有个直观的理解。
  • 问:如果被动触发后会进入CD,此时被动不再生效如何实现?(Dota2白牛重击效果)答:策划在被动触发时配置StartCooldown(duration)即可,技能的CD是个可配置行为,执行StartCooldown就转CD,什么技能都能走CD,而且可以在任意情况下走CD。走不走CD策划看着配就行。技能走CD后然后在被动行为里面检测技能是否在CD状态,如果在CD状态则不执行任何效果。
  • 问:技能既可以主动释放又能有被动效果如何实现?(Dota2敌法师护盾)答:被动效果其实是由Buff具体负责监听各类事件触发效果,主动技能也能在OnAblityInit的时候执行行为,策划在此处配置加buff就行了。那么问题继续来了,如果有一个效果是禁用被动技能的话,前面的带被动效果的主动类型技能该不该禁用呢?答:这时候技能类型为标记为位(bit)的作用就体现出来了,如果标记为被动(AbilityFlag & AbilityPassive为true)的话就禁用。
  • 问:蓄力类技能也是一种常见的技能类型啊,为什么没有被提到?答:蓄力类技能在我们的技能系统中直接简化为普通技能了。它只需要策划在技能抬手的时候播一个蓄力动画,然后CastPoint配成蓄力时长,在Spell的时候再播一个动画就行了。继续问:那蓄力后的攻击动画到攻击效果还有一个间隔时长怎么办?继续答:配置技能为引导类技能,例如配置ChannelInterval为10000秒,ChannelTime为0.3秒,这样技能引导阶段就只调用ChannelFinish,蓄力的效果在ChannelFinish里面触发即可。
  • 问:各类轻功,击退,击飞,冲刺攻击等各种位移效果怎么实现,他们之间万一存在各种复杂的打断规则又怎么处理?答:我们通过Buff去改变角色运动,状态,属性等。下一章将会具体讲述这些情况。

评分

参与人数 2元素币 +20 活跃度 +26 展开 理由
元素界王神... + 20 + 11 【点赞】这很有大网气质!
元素小行家... + 15 可以啊!值得一看

查看全部评分

还没有设置签名!您可以在此展示你的链接,或者个人主页!
使用道具 <
仙剑_3  发表于 2021-4-30 14:39:56  
2#
666666666
回复 收起回复
使用道具
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表