使用C++构建ARPG的玩法

本文档介绍了如何构建ARPG游戏的玩法系统。

Choose your operating system:

Windows

macOS

Linux

参见

本文档旨在描述如何构建动作角色扮演游戏(ARPG)中的玩法(Gameplay)系统,同时还可以为设计类似系统提供示例。它适用于那些已经阅读过 UE4中的C++编程简介 ,并使用 第一人称射击游戏教程 中提供的模板构建过一些基本原型的开发者。有关特定于技能系统的功能,请参阅 Gameplay技能系统 文档。

代码概述

大部分虚幻引擎4(UE4)项目都以现有模板或现有示例项目的副本为起点。以ARPG为例,它最初是作为类似于自上而下(Top Down)模板的纯蓝图游戏,然后我们将其转换为混合了C++和蓝图的项目。在此背景下,大多数基本的Gameplay逻辑都是用蓝图而不是C++实现的。 平衡蓝图与C++ 这份文档讨论了我们在决定使用蓝图还是C++时应该考虑到的部分因素。在初步创建和转换项目后,我们创建了用于Gameplay的原生类层级。另外,我们还为C++代码和内容定义了命名和目录组织方案。

下面概述了ARPG中使用的源文件:

文件名

说明

ActionRPG.h

这是项目中每个C++文件都包含的模块头文件。这里包含大多数类所需的共享引擎头文件以及全局定义。

RPGTypes.h

用于定义其他类中使用的游戏特定结构体和枚举的共享头文件。通常,最好创建一个或多个此类头文件,避免出现循环使用头文件的问题。

RPGPlayerControllerBase.h

它是大多数游戏所需的 PlayerController 的游戏特定子类。对于ARPG,它主要用于处理物品栏。

RPGCharacterBase.h

角色的游戏特定子类。对于ARPG,所有 蓝图角色(Blueprint Characters) 都继承此类,但是许多游戏需要具有多种角色类型的层级。

RPGGameInstanceBase.h

它是 GameInstance 的游戏特定子类,是大多数游戏所必需的。由于在整个游戏中只声明一个游戏实例,它很适合存储全局Gameplay数据。

RPGGameModeBase.h RPGGameStateBase.h

游戏模式(Game Mode)和状态子类。对于ARPG来说这些只是存根代码,因为大多数贴图特定的Gameplay逻辑是使用蓝图实现的,但许多游戏会选择使用C++代码制作各种模式和状态。

RPGBlueprintLibrary.h

公开不与特定Actor挂钩的游戏特定蓝图函数,几乎每个游戏都需要一个或多个这类文件。

RPGSaveGame.h

此类用于在磁盘上存储物品栏/经验值信息,下文将详细介绍。

RPGAssetManager.h

这是下文中描述的物品栏系统使用的资源管理器(AssetManager)的子类。

RPGInventoryInterface.h

原生接口,允许 RPGCharacterBase 在无需手动转换的情况下查询 RPGPlayerControllerBase 以了解物品栏的信息。

Items/RPGItem.h和子类

不同种类的物品栏项目类型。

Abilities/RPGAbilitySystemComponent及其他

用于技能系统,具体请参阅 ARPG中的游戏性技能 中描述的技能系统。

ActionRPGLoadingScreen Module

一个简单的C++加载屏幕,用于在首次加载游戏或转换地图时显示纹理。这是一个单独的模块,因为它需要在加载主要的ARPG游戏模块之前先进行加载。

虽然ARPG中没有编辑器模块,但许多其他虚幻引擎4(UE4)游戏都有一个 编辑器模块(Editor Module) ,可以添加需要在UE4编辑器中使用的其他UI或工具。

创建原生类后,你需要更改

[项目设置](Basics/Projects/ProjectSettings)
以生成正确的 游戏模式 游戏实例 资源管理器 类。你可能还需要更改贴图设置,以便反映项目中的新改动。

物品栏和资源管理器

ARPG使用 资源管理器 系统加载和访问物品栏项目。资源管理器最初用于管理在各种不同情况下以及整个游戏中可用的资源,通常应用于所有物品栏项目。对于ARPG来说,有四种物品类型:

  • 武器(Weapons) :是一种可供玩家装备的蓝图,可造成近战伤害。

  • 技能(Skills) :指的是玩家可以装备和使用的特殊攻击(例如火球),可以造成直接和区域作用伤害。

  • 药剂(Potions) :是一种一次性消耗品,用于治疗和回复法力值。

  • 代币(Tokens) :是一种简单的计数器,记录获得的灵魂值和经验值等。

其中每一项都有单独的原生C++类,它继承自 URPGItem ,并使用 DefaultGame.ini AssetManagerSettings 部分中的代码行定义。我们决定不为ARPG创建项目蓝图,因为它们没有专属的逻辑或继承结构,在每个游戏中都会有所不同。每个项目基类会提供UI信息(例如要使用的图标)以及Gameplay信息(例如装备特定物品时会获得的技能)。

玩家拥有的项目存储在 URPGPlayerControllerBase 实例中,使用以下两个贴图属性:

  • 第一个贴图是从 URPGItem * 到 FRPGItemData ,存储数量和关卡。

  • 第二个贴图是从 FRPGItemSlot URPGItem *,描述某个项目存储在"武器插槽1"中。

有效项目插槽和默认物品栏存储在 BP_GameInstance 中。Player Controller原生类提供用于添加、删除和查询物品栏项目以及与技能系统交互的API。由于ARPG中的每个项目类型都是主要资产类型,我们将 FPrimaryAssetType 结构的用途更改为"项目类型"并将其传送至过滤器函数。ARPG提供游戏内存储,因此需要在启动时预加载游戏中的所有项目。它使用 BP_GameInstance 的逻辑来实现这一目的:

点击查看大图。

AsyncLoadPrimaryAssetList 节点最终在 URPGAssetManager 上调用 LoadPrimaryAssets 函数,后者开始异步加载指定类型的所有项目。完成加载后,它会将其添加到存储在游戏实例中的贴图中,并在存储UI中使用。需要注意的是,调用 LoadPrimaryAssets 时,会将这些资产保存在内存中,直到调用 Unload 为止,即使这些资产未被进行任何引用也是如此。 RPGAssetManager 子类相对比较简单,因为它仅为每个项目类型声明某些静态类型,以及从磁盘加载物品栏时使用的 ForceLoadItem 函数。

对于ARPG来说,使用物品栏项目的逻辑主要存储在玩家和敌人蓝图共享的 BP_Character 蓝图中,但有许多游戏在原生C++中实现该项目的用途。此外,物品栏还与技能系统进行大量交互,具体请参阅 Gameplay技能系统 文档。

保存游戏

ARPG通过原生结构使用 URPGSaveGame ARPG类将玩家的物品栏(包括灵魂/经验值)存储在磁盘上。通常来说,任何关键信息都应使用原生结构存储,以便可以使用原生版本控制和修正代码。对于 URPGSaveGame ,使用 ERPGSaveGameVersion 枚举和Serialize函数中的修正代码来实现。这是因为在任何时候,用户定义的结构体都可能被意外修改。如果开发者试图重命名或删除字段,那么玩家保存的游戏就会丢失数据,可能导致玩家保存的数据被完全破坏。因此通常来说,应该使用具有版本控制功能的原生结构来实现关键数据。

ARPG保存游戏使用存储为字符串的 PrimaryAssetIds (版块类型 ItemType:ItemName )来存储物品栏。这种存储项目引用的方式比资产路径(如 /Game/Items/ItemName.ItemName )更安全,因为即使资产移动了,引用也不会被破坏。如果更改资产名称,可以使用 PrimaryAssetIdRedirects 或原生代码进行修复。 ForceLoadItem 可以同步加载尚未在内存中的项目,以便从 PrimaryAssetId 转换为 URPGItem (由于上面提到的存储预载,在ARPG中通常需要这样操作)。

URPGGameInstanceBase 使用 BP_GameInstance 中设置的变量来处理物品栏的实际保存和加载。重要的一点是能够从原生代码访问保存函数,因为每次只要从物品栏添加或删除项目, 玩家控制器(Player Controller) 就可以强制物品栏保存。如有必要,你也可以从蓝图手动调用它。对于ARPG,使用 SaveGameToSlot 蓝图函数将保存写入磁盘,但如果原生实现,之后可以将其更改为服务器端解决方案。选项菜单不使用原生保存游戏实现,因为数据丢失无关紧要。你还应始终将该信息存储在本地设备上。

无论哪个游戏,在开发之初,都应仔细考虑如何进行游戏存档管理。

打包发布

在构建了Gameplay基础架构并且团队已经开始制作内容后,最后也是最重要的编程任务是准备打包和发布游戏。默认情况下,UE4打包的内容多于发布版本所需的内容,这可能会在移动平台中出现问题。对于ARPG来说,第一步是确认只包含ARPG需要的内容,因此我们使用 资产管理器 来帮助解决这个问题。

主资产类型(Primary Asset Type) 配置文件的 "CookRule=AlwaysCook" 分段允许将项目的 内容(Content) 文件夹中的所有项目烘焙为最终成品。为了确保ARPG中包含 主菜单(Main Menu) Gameplay 贴图,我们将两者都添加到 打包设置(Packaging Settings) 中的 +MapsToCook 行。在确定ARPG包含所需的所有内容后,我们使用UE4编辑器面向移动平台打包项目,以便验证打包游戏是否按预期运行。验证完打包游戏是否正确运行且其中包含所有项目内容之后,我们再考虑如何降低下载与内存大小。由于ARPG面向的是移动平台,因此我们希望尽量减少下载和内存大小。为了实现这一点,我们通过以下步骤来减少安装大小与内存占用:

  1. 禁用所有未使用的 插件(Plugins) 。针对ARPG执行这一操作可将整体项目大小减少30 MB。
    ARPG_DisableUnusedPlugins_01.png

    上图仅显示了禁用的 增强现实(Augmented Reality) 插件,你可以禁用项目中的每个插件分段,最大程度地节省空间。

  2. 启用 烘焙时排除编辑器内容(Exclude editor content when cooking) ,该标记可在 打包(Packaging) 设置中找到。这样可以防止项目将 /Engine/EditorMaterials 等UE4编辑器文件夹中的内容一起打包。
    ARPG_SkipCookingEditorContent_01-1.png

    请注意,该操作会破坏使用这些材质的所有游戏内容。不过,你不应该在项目中使用UE4编辑器文件夹中的任何资产。

  3. 默认情况下,由于 DefaultEditor.ini 文件夹中的 +ContentDirectories 行,UE4将烘焙 /Game/UI 和其他一些文件夹中的所有内容。ARPG在此文件夹中有一些原型UI项目,我们在 ARPG DefaultEditor.ini 文件夹中添加了includes以将其禁用。如果结合此步骤与上一步骤,就可以将ARPG的安装大小减小50MB。 ARPG_DefaultEditorINI_01.png

  4. 使用资产审核(Asset Audit)窗口中提供的 尺寸贴图(Size Map) 工具(在 烘焙和分块 文档中描述),我们能够找出一组性能成本较大的纹理和静态网格体。然后,我们将此信息转发给内容团队进行整理。通过优化这些资源,ARPG的安装大小又减少了100 MB。 ARPG_SizeMapTool_01.png

  5. 我们暂时启用了 项目设置>打包(Project Settings > Packaging) 中的 用于分发(For Distribution) 复选框,并将 编译配置(Build Configuration) 开发(Development) 更改为 发行(Shipping) ,以便更清楚地了解ARPG的最终大小。一般来说,在烘焙最终版本(通常使用传递给UAT脚本的命令行选项)时都会将其启用,但 不应 在项目开发期间启用。从开发(Development)版本变为发行(Shipping)版本,可以将ARPG的安装大小节省大约50 MB。
    ARPG_ForDistributionSettings_01.png

完成上述所有步骤后,ARPG的安装大小减少了大约 230 MB ,有助于在各大应用程序商店进行发布。

欢迎帮助改进虚幻引擎文档!请告诉我们该如何更好地为您服务。
填写问卷调查
取消