欢迎光临散文网 会员登陆 & 注册

在Unity中制作完整的技能系统(代码篇)

2022-06-01 14:28 作者:皮皮关做游戏  | 我要投稿

哈喽~又是我暴躁老哥酒九。

上期文章向大家介绍了一下技能系统的思路和使用方法。那么话不多说,接下来就是有关这些功能都是如何实现的。整整整。

场景搭建和角色素材这些操作大家就自己去选择准备吧。素材准备工作做好之后,我们就可以开始编写具体的脚本了。

新建项目,新建一个文件夹命名为SkillSystem,之后我们技能系统所有的脚本就放在这里面了(养成收拾脚本的好习惯)。

PS:接下来的所有脚本我们都统一放进一个命名空间中,我这里命名为MOBASkill,后面代码中就不单独写出来了。

1、系统总体规划

我们再来捋一捋技能系统的各个模块之间是怎么互相作用的。

每一个拥有技能的角色身上,都会有一个技能管理器负责该角色的技能数据存放和生成对应技能的预制体。在我们生成技能预制体(释放技能)的同时,对应的技能预制体身上挂载好的技能释放器就会在释放器配置工厂中找到对应的效果算法和目标选择算法,并且执行算法中的代码,完成查找敌人并对敌人产生对应的效果,最后销毁预制体本身。

这就是一次完整的技能释放流程。

2、技能数据类(SkillData)

我们新建脚本命名为SkillData,将技能中需要的数据都写在这个数据类中。大家可以根据自己的设计想法来添加,我就不过多啰嗦,看着代码讲。




这里有几个变量需要单独说一说作用:

1.attackTargetTags和attackTargets,咋一看这两个变量的作用似乎是一样的,但前者表示的是在释放技能之前该技能可以作用于哪些物体上(敌人,队友,建筑等),后者则会在执行技能范围选择算法之后返回在技能范围中的敌人(实际攻击到的目标)。

2.owner这其实就是挂载管理器的物体自己,在后续算法中可以更方便的调用本身的数据,方法或者组件等。

3.skillIndicator是成功释放技能之前显示出来的辅助技能释放的工具。

PS:通常我们定义了公有变量之后就会在Inspector窗口中生成对应的输入框,而当在变量前加上[HideInInspector]之后就会该公有变量就不会在Inspector中显示。

3、技能管理器(SkillManager)

技能管理器的作用就是存好人物的所有技能数据,初始化技能数据中未填写的部分(owner,skillPrefab,hitFxPrefab),准备技能,生成技能等。因此,首先我们需要准备一个数组来存放人物的全部技能,根据数据中的预制体名字(prefabName,hitFxName)给对应的GameObject赋值的方法,生成技能时各种内容等。来看看代码。




这里对于能否释放技能的条件有:

该技能ID是否存在;

技能的是否完成冷却(利用剩余冷却时间是否为0来判断);

技能所需的消耗值玩家的对应数值是否足够。

大伙儿可以根据自己的需求来添加删除条件。举个例子:一个技能拥有三段释放,那么就可以将“上一段技能是否释放”来作为条件实现。生成技能这里我使用了对象池,大家也可以改成普通的实例化。后面的技能冷却则是通过协程实现的。

4、释放器配置工厂(DeployerConfigFactory)

根据之前的技能流程图,我们可以发现:在技能管理器中释放技能的操作其实只有“实例化预制体”和“将技能数据传入释放器中”,而实际的选取敌人、执行技能效果都是在释放器中来完成的。那技能释放器是怎么知道要用哪些算法的呢?我们可以看到技能数据中有两个变量impactType和selectorType。这两个变量中都存放的是字符串内容,那么我们就通过这些字符串内容来获取到对应的算法。这些操作由释放器配置工厂来完成。

先准备好技能范围选择算法和效果算法的接口:




接下来所有的相关算法都是先继承这两个接口,再编写具体的逻辑。

现在来看释放器配置工厂。




在类中我们用CreateObject方法来根据字符串变量找到对应的算法,主要操作就是使用泛型(T)并且将我们的泛型约束为引用类型(where T : class),根据前文提到的算法的字符串变量的Type来创建对应类型的方法。而CreateAttackSelector和CreateImpactEffects两个方法就是把算法名补全之后返回指定接口类型的方法。

PS:这里的Activator.CreatInstance作用是用与指定参数匹配程度最高的构造函数来创建指定类型的实例。通俗的讲就是按照参数给出方法,不过它返回的是object类型,所以要转化成我们需要的类型(as T)。

5、技能释放器(SkillDeployer)

解决了根据数据生成算法的问题之后,在技能释放器中就只需要初始化释放器算法并且调用相应的算法就好了,代码如下:




这里释放器就可以作为所有释放器的父类,如果有释放情况的不同,就继承他在子类中进行重写方法。比如前文提到的:近战技能释放是如何释放,远程技能释放又是怎样的等等,这里就交给大家自己完成啦。




6、技能范围选择算法(Selector)

顾名思义,这里要完成的内容就是将在规定范围中的敌人全部选择出来。给大家演示一下扇形范围的敌人检测。上代码。




说明一下整体的流程。首先我们根据技能数据中的attackTargetTags中的Tag找到所有带有该Tag的物体,再通过一个列表的FindAll方法来找符合条件的敌人,再返回一个数组到技能数据的attackTargets中去。这样就完成了敌人的查找。

PS:1.脚本名是一定要与释放器配置工厂中的命名规则一致,否则无法找到。在这里范围选择算法名为xxxSkillSelector,而效果算法名应该为xxxImpactEffect。2.在FindAll中使用了Lamda表达式来完成条件的限制,Vector3.Distance负责在攻击距离内,Vector3.Angle负责在攻击角度内。3.这里还需要大家自己添加上敌人是否存活的选择条件判断、技能目标为单个或多个的返回情况等。

7、技能效果算法(Impact)

技能的效果就有很多了。可以是回复血量,消耗法力值,减少血量等等,大家可以根据自己的需求来自行编写。这里的例子是给敌人添加一个击飞Buff。




为什么要用协程来持续检测敌人呢?

因为这个技能是一个冲撞技能,在玩家向前位移的整个时间范围内检测到的敌人都会被添加击飞的Buff。BuffManager是一个简单Buff系统中的管理器,这里不必深究。当释放技能时就会调用Execute中的内容。

好了,今天的教程就暂时讲到这里~

皮皮关与网易联合开发了完备的游戏开发线上课程。想要进军游戏开发领域的童鞋,可戳下面链接了解课程详情:

https://ke.study.163.com/course/detail/100103487

如果有任何问题,还可以通过以下入口与网易小伙伴取得联系,有什么问题直接正面怼他(战术后退

同时,欢迎加入游戏开发群欢乐搅基:1082025059


在Unity中制作完整的技能系统(代码篇)的评论 (共 条)

分享到微博请遵守国家法律