Gameplay标签

可以用于识别、分类、匹配和过滤对象的Gameplay标签。

Choose your operating system:

Windows

macOS

Linux

Gameplay标签 是概念性分层标签,使用用户定义的名称。这些标签可以有任意数量的分层级别,以"."符号分隔,例如,有三个级别的Gameplay标签将采用形式"Family.Genus.Species",其中"Family"是这个层级中最广泛的标识符,而"Species"是最具体的标识符。请注意,"Family.Genus.Species"的存在暗示着"Family.Genus"和"Family"Gameplay标签也存在。单个标签是轻量级的,使用类型FGameplayTag。由于游戏对象经常有多个标签,因此提供了 Gameplay标签容器(使用类型FGameplayTagContainer),它可以处理多种附加查询。Gameplay标签(或Gameplay标签容器)可以添加到任意项目,将对象与概念标签关联起来,继而使用标签来为您的项目识别、匹配、分类或过滤对象(根据需要)。

创建Gameplay标签

Gameplay标签必须添加到中央标签词典,引擎才能知道这些标签的存在。这可以通过编辑器功能,用三种方式来实现。您可以通过三种方式来创建(或删除)标签:

  • 项目设置(Project Settings) 菜单中手动添加或移除。

  • 通过在"GameplayTags"文件夹中创建和编辑.ini文件。

  • 通过构建数据表资源。

所有三种方法都在 项目设置(Project Settings) 中,打开 Gameplay标签(Gameplay Tags) 选项卡,在 项目(Project) 部分下设置。

项目设置(Project Settings)中的Gameplay标签(Gameplay Tags)菜单

手动添加标签

添加Gameplay标签的最简单方法是在 项目设置(Project Settings) 菜单中手动输入。通过选中 从配置导入标签(Import Tags From Config) 选项,将会加载`Config/DefaultGameplayTags.ini`,以及`Config/Tags`目录中找到的任何.ini文件中的所有Gameplay标签。这样将出现标有 **添加新Gameplay标签(Add New Gameplay Tag)** 的选项,该选项可以用于向任何现有的Gameplay标签.ini文件(包括默认文件)添加新的Gameplay标签。以这种方式添加的标签还有一个可选字段,用于输入将在编辑器中作为工具提示显示的简短描述。

项目设置(Project Settings)中的手动添加标签

直接编辑.ini文件

要使用您自己的.ini文件添加标签,必须启用 从配置导入标签(Import Tags From Config) 选项。然后可以从项目`Config/Tags/`路径下的每个.ini文件加载Gameplay标签,这些文件手动编辑十分容易。如果进行这些编辑时编辑器仍在运行,关闭 **从配置导入标签(Import Tags From Config)** 选项然后再打开,可以重新加载这些文件。这些文件中的格式类似于以下示例:

[/Script/GameplayTags.GameplayTagsList]
GameplayTagList=(Tag="Vehicle.Air.Helicopter",DevComment="This is a custom tooltip!")
GameplayTagList=(Tag="Movement.Flying",DevComment="")
GameplayTagList=(Tag="Movement.Hovering",DevComment="")
GameplayTagList=(Tag="Movement.Landing",DevComment="")

该方法很方便您的队友添加自己的标签,因为`Config/Tags`中的.ini是很容易编辑的文本文件,可以按照您喜欢的任意文件命名约定进行命名。

要使用"开发者标签"配置文件,转至 项目设置(Project Settings) 中的 Gameplay标签开发者(Gameplay Tags Developer) 菜单,用您所需的文件名填写 开发者配置名称(Developer Config Name)。如果启用,会将添加到默认.ini文件(由您添加)的所有标签保存到您指定的.ini文件。您的.ini文件存在于`Config/Tags`文件夹中,可以传递给其他开发者或提交到源控制系统,而不必进一步修改。这对于包含数千个标签的大型项目十分有用,或者用于区分特定开发者创建的标签,或者用于特定的游戏功能。这不是强制性要求,但对于某些团队和工作流程十分有益,可以帮助将特定标签存储在单独的文件中。

数据表资源

最后,标签可以通过数据表资源添加,使用行类型为`GameplayTagTableRow`。这对于从外部源导入Gameplay标签尤其有用,如Excel电子表格文件,但您可以不必导入文件而创建自己的标签,并在编辑器中处理标签。创建资源后,将它添加到 **项目设置(Project Settings)** 菜单中的 **Gameplay标签表的列表(GameplayTagTableList)**,其中包含的所有标签都会添加到 **Gameplay标签管理器(Gameplay Tag Manager)**。请注意,该系统支持列出多个资源,因此您可以将项目标签拆分到不同的电子表格中(如果对您的工作流或组织有益)。

数据表资源中的Gameplay标签

数据表资源使用虚幻引擎资源(而不是.ini文件),可以在编辑器运行期间像其他游戏资源一样查看和更改。

管理Gameplay标签

添加Gameplay标签后,您可以搜索对它们的引用、删除或重命名来进行管理。所有这些操作都可以使用 项目设置(Project Settings) 菜单中的标签旁边的插入符号下拉菜单进行访问。如果标签是通过.ini文件添加的(无论是手动编辑还是通过 项目设置(Project Settings) 菜单添加),则只能在该菜单中将其删除,且不能被进行任何引用。重命名标签会导致向GameplayTagRedirects列表中添加标签,任何重命名的标签都会在加载时被静默修复。

在项目设置(Project Settings)中编辑单个Gameplay标签

Gameplay标签可以在项目设置(Project Settings)中通过插入符号下拉菜单进行编辑。

Gameplay标签编辑限制

Gameplay标签编辑器支持根据一列授权用户,限制层级中任意级别的Gameplay标签编辑。要使用Gameplay标签编辑限制,打开 项目设置(Project Settings),并在 Gameplay标签(GameplayTags) 部分下面,展开 高级Gameplay标签(Advanced Gameplay Tags) 层级。要限制对一组Gameplay标签的编辑,必须先指定.ini文件来存储标签,但不要命名为"DefaultGameplayTags.ini"。还应当指定受限标签的所有者,这样用户想要编辑时就知道可以联系谁。最后,Gameplay标签本身可以添加到"受限标签列表",在这里标签会标有一个复选框,表示是否允许未列出用户向他们添加子代。如果用户(除列出所有者以外)尝试编辑"受限标签列表",将会弹出警告,要求用户确认他们获得了所有者的授权。如果用户不选择"是",则无法进行编辑。

RestrictedTagsUI.png

用于添加受限Gameplay标签的界面。复选框指示用户可以添加子标签的位置。

用户(除了列示为所有者的用户)将在尝试修改"受限标签列表"时收到警告。

RestrictedTagWarning.png

不拥有"受限标签列表"的用户尝试编辑时出现的警告/确认窗口。

"受限标签列表"设置完毕后,一般的Gameplay标签列表将包含您的受限Gameplay标签。但是,受限标签的插入符号下拉菜单中没有"重命名"或"删除"选项,您在"受限标签列表"中选中对应框的标签旁边只会出现"+"按钮。

GameplayTagsUIWithRestrictedTags.png

标准Gameplay标签列表删除了不归当前用户所有的受限标签的"+"按钮。

RestrictedTagCaretMenu.png

"受限标签列表"中创建的任何标签在其插入符号菜单中都只有搜索选项;"重命名"和"删除"选项都不可用。

当前,受限标签一经创建,就无法在编辑器中删除,即使是在"受限标签列表"中创建。但是,可以从.ini文件中将它们删除。以下是对应于本示例中的受限标签的"RestrictedTags.ini"文件。从该文件删除标签十分简单,只需删除包含相应"Tag"条目的行即可。

[/Script/GameplayTags.RestrictedGameplayTagsList]
RestrictedGameplayTagList=(bAllowNonRestrictedChildren=False,Tag="RestrictedDesignTags",DevComment="These tags are controlled by the design lead")
RestrictedGameplayTagList=(bAllowNonRestrictedChildren=False,Tag="RestrictedDesignTags.MajorTags",DevComment="These are restricted.")
RestrictedGameplayTagList=(bAllowNonRestrictedChildren=True,Tag="RestrictedDesignTags.MajorTags.EditableTags",DevComment="This is not restricted, unlike its parent.")
RestrictedGameplayTagList=(bAllowNonRestrictedChildren=True,Tag="RestrictedDesignTags.MinorTags",DevComment="These are not restricted.")
RestrictedGameplayTagList=(bAllowNonRestrictedChildren=False,Tag="RestrictedDesignTags.MinorTags.Special",DevComment="This is restricted, unlike its parent.")

Gameplay标签测试运算

有许多测试运算都基于将标签与其他标签匹配的概念,可以对Gameplay标签和Gameplay容器执行。每个函数将对Gameplay标签或Gameplay标签容器调用,并以单个Gameplay标签或Gameplay标签容器为参数。

下表详细列出了标签和标签容器的可用操作。在该表中,格式"A.1"表示单个Gameplay标签,而"{A.1}"表示作为Gameplay标签容器一部分的同一个标签。包含多个标签的容器将采用格式"{A.1, B.1}"。

函数/运算

输入参数

返回值

A.1

MatchesTag

A

true

A.1

MatchesTagExact (or ==)

A

false

A.1

MatchesAny

{A, C}

true

A.1

MatchesAnyExact

{A, C}

false

A.1

MatchesAll

{A}

true

A.1

MatchesAllExact

{A}

false

{A.1, B.1}

HasTag

A

true

{A.1, B.1}

HasTagExact

A

false

{A.1, B.1}

HasAny

{A, C}

true

{A.1, B.1}

HasAnyExact

{A, C}

false

{A.1, B.1}

HasAll

{A, B}

true

{A.1, B.1}

HasAllExact

{A, B}

false

请注意,提供空的或默认的Gameplay标签容器作为输入参数会导致所有运算都返回false,但`HasAllHasAllExactMatchesAll`和`MatchesAllExact`除外。理由是参数容器中没有源集中缺少的标签。

例如,以下蓝图将使用以上提到的部分运算来检测Gameplay标签容器是包含`TestTag.One`还是`TestTag.Three,而不是同时包含这两个标签,且不包含`TestTag.Two(在游戏中产生测试Actor)。对于该测试,我们将在蓝图中使用文字容器值进行测试,但会对Actor容器使用蓝图(或C++变量)。

单击查看大图。

Gameplay标签查询

可以对Gameplay标签容器执行的封装特定类型测试中的 Gameplay标签查询 变量。您可以使用它们以数据驱动测试,在许多地方执行相同的测试,而不必变动及多个变量或多段代码,并通过原生代码执行大部分工作来加速测试。Gameplay标签查询可以执行以下任意三种类型的测试。

  • 如果在容器中找到来自查询的至少一个标签,任何标签匹配 就会成功。

  • 如果查询中没有标签,也没有在容器中没有找到标签,所有标签匹配 就会成功。这包括查询中不存在任何标签的情况。

  • 如果查询中没有标签,而在容器中到了标签,无标签匹配 就会成功。这包括查询中不存在任何标签的情况。

但是,这些测试可以通过三个更大的表达式合并起来,其中每个表达式包含一个额外表达式或测试的数组:

  • 任何一个子表达式或测试成功时,任意表达式匹配 就会成功。

  • 所有子表达式或测试都成功时,所有表达式匹配 就会成功。这包括查询中不存在子表达式或测试的情况。

  • 子表达式或测试均不成功时,无表达式匹配 就会成功。这包括查询中不存在子表达式或测试的情况。

请注意根据以上运算表,所有三种测试类型都指的是"确切"匹配。

我们可以使用一个Gameplay标签查询重现之前的测试示例,即要求`TestTag.One`或`TestTag.Three(而不是同时)位于源容器中,并且要求没有`TestTag.Two。对于该测试,我们将排他使用蓝图(或C++)变量,尽管也支持文字值。这是我们的测试查询变量:

样本Gameplay标签查询变量

通过设置该查询,我们可以按如下所示,在测试Actor蓝图中评估Gameplay标签容器:

单击查看大图。

在游戏中使用Gameplay标签

要将您创建的标签应用于游戏中的对象,向对象添加Gameplay标签(C++类型`FGameplayTag)或Gameplay标签容器(C++类型`FGameplayTagContainer)属性。您还可以根据需要向对象添加 Gameplay标签查询(Gameplay Tag Queries)(C++类型`FGameplayTagQuery`),或者可以直接在蓝图或C++代码中使用标签运算。添加这些属性后,可以从代码或编辑器编辑,就像任何其他变量一样。

在C++中快速访问Gameplay标签

IGameplayTagAssetInterface 可以在C++中实现。同时覆盖 GetOwnedGameplayTags 函数,将会创建一种蓝图可访问方式,以使用与该对象关联的标签填充Gameplay标签容器。在大多数情况下,这只表示从基类将标签复制到新容器,但类实现可能会从多个容器收集标签,或者调用蓝图函数来访问蓝图声明的标签或者对象需要的任何内容。该接口的好处是使您可以一种标准化方法与多个不同的对象类型互动,这样可以获取对象的标签,而不必显式转换对象类型,然后为每个可能的类型编写自定义代码来获取正确的标签变量(或多个变量)。这对于较大项目尤其有用,可以帮助避免(难以重现的)错误,让代码更简洁、更快速、更易于维护。

本文基于此前的虚幻引擎版本编写,未针对当前的虚幻引擎5.0版本更新过。