层次化标记可以成为整理概念和数据的非常实用的方法,游戏性标记系统是 UE4 用于声明和查询层次化标记的方法。引擎中的游戏性标记已经存在于多个版本中,但是在 UE 4.15 中,它的界面和性能得到了很大改进,因此现在就是开始使用游戏性标记标记和整理内容的好时机。但是,什么是游戏性标记呢?为什么需要使用它们?

  游戏性标记就是形式为“Family.Genus.Species.Subspecies”或者仅仅是“IndividualTag”的名称。它们在内部作为 FName 实现,在一个中央字典中注册以便验证。由于使用了“.”来嵌套多层名称,查询时既可以查找确切标记,也可以找查找包含某个父标记的任何标记。例如,如果两个项目分别被标记为“Weapon.Ranged”和“Weapon.Melee”,MatchesTag("Weapon") 对这两个项目都会返回 true。MatchesTagExact("Weapon") 对这两个项目都会返回 false,因为精确匹配会忽略父标记。

  游戏性标记容器是可用来一次查询多个标记的游戏性标记集合。标记如果是明确添加的,则只能通过精确校验,但在普通校验中会包括所有父标记。如果调用 Container.AddTag("Weapon.Melee") 和 Container.AddTag("Spell.Fireball"),则 Container.HasTagExact() 将只会对“Weapon.Melee”和“Spell.Fireball”返回 true,而 Container.HasTag() 会对“Weapon”、“Weapon.Melee”、“Spell”和“Spell.Fireball”返回 true。

  游戏性标记有什么用处?首先,每当你希望将设计师可以输入的文本限制在一个类似于名称和枚举的组合的有效名称集合内时,都可以用它们来取代名称。《Paragon》之类的游戏利用它的层次化特性来表示伤害类型之类有嵌套性质的事物。例如,如果某种能力能够在一段时间内造成火焰伤害,就会传递“Damage.DoT.Burn”标记。那么,你可以注册蓝图或本机代码来查  找“Damage”、“Damage.DoT”或“Damage.DoT.Fire”,在这个具体案例中,这三个标记都会触发。

注册标记

  要使用游戏性标记,必须在中央标记字典中注册它们。那么,如何将标记添加到字典?主要有两种方法:使用 ini 文件或使用数据表。要设置任何一种方法,请在“项目设置”(Project Settings)用户界面中打开“游戏性标记”(GameplayTags)选项卡。此操作会打开标记管理用户界面:

泰课在线

  要使用 ini 文件添加标记,启用“从配置导入标记”(Import Tags From Config)选项。这将使系统从 GameName/Config/DefaultGameplayTags.ini 以及 GameName/Config/Tags 中的任何 ini 文件加载标记。如果希望从事项目的所有人都能轻松添加标记,应该使用此方法。完成此操作后,可以使用标记管理用户界面或标记选择界面中的“添加新标记”(Add New Tag)按钮添加新标记。按现有标记旁的 + 图标,或打开“添加新标记”(Add New Tag)选择器:

泰课在线

  如果要导入外部标记列表,也可以使用 GameplayTagTableRow 类型的数据表来添加标记。要进行此操作,请导入数据表,然后在标记设置用户界面中将它添加到 GameplayTagTableList。也可以在项目启动过程中使用 AddNativeGameplayTag 直接从本机代码添加标记。

  将标记添加到字典后,可以通过搜索引用、删除或重命名标记来管理它们。可以在管理视图中,通过标记旁边的光标下拉菜单来访问这些操作。只有通过 ini 文件添加并且不被其他任何项目引用的标记才能删除。重命名的标记会出现在 GameplayTagRedirects 列表中,任何重命名的标记都将在加载时被修正。“搜索引用”(Searching For References)会打开“引用查看器”(Reference Viewer),显示使用指定标记的所有资产。

使用标记

  要实际使用标记,需要先标记某些项目。第一步是将 GameplayTag 或 GameplayTagContainer 属性添加到蓝图或本机类型。如果要标记的项目一次只能有一个值,应该使用一个游戏性标记(例如,可以将标记“Color.Blue”添加到一个用户界面颜色结构,因为它不可能同时有多种颜色)。如果希望支持多种不同的状态或值,应该使用容器(例如,可以将一个 npc 标记  为“Character.NPC”、“Character.Humanoid”和“Gameplay.Important”)。添加这些属性后,可以在“蓝图默认值”(Blueprint Defaults)视图或资产编辑器中编辑它们。

泰课在线

  既然项目已经有了标记,你就可以使用这些标记在游戏性代码中查询和过滤项目。在 C++ 中,可以使用在 GameplayTagContainer.h 中定义的运算。重要的运算有用于单个游戏性标记的 MatchesTag、MatchesAny、IsValid 和 GetTagName,以及用于游戏性标记容器的 HasTag、HasAny、HasAll、AddTag 和 RemoveTag。标记匹配函数将会依据父标记进行匹配,而 Exact 变体只会匹配特定标记。

  在蓝图中可以访问同样的运算,但 Exact 选项是传递到匹配函数中的布尔值。下面是一个基本示例,使用“设置字面游戏性标记”(Make Literal Gameplay Tag)节点来判断在标记容器中传递的项目是否匹配某个标记(包括父标记):

泰课在线

  在 GameplayTag 类别中还有一些更高级的节点,例如“打开游戏性标记容器”(Switch on Gameplay Tag Container)和“将标记容器与其他标记容器比较”(Compare Tag Container To Other Tag Containers)。提醒一下,在 4.15 版之前,这些操作有许多也是可以使用的,但是要通过较为笨拙的语法和用户界面。

  以上就是关于如何将游戏性标记集成到游戏中的基本概述。我们还打算通过其他方法将游戏性标记集成到引擎中,不过当前的工具应该可以提供坚实的构建基础。没有游戏性标记,Epic 不可能发售《Paragon》和我们正在内部开发的其他游戏,因此我希望它们能够为你的游戏提供一些新的设计和编程选项。