Choose your operating system:
Windows
macOS
Linux
本示例已停止维护,虚幻引擎4.24后的版本将不再支持此示例。在加载此项目前,请确保你已经安装了正确的引擎版本。 如需了解如何将更新项目至最新的引擎版本,请参阅升级至Epic最新更新内容。
本文档介绍了名为 动作游戏(Platformer Game) 的游戏项目示例。你可以根据如下操作,找到该示例:
点击Epic启动程序中的 学习(Learn) 选项卡,然后向下翻到 游戏(Games) 分段。
点击 射击游戏(Shooter Game) 缩略图打开项目主页。点击黄色的 免费(Free) 按钮。
稍作等待后,按钮名称会变成 创建工程(Create Project)。点击按钮后,启动程序会提示你输入项目名称并选择安装路径。
点击 创建(Create) 后,你就可以将该项目下载到指定的目录。
动作游戏 示例是在PC/移动平台上的横向卷轴游戏。该示例展示了基本的武器和游戏模式,以及简单的前端菜单系统。
完整的特性列表如下:
强制移动
自定义移动: 滑行(PlatformerPlayerMovementComp)
根运动动画(在车辆上爬行)
调整特定点(可供攀爬的突出部分)的位置以播放动画
强制移动
玩家的移动是通过 CharacterMovementComponent
来实现的。每次移动更新前,使用 ScaleInputAcceleration()
启用修改加速度。此函数在 UPlatformerPlayerMovementComp
中被覆盖,强制在游戏中沿X轴加速。 另外,所有的轴绑定——查看和移动都在 APlatformerCharacter::SetupPlayerInputComponent()
中被移除,防止玩家自己移动。
自定义移动
滑行 自定义移动可以让玩家像平常蹲下来那样穿过障碍物。
滑行在 PhysWalking()
函数中作为 UPlatformerPlayerMovementComp
的行走模式的一部分进行应用。
当玩家在 UPlatformerPlayerMovementComp::StartSlide()
中开始滑行时,通过 SetSlideCollisionHeight()
函数会降低它们的碰撞胶囊体的高度。
|
|
---|---|
行走时高度 |
滑行时高度 |
当玩家在 CalcCurrentSlideVelocityReduction()
和 CalcSlideVelocity()
中滑行时,速度在每个tick都会降低,不过可以通过滑下斜坡增加速度。玩家的速度不会被降低到 MinSlideSpeed
的阀值以下,防止被障碍物卡住。
玩家可以通过跳跃强制退出滑行状态,或者在玩家速度过低时也会自动退出。不过,碰撞胶囊体降低的高度意味着他们不能直接退出滑行状态,除非他们足够的间隔距离,到达该点处就可以适应碰撞胶囊体的默认高度。TryToEndSlide()
函数调用 RestoreCollisionHeightAfterSlide()
函数,后者会查看重新恢复碰撞胶囊体的默认高度是否会导致玩家与世界几何体的一部分产生重叠。 如果不发生重叠,则玩家可退出滑行状态。
根运动动画
当角色无法跳跃并跑向障碍物时,它会自动尝试攀爬,或 跨越 它。 该移动使用 根运动(root motion) 动画,其中动画序列本身会修改骨骼的根运动位置,并且该运动随后被转移到Actor上,导致玩家的位置变更为与普通动画序列相反的方向,该序列只会影响骨骼的子骨骼。
当移动组件检测到玩家撞上了墙后,会调用 APlatformerCharacter::MoveBlockedBy()
。 应用此函数会停止玩家的强制移动,播放 HitWallMontage 的 'bump reaction' 动画蒙太奇。 该动画完成后,会执行 APlatformerCharacter::ClimbOverObstacle()
来进行实际的攀爬。
针对多种高度的不同障碍物,有三种不同的攀爬动画蒙太奇,并且关卡中的所有障碍都必须匹配这些高度之一,这样才可以正常进行攀爬。每个动画蒙太奇的动画序列都会应用动画到根骨骼中。APlateformerCharacter::Tick()
在每帧计算根骨骼的位置变更并将其应用到Actor的位置,以便将动画蒙太奇的根骨骼运动传送到玩家的角色上。
在完成前,调用动画 ResumeMovement()
,恢复默认的强制移动机制。任何剩余动画都会随着角色向前移动而混出。
位置调整动画
由于玩家撞击突出部分时的跳跃位置不同,每次玩家相对于突出部分的垂直位置也都不同,所以地面障碍的可攀爬突出部分也不同。
攀爬仅与单个专用Actor类 PlatformerClimbMarker
共同发挥作用,以便同步动画。就攀爬移动而言,当玩家跑向突出部分并且 APlatformerCharacter::MoveBlockedBy()
被调用时,整个流程开始。此函数会查看玩家是否正在下落(与行走相反)以及玩家碰撞的对象是否属于特殊 PlatformerClimbMarker
Actor之一。如果是这种情况,将会禁用强制移动并且执行 APlatformerCharacter::ClimbToLedge()
,将其传递到左上角位置-例如,可攀爬的突出位置。
由于突出位置攀爬动画总是需要在相对于突出位置的同一位置处开始,并且玩家可在附近的任意位置处,角色的位置将从与对突出位置处产生冲击的初始位置到动画所期望的位置间进行插值。 ClimbToLedge()
存储了作为`AnimPositionAdjustment`的初始位置,并随后立即传送角色到攀爬动画结束并开始播放攀爬蒙太奇的位置。 同时,APlateformerCharacter::Tick()
快速对角色的`SkeletalMeshComponent`的相对位置进行为0的插值,使得网格物体平滑地与动画同步。
菜单系统
我们使用Slate界面框架来创建菜单系统。其中包含 菜单(menus), 菜单控件(menu widgets), 以及 菜单项目(menu items) 。每个菜单都包含单个菜单控件( SSHooterMenuWidget
),负责所有菜单项目的布局、内部事件处理以及动画。菜单项目( SSHooterMenuItem
)是可以执行操作并包含任意数量的其它菜单项目的复合对象。它们可以是标签、按钮或包含由组成其它菜单项目的完整子菜单的"选项卡"。这个菜单可以用键盘或控制器来操作,但示例中仅限于鼠标操作。
每个菜单都是通过 Construct()
函数来 构建 的,这个函数添加了所有必要的菜单项目(包括子项目),并在需要时在函数上附加委托。这是通过辅助方法来完成的—— AddMenuItem()
, AddMenuItemSP()
等,它们在 SShooterMenuWidget.h
文件的 MenuHelper
命名空间中进行定义。
通过菜单的共享指针数组,可以浏览到上一菜单,并且存储到菜单控件的 MenuHistory
变量中。 MenuHistory
类似于存储先前输入菜单的堆栈,并且可以让返回操作更为方便。通过这种方式,菜单间不会创建直接联系,并且可以按需把同一菜单重复用于不同的位置。
动画通过在 SShooterMenuWidget::SetupAnimations()
中定义的插值曲线执行。每条曲线都有起始时间、持续时间以及插值方式。动画可以进行正向或反向播放,并且可以使用 GetLerp()
函数在特定时间为属性设置动画,而这个函数会返回从0.0f到1.0f的值。 在 SlateAnimation.h
的 ECurveEaseFunction::Type
中定义了几个不同的可用插值方式。
主菜单
通过指定 ShooterEntry 贴图为默认值,主菜单会在游戏开始时自动打开。这时会载入特殊的游戏模式 AShooterGameMode
,这个模式使用 APlatformerPlayerController_Menu
类,它会通过创建 PostInitializeComponents()
函数中的 FShooterMainMenu
类的新实例来打开主菜单。
游戏中菜单
游戏中菜单在 AShooterPlayerController
类的 PostInitializeComponents()
函数中进行创建,并且通过 OnToggleInGameMenu()
函数来打开或关闭。
选项菜单
选项菜单可以作为主菜单和游戏中菜单的子菜单来使用。唯一的区别是应用变更的方式:
对于主菜单的变更,在玩家开始游戏时进行应用。
对于游戏中菜单的变更,在菜单关闭时立即进行应用。
选项菜单中的设置被保存到 GameUserSettings.ini
,并且在启动时自动载入。