今天,我们开始做一个动作类游戏。
美术资源
我们先下载今天要用到的美术资源。
链接:https://pan.baidu.com/s/1Vci83yoTRvViXIXElZ4k0g?pwd=tynm
提取码:tynm
新建项目。
把美术资源拖进项目。
创建角色
我们创建个文件夹,就叫Player。
创建角色蓝图。
我们再创建一个玩家控制器。
这时候我们再添加一个游戏模式。
然后我们改下GameMode的类默认值细节的设置。
编译保存。然后改一下默认游戏模式。改成我们刚建的。
返回资源浏览器。编辑PlayerChar。给它添加个模型。
调整下位置,旋转。
选中胶囊体组件,把胶囊体半高改成92。
然后添加摄像机。
然后调整下弹簧臂的位置。
编译保存运行。
移动
编辑PlayerChar。添加自定义事件。
增加ScaleValue变量编译。
保存编译。返回项目设置。
添加轴映射。
然后我们打开Controller。
编辑。
编译保存。现在角色可以向前向后移动了。左右也是。
然后再在项目设置里加一个轴。
然后控制器也加上左右。
前后左右都没有问题。现在回到项目设置添加视角。
返回playerchar。
编译保存运行。ok行走没问题了。
移动动画
现在要创建动画蓝图了。
打开动画蓝图编辑。保存。
新建一个混合空间。
点击编辑混合空间。在资产详情里修改水平坐标。
拖动idle_eqip_01到最左。
然后把walk_eqip_front拖到速度为1时的地方。
让速度到3时跑。
保存。等于走有三种状态。
然后再打开动画蓝图。
点开状态机。
添加状态。
进去Idle/Run状态。
把Speed提升为变量。
然后点击事件图表。
保存,打开playerchat。点网格体。设置动画类。
编译保存,运行。现在可以跑了。
现在输入我们加一个慢走。
打开玩家PlayerCharController。编写走路。
编译保存运行。现在可以慢慢地走了。
武器
现在我们加一下武器。在playerChar中加一个骨骼网格体。
然后父项插槽选Sword_1。资产也选一下。
编译保存运行。
连招系统
攻击
找到这个动作。
然后创建动画蒙太奇。
然后绑定下按键。
然后打开PlayerChat。添加自定义事件。
然后我们找到角色的控制器。加上攻击。
运行发现胶囊体没有跟角色移动。找到动画,启动根运动。
现在胶囊体会跟角色移动了。角色会跟着攻击动画移动。打开PlayerChar。让角色每次攻击都能连续。不会因双次按下攻击按键而抽搐。增加一个变量,用来判断是否在攻击中。
完整蓝图。
现在连点不会抽搐了。
连招
删掉攻击的逻辑,开始编写连招逻辑。
增加变量。并使用数组。
这里要多少个连击动作,就加多少个数组就可以了。
接着,我们找到连击动作。
创建动画蒙太奇。
然后找到Combo_01动画。
我们分解下连招动画。找到第一下下剑时的结束时间。调整结束时间。
然后做连招第二下的动画。
然后做连招第三下的动画。
然后做连招第四下的动画。
所有分解的招式。
然后返回PlayerChar。编辑连招逻辑。
然后找到刚创建的数组变量。
把四个连招动作按顺序赋予数组。
然后我们添加一个变量,用来计数攻击次数。
初始值设为-1。
然后编译下蓝图。
攻击先判断是否在攻击。
然后攻击次数加1。
然后判断攻击次数是否大于招式动画的长度。
如果小于招式动画的长度就获取一下招式。
如果大于招式动画的长度就把,Attack count归零。
然后设置一下ComboReset。
接着找到动画Combo_01_1_Montage,然后在攻击后摇前,大概在8后,右键加一下动画通知。
在动画结束时也加一下动画通知。
动画234也一样。
加完通知后,接着我们使用下通知。 打开PlayerCharABP。
在ComoStart通知时去做Do Attack。
然后再动画播放结束时,把所有的状态设置为初始值。
然后在动画蒙太奇里设置下混出混入时间。让混出混入时间远小于本身动画的时间。
然后创建一个保存攻击的状态。
SaveAttack开始时也要保存下。
然后把动画蓝图里的DoAttack改成AttackSave就可以连击出连招了。
https://github.com/user-attachments/assets/801d8e67-cbcd-4e1b-846b-c73e4299567a
更好的打击感
上面已经把攻击连招讲完了,但是攻击的时候不能转向,他只能朝着一个方向走,手感不是很好。下面完善一下攻击。然后做出攻击时可转向,添加闪避以及伤害通知。
攻击时可转向
一个流畅的动作类游戏,他必须得是非常跟手的。随时都跟着你的操作。在你攻击的时候,他应该也能跟着转向。这样才是一个好的动作游戏的手感。
打开playerchar。
新建一个函数。
用这个函数计算最后一次输入。就是要用这个函数获取最后一次键盘是按的哪个方向。这个函数不能单独使用,得配合其它函数使用。
新建一个变量,用来保存我们的输入movement。
还要新建一个变量,用来保存我们最后一次输入的角度。
我们把角色移动拖进来。
把角色最后输入的向量存到Movement Input。
我们还需要加一个变量,用来检测砍一刀时,有没有输入向量。
输入角度也保存一下。
这样这个函数是算写完了。
然后我们返回事件图表,让每帧都执行一下。
然后我们再创建一个函数。用这个函数改变角度。就是要让攻击动画改变角度。
添加两个输入。
先判断下输入的两个值。
然后就可以对角度设置渐变推进。
也设置下没有速度的时候的情况。
然后我们做下动画通知。新建一个文件夹。
创建一个AnimNotifyState蓝图。
打开编辑。新建变量。
然后重载一下函数。
然后找个动画试试。找到攻击这个蒙太奇。
添加状态通知。
表于在这段区间之间都可以转向。就是攻击前摇时可以选择方向。
然后回到RotationByAnim,把InterpSpeed变量小眼睛点开。
编译。回到动作就可以看到这个变量了。
然后设置这个渐变速度为10。
然后把其它的动画也设置下。
然后接下来我们开始写这个动画通知的函数。
我们再重载下两个函数。
现在攻击时可以转向了。
https://github.com/user-attachments/assets/f2124445-7383-46ad-b3cc-a05e40cee7fb
伤害通知
直接在动画序列中加通知。
接着我们回到playerchar写伤害逻辑。
然后我们返回动画蓝图。
运行可以看到攻击的范围。
https://github.com/user-attachments/assets/d1f9993d-0546-469f-a9c4-45f4dbdc1316
闪避
我们先加一下按键。
然后我们找个动画。创建动画蒙太奇。
然后回到动画。把启动根运动勾上。
角色就能跟着胶囊体动了。
然后我们写一下闪避的逻辑。
在控制里也加一下。
编译保存运行。
https://github.com/user-attachments/assets/6e411bef-0ddc-465b-b158-d4b264e40361
但反复按会鬼畜。这里改一下。
然后在动画播放完后状态设置为不翻滚。
编译保存运行。
现在反复按不会鬼畜了。
这里可以加速动画播放让翻滚快点。
闪避时可转向
直接给这个通知拉满,只要在翻滚的过程就能改变方向。
修复攻击时闪避后不能再攻击的Bug
因为攻击中闪避而没有走ComboReset。所以IsAttack永远为真。所以在闪避后再做一下ComboReset就可以了。
闪避时不能攻击
如果在闪避中,就不要给角色攻击了。
创建敌人
按照惯例,先创建一个文件夹。
创建模型
然后创建一个蓝图。
然后打开它。给它加个模型。
调下参数。
然后改一下这个模型的颜色。
再原来的材质上复制多一份。
双击新的材质,我们改下颜色。
点应用,保存。回来看,白色的材质球就做好了。
然后回到AIChar,模型换个颜色。
敌人AI
然后我们创建一个AIController。
然后还要一个行为树。
打开AICharController。在事件开始时运行行为树。
然后在AIChar里关联上AICharController。
编译保存。然后我们打开行为树,新建一个黑板。
给AI也创建下动画蓝图。
然后打开它。
双击状态机添加状态。
因为都是小白人,所以AI也可以用之前创建的混合空间。
speed提升为变量。
编译保存。
然后回到AIChar。使用刚才的动画蓝图。
然后给敌人加下武器。加下骨骼网格体。
然后加一下盾。
然后我们返回动画蓝图。
我们动画蓝图算是写完了。AI也会根据它移动的速度来决定它动画是走是跑还是站立。这些都是和主角一样的。然后我们写下行为树。
然后新建一个装饰器。
用来检测有没有玩家。
然后取一下位置。
然后需要加一下球形检测。
Object Types提升为变量。
半径给1000。
然后Draw Debug Type改成持久。
最后连上。
输出会Out Hits打开。
然后把每个数组再break一下。
如果这个球体检测到玩家,那就转化为玩家。检测不到就什么都不干。
然后as player char给他设置黑板值。
然后把Key提升为变量。
把小眼睛点亮,这样你在行为树上才能看到这个变量。
然后返回节点也连上。在循环结束之后返回为真。
编译保存。返回行为树。添加装饰器。
然后点击黑板,在黑板上新建一个值。
改下基类。
保存。
把顺序换成选择。
然后再来个顺序。再加个装饰器。
再来个顺序。
设置未设置。用于没检测到玩家的操作。
检测到玩家就走向玩家。
保存。给场景添加一个导航网格体边界体积。
调整导航网格体边界体积,让它覆盖整个场景。保存运行。现在可以看到敌人走过来了。
https://github.com/user-attachments/assets/b852159c-7af5-4355-939e-5cbf04939564
参数调整
AI追到你后的等待时间可以自行调整。
敌人的速度也可以调整下。
添加巡逻
新建一个服务。
打开,重载下接收Tick AI。
然后先取一下位置。
然后得到一个随机可以到达的位置。
设置半径为500。
然后把得到的位置设置为黑板键。
把Key提升为变量。改一名。
小眼睛打开。
最后把线连上。
编译保存。
返回行为树。添加服务。
返回黑板。增加一个向量变量。
返回行为树,把Target Location改为目的地。
移动到目的点。
保存。运行。现在AI能随机走动了。
攻击
然后在行为树新加一个任务,让敌人攻击。
打开,重载下接收执行AI函数。
转化为AIChar,直接播放蒙大奇。
给AI找个攻击动画。
创建一个动画蒙太奇。
打开动画,启动下根运动。让他播放这个动画时有位移。
返回任务,指定动画资产为Attack_08_Montage。
最后返回执行结果。
然后返回行为树。添加攻击。
编译保存运行。现在敌人会先过来再攻击,等待两秒再攻击。
https://github.com/user-attachments/assets/7590acab-f16d-413a-9b09-176d8f08e8de
添加伤害
玩家打AI
先给AI加点变量。
接着回到主角这里,编辑攻击逻辑。
基础伤害给到10。
主角这边的攻击伤害算写完了。
返回AIChar,继续写敌人被打的逻辑。
保存编译运行。
打印了很多。需要关掉一些没必要的碰撞。
主角这边也改一下。
现在的攻击输出就正常了。
因为AI会档主角的摄像机,所以AI的胶囊机碰撞的自定义下。
死亡
先加个变量判断是否死亡。
UI
敌人血条
新建UI文件夹。
我们做一下血条。新建UI控件蓝图。
然后打开它。新加画布。
然后加个进度条。
锚点改成中间。
然后把位置设置回来。
对齐都改成0.5。
尺寸y改成15。
填充颜色改成红色。
然后创建绑定。
添加对象变量。
用现血量除以总血量得到血条的百分比。
编译保存。回到AIChar。
添加控件组件。
改名为血条。
控件类是AIHPBar。
血条放到头顶上。
给它空间设为屏幕。
编译保存。回到事件图表。
把HPBar拖进来。
这样血条就加上了。
玩家血条
接着我们做一下玩家的血条。
新建个控件蓝图。
编译保存。然后在PlayerChar里加点变量。
然后回到PlayerHPBar创建绑定。
然后我们回到PlayerChar。
编译保存运行。
让玩家受伤
直接在动画Attack08里新建一个通知。
新建通知后,需要一个球形检测。
基本和之前写的玩家攻击逻辑一样。
然后返回PlayerChar。先加个变量。
然后回到AIChar_ABP。
保存编译,运行。现在敌人打玩家,玩家会扣血了。
AI被打动画
找到这个被打动画。
然后创建动画蒙太奇。
打开AIChar。
AI死亡动画
找到这个动画。
创建动画蒙太奇。
返回AIChar编写死亡动画逻辑。
动画要设置根运动。
在动画蒙太奇中不设置启动自动混出。敌人死亡倒地就结束了。
然后找到AI攻击。
让AI攻击前加个判断 ,判断是否正在播动画。
接着回到AIChar。在死亡后删除胶囊体。
编译保存运行。
把AI的攻击动画换成原地的
现在AI攻击会向前,对于游戏来说,玩家不容易闪避。我们给AI换个原地攻击的动画。敌人呆一点比较好。选一个腿没有动的。
然后创建蒙太奇。
动作启动根运动。
在AI攻击蓝图中改用这个动画。
当然,也要加上动画通知。
增加AI攻击前摇时间
打开攻击的动画蒙太奇,再拉一个动作。
把第一段做成0.138。
把前摇速率放慢。
现在敌人的攻击前摇时间加长了,玩家容易闪避了。
玩家被攻击动画
找到玩家被打动画。
然后启用根运动。
创建动画蒙太奇。
然后回到PlayerChar。增加被攻击动画。
每次受到伤害重置下玩家的攻击,防止玩家攻击时被攻击而不能再攻击。
玩家被死亡动画
把红框去掉