4.2 游戏标签 - Gameplay Tags

FGameplayTags 是通过 GameplayTagManager 进行注册的具备一系列层级的标签名字,如 Parent.Child.Grandchild...。这些标签在分类和描述一个对象的状态时格外有用。例如,如果一个角色被眩晕了,我们可以在眩晕的持续时间之内给它一个 State.Debuff.StunGameplayTag

你会发现其实你是用 GameplayTags 替代了之前用布尔或者枚举来处理的内容,并且通过判断某个对象是否具备特定的 GameplayTags 来进行一些布尔逻辑运算。

当为某个对象赋予标签时,我们通常会将标签添加到对象上的 ASC,这样 GAS 就能和他们产生相应的交互。UAbilitySystemComponent 实现了接口 IGameplayTagAssetInterface 中的给定方法,来访问它所有拥有的 GameplayTags

多个 GameplayTags 可以存储在一个 FGameplayTagContainer 里。这里通常我们更偏向于使用 GameplayTagContainer 而不是 TArray<FGameplayTag>,因为 GameplayTagContainers 中有一些高效的工具。因为标签本质上就是标准的 FName,如果项目设置中的 Fast Replication 处于激活状态的话,他们可以被高效得打包在一起到 FGameplayTagContainers 中,以方便网络复制的使用。Fast Replication 要求服务器和客户端们有着相同的 GameplayTags 列表。这通常并不会有什么问题,所以你尽管激活这个选项就好了。GameplayTagContainers 在遍历时也可以一返回到一个 TArray<FGameplayTag> 数组。

存储在 FGameplayTagCountContainerGameplayTags 有着一个 TagMap,其内存储着相应 GameplayTag 的实例的数量。FGameplayTagCountContainer可能还存在某些 GameplayTag,其对应的 TagMapCount 实际上已经是 0 了。当调试的时候可能就会遇到这种情况。HasTag() 或者 HasMatchingTag() 或者相类似的函数都会去检查 TagMapCount,并且在 GameplayTag 不存在或者相应的TagMapCount为0的情况下直接返回false。

GameplayTags 必须在 DefaultGameplayTags.ini 中提早进行定义。虚幻编辑器在项目设置中提供了一个编辑界面来让开发者管理 GameplayTags,而无需手动编辑 DefaultGameplayTags.ini 文件。GameplayTag 的编辑器内可以进行创建、改名、查找引用以及删除操作。

GameplayTag Editor in Project Settings

查找 GameplayTag 的引用将会在编辑器内打开一个类似 Reference Viewer 的图形界面,其中展示了所有引用 GameplayTag 的资产。当然,不包括任何 C++ 类。

重命名 GameplayTag 实际上是创建了一个重定向,与原 GameplayTag 有引用关系的资产可以通过这个重定向找到新的 GameplayTag。我偏向于创建一个新的 GameplayTag,然后手动更新所有的引用,然后删除掉旧的 GameplayTag,从而避免创建一个重定向。

除了 Fast ReplicationGameplayTag 编辑器中有一个选项可以选择常用的网络复制的 GameplayTag,从而进一步实现优化。

如果 GameplayTag 是由 GameplayEffect 添加的话,那他们就会被复制。ASC 可以让你添加不会被复制并且必须手动管理的 LooseGameplayTags。示例项目使用 LooseGameplayTag 来作为 State.Dead,这样所属客户端在他们的hp降为0后就能够立即响应。重生的时候需要手动得将 TagMapCount 设置回 0。仅在使用 LooseGameplayTags 时才会用到手动调整 TagMapCount。我偏向于使用 UAbilitySystemComponent::AddLooseGameplayTag()UAbilitySystemComponent::RemoveLooseGameplayTag() 这两个函数,而不是直接手动调整TagMapCount

在C++中去获取GameplayTag的引用:

FGameplayTag::RequestGameplayTag(FName("Your.GameplayTag.Name"))

至于高级的 GameplayTag 的相关操作如获取父级或者子级的 GameplayTag,参考 GameplayTagManager 中提供的一些方法。要访问 GameplayTagManager,首先要包含 GameplayTagManager.h 头文件,然后调用 UGameplayTagManager::Get().FunctionName 函数即可。实际上 GameplayTagManagerGameplayTag 存储为关系节点(父,子,等等),所以处理速度要快于字符串的操作和比较。

GameplayTagsGameplayTagContainers 可以通过 UPROPERTY 中的说明符 Meta = (Categories = "GameplayCue") 来过滤蓝图中的标签,从而仅显示父级标签为 GameplayCue 的那些 GameplayTags。当你知道那些仅用于 GameplayCuesGameplayTag 或者 GameplayTagContainer 变量时这样的操作就非常有用处了。

此外,还有一个单独的结构体 FGameplayCueTag 封装了 FGameplayTag,这样也可以实现上面的那种过滤的效果。

如果你想在一个函数中过滤 GameplayTag 参数时,可以使用 UFUNCTION 中的说明符Meta = (GameplayTagFilter = "GameplayCue")。而函数中的 GameplayTagContainer 参数是不可以被过滤的(译者注:现在已经支持过滤的特性,但是后续翻译时仍然保留了相关描述,目的是让大家了解相关特性是如何通过元数据进行支持的)。如果你想要让你的引擎支持这个特性,参考 Engine\Plugins\Editor\GameplayTagsEditor\Source\GameplayTagsEditor\Private\SGameplayTagGraphPin.cpp 中的函数 SGameplayTagGraphPin::ParseDefaultValueData() 是怎样调用 FilterString = UGameplayTagsManager::Get().GetCategoriesMetaFromField(PinStructType); 并且在函数 SGameplayTagGraphPin::GetListContent() 中传递 FilterStringSGameplayTagWidgetEngine\Plugins\Editor\GameplayTagsEditor\Source\GameplayTagsEditor\Private\SGameplayTagContainerGraphPin.cpp 中的 GameplayTagContainer 相关函数并没有检查元字段属性并代入过滤器。

示例项目广泛使用了 GameplayTags

4.2.1 响应游戏标签的变化 - Responding to Changes in Gameplay Tags

ASCGameplayTags 的添加和删除提供了相应的委托。需要给定一个 EGameplayTagEventType 来表明事件类型,即是 GameplayTags 的增加亦或是删除,还是 GameplayTagTagMapCount发生了变化之类的。

AbilitySystemComponent->RegisterGameplayTagEvent(FGameplayTag::RequestGameplayTag(FName("State.Debuff.Stun")), EGameplayTagEventType::NewOrRemoved).AddUObject(this, &AGDPlayerState::StunTagChanged);

回调函数中有两个参数,分别是 GameplayTag 和新的 TagCount

virtual void StunTagChanged(const FGameplayTag CallbackTag, int32 NewCount);
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值