我利用了组合模式、观察者模式和模板方法模式。

我有几个主要组件,WizardBase、AbilityBase、AbilityObjectBase、AbilityScriptableObject和WizardScriptableObject。

WizardBase:
- 它的职责是保存所有可用的技能,对特定角色可用,编辑时可以指定哪些技能可用,可以触发技能/冷却和管理可用技能。
它也处理技能区域,其他技能可以使用它来调用不同的技能区域,并提供对其他玩家相关组件的访问。
FireWizard、EarthWizard继承WizardBase来过滤什么技能可以附加到它上面。

AbilityBase:
- 它的职责是封装特定技能逻辑,它作为玩家/NPC上的组件,提供可覆盖的模板方法,以允许自定义逻辑。
它也使用IInput接口订阅事件,如onClickPress、onClickRelease,这些事件用于实现基于用户输入的自定义交互。
它也提供了方法来在技能激活/禁用时运行逻辑,在魔法激活/禁用时也提供了方法,在技能使用期间清理创建的所有东西,如一个free()方法。
EarthAbilityBase、FireAbilityBase继承AbilityBase,然后所有游戏技能都继承其中一个,例如Earth_ThrowRock继承EarthAbilityBase。

AbilityObjectBase:
- 这是可选的,如果技能需要创建长时间运行的动作,则可以从AbilityBase中添加一些额外的逻辑,然后将其迁移到AbilityObjectBase中,而AbilityBase仅用于输入事件和清理,然后发出AbilityObjectBase,这个技能持有其他自定义逻辑。
例如,EarthArmor、EarthThrowRock和FireShieldProjection也使用AbilityobjectBase来实现长时间技能,但FireHotWave不需要,因为它仅执行一次。

现在,如果我想添加一个新角色,例如水之主,带20种技能。

我首先创建一个新角色,WaterWizard,并继承WizardBase。
我创建一个新的WaterAbilityBase,并继承AbilityBase。
然后我覆盖WaterWizardBase中的一些方法,仅允许WaterAbilityBase组件。
然后我创建一个新的WizardScriptableObject,它保存角色数据,元素ID、默认技能、图标、颜色等。
然后我添加一个角色对象,并将WaterWizard组件添加到该对象上。
然后,我开始创建新的组件和技能数据对象,用于所有20种水之主的技能。
WaterWave、WaterSplash等。
能力数据对象包含技能数据,如伤害值、攻击类型、防御还是进攻技能、技能类型等。
然后我将所有20种技能组件添加到水之主角色上,它有水之主组件,那么在游戏运行时,它会选取所有类型为WaterAbility的组件。
能力组件没有更新方法,所以不会消耗CPU资源。

然后,装备菜单自动检测新的角色和技能,对角色中的技能进行设置,对技能进行激活。
总体来说,添加新角色需要30分钟,添加新技能需要1-3小时,取决于是否还需要制作自定义艺术。
它们依赖抽象的IInput处理器,所以不论触发事件的方式如何,都可以使用行为树、鼠标或键盘触发。
唯一的区别是,如果技能附加在NPC上,我会在服务器端订阅IInput接口事件,而不是在客户端。
总体来说,我非常高兴如此,这些设想将基本上增加一个技能的数量,可悲的是我已经几乎没有灵感了..