UE5小游戏开发 - 武士决斗

(效果图)

今天的游戏很简单,在屏幕中出现叹号后双方可以按下攻击键,先按下的一方获得胜利,类似于西部牛仔对枪,讲究的就是谁在读秒之后出击更快。游戏效果如上图所示。


游戏流程

  1. 游戏开始后,两侧的角色移动进入屏幕
  2. 等待中间出现红色叹号,代表决斗开始
  3. 出现红色叹号后,尽快按下攻击键
  4. 先按下攻击的角色获胜,触发攻击效果
  5. 若在出现红色叹号前按下攻击键,则角色头上方出现红叉,游戏失败
  6. 攻击结束后短暂停留,游戏重新开始

操作方式

将一个鼠标或键盘键位绑定为攻击键,不涉及其他复杂操作


设计实现

游戏涉及到两个角色,且他们都需要有攻击、失败、提前攻击导致失败等操作和状态。所以很容易想到应该把两个角色抽出父类,父类负责实现上文中提到的公共功能。除此之外,玩家操作的角色应该绑定play controller,而电脑控制的角色应该绑定AI controller,在其他的部分均可调用同样的代码即可。

角色父类

游戏的体量不大,所以有些功能就在父类里看着方便的地方实现也不算很差的做法。

(父类EventGraph)

第一行:在这个父类中我们先拿到GM,然后实现游戏流程的第一步,通过函数Slide In让两个角色滑入镜头中。再将头顶的红色叉号设置为不可见,方便后续如果提前攻击的时候展示出来表示游戏失败,最后获取一个红色叹号的引用方便后面用。

第二行:手搓了一个滑动进入的效果,对于这种体量的游戏手搓更简单更快。在SlideInAnim这个时间轴中我们每一帧都更新当前sprite的位置,这个位置是通过起点StartPos和终点EndPos计算得出的。Lerp负责返回一个A点到B点中更靠近Alpha的值,而这个Alpha是通过时间轴的曲线得到的,如下图所示,随着时间的推移Alpha的值更趋近于1。对于Lerp返回的值来说,当Alpha趋近于1时,返回的坐标趋近于B点。这样随着时间一帧一帧的流逝,可以模拟出从A点到B点的效果。我们的曲线做了平滑处理,还增加了回弹的效果,这样看起来角色会向决斗中心冲击并稍稍退回来,这样打磨细节更能提高游戏的品质。SlideIn开始连的SetPlayRate让移动更快,是在做完之后发现角色运动太慢表现效果比较差,所以加上它也是为了提升游戏的观感。

(SlideInAnim中的轨道)

第三行:当有一方攻击后会触发这个Event。我们这里创建一个枚举类型来记录游戏中的四种状态,方便做切换如下表所示。这种代表游戏状态的变量放在GM中存放是最合适的,所以这里读一下GM并且根据状态做判断。如果是Wait状态,那属于提前攻击了,这里让角色头顶的红叉显示出来让玩家知道失败了;如果是Draw说明正是应该攻击的时候,攻击后将屏幕中的红色叹号隐藏掉,并且触发SetGameFinish将枚举状态切换成Finished,之后是一个攻击动画,走到对面脸上给一刀并且切换成攻击动画这里就不详细说了,大家看就能明白。最后的AttackSucess中将输得一方切换成战败画面,并且在一段时间后重新开始游戏,蓝图如下所示。

额外需要提到的一点,这游戏只有一个胜者,所以写的时候很自然的就发现需要一个标记位来做个简单的锁,就是HasbeenAttack字段。实际上目前还是有可能两个角色在同一帧攻击导致游戏崩溃,但这种几率非常非常低,而且这不是我们今天主要探讨的内容。

状态 含义
Intro 游戏刚开始
Wait 等待红色叹号出现
Draw 可以进行攻击
Finished 有一方攻击完毕,游戏结束

(GM中的枚举字段包含的状态)

(GM中的AttackSucess函数)

第四行:当角色失败的时候执行的事件,大家在上面的这个AttackSucess里面应该也看到调用了,主要是切换图片样式和红叉显示情况。

玩家角色

这是一个很标准的player controller获取并且绑定映射,今天这是第一篇文章所以简单说一下,以后这种内容就跳过了。

(玩家角色EventGraph)

先是获取玩家控制器,然后通过Possess将当前的这个Sprite和控制器绑定,用好理解的话说就是我们现在的灵魂Player Controller附身了这个Pawn(也就是Sprite)的身体,以后游戏一开始我们就操控这个Pawn。之所以要写这个步骤是游戏中有多个角色,我们需要手动指定一个让程序理解我们要控制哪一个角色。此处也可以设置"玩家出生点"并且在GM中指定默认Pawn,这几种做法均可。

后面写的略有重复,但是这套操作比较经典。先获取Controller将类型转化为PlayerController确保获取类型无误,这个地方不要直接get Player Controller,先获取Controller再转化可以确保当前的角色不是加的什么AI Controller,避免直接get Player Controller导致程序崩溃,多转一步要的就是这个不方便,增加代码鲁棒性。后续使用增强控制器并且添加按键映射。

这个游戏是固定机位,摄像机不需要和某个角色的位置产生交互,所以后面我们创建一个固定摄像机,并且通过Set View Target with Blend来启用新增加的摄像机。

敌人角色

敌人角色由电脑控制,敌人会在可攻击之后的随机一段时间内发起攻击,具体是多久后会发起攻击需要反复尝试时间范围,这是游戏核心的体验内容,太快或太慢都会让游戏失去乐趣。

(敌人角色EventGraph)

这里绑定了一个Can Attack的广播,当可以攻击后由GM发送出来。当电脑控制的敌人收到这个事件后触发EnemyAttack事件,在一段时间的延迟后进行攻击操作。

游戏模式(GM)

负责游戏主要的流程和状态的控制。

有点后悔了,应该先写GM这样整个思路看起来可能更好理解一点。

(GM的EventGraph)

第一行:获取多个对象的引用。

第二行:我们这里自己手搓了一个简易的计时器,每一帧的时间叠加到ElapsedTime中做累计,如果累计的时间超过了RoundStartTime那么将当前游戏状态从Intro切换到Wait,此时再经过一个随机时间之后,状态再切换到Draw并发送可以攻击的广播,画面中出现红色叹号。

其他内容

其他部分主要是美术素材的切分并设置为半透明精灵效果,游戏画面中角色位置的调整,曝光调整。蓝图部分还有红色叹号作为单独的蓝图有一点点可见切换的内容,还有角色有几个函数里面做些简单的功能,此处就不一一截图列出了,详细内容请见项目工程文件。


项目源码

项目打包了,感兴趣的朋友们可以自取。

https://github.com/UsagiKnight/LightingDuel_UE5_2D_MiniGame

相关推荐
无限进步_13 小时前
扫雷游戏的设计与实现:扫雷游戏3.0
c语言·开发语言·c++·后端·算法·游戏·游戏程序
Brianna Home1 天前
Godot4.3开发2D游戏全记录
游戏·游戏引擎·godot·游戏程序·动画
王维志1 天前
使用Asp.Net WebApi(.net 8)托管Unity WebGL
unity·游戏引擎·webgl
开发游戏的老王1 天前
虚幻引擎入门教程:虚幻引擎的安装
游戏引擎·虚幻
muyouking111 天前
Unreal Engine 中的旋转表示:FQuat 与 FRotator 全面解析
游戏引擎·虚幻
霜绛2 天前
Unity:Json笔记——Json文件格式、JsonUtlity序列化和反序列化
学习·unity·json·游戏引擎
开发游戏的老王2 天前
虚幻引擎虚拟制片入门教程 之 创建项目及启用插件
游戏引擎·虚幻
L X..3 天前
Unity反射调用 ReactiveProperty<T>(泛型类型)内部方法时崩溃
unity·c#·游戏引擎·.net
开发游戏的老王3 天前
虚幻引擎虚拟制片入门教程 之 模型资源的导入
java·游戏引擎·虚幻
ricky6753 天前
[Linux]Linux系统的20个实用命令详解
ue5