文章目录
前言
深入 GAS(Gameplay Ability System)中的 Tag System 实现原理,这是 GAS 中一个非常精巧且强大的模块,支撑了:
- 技能激活条件
- 效果(GE)应用与否
- 角色状态判断(如“眩晕”、“隐身”)
- 整个系统的“规则引擎”和“语义判定”
一、Tag System 是什么?
-
GameplayTag 是一种 轻量级语义标记系统,其本质是用于:
- 表达角色、技能、效果、属性等的语义状态和行为约束。
类似状态机中的“状态标识”或者 ECS 中的“标签组件”。
例如:
Tag: Status.Stunned ← 表示眩晕
Tag: Ability.BlockJump ← 表示禁止跳跃
Tag: Skill.Fireball ← 表示火球技能
Tag: Relationship.Enemy ← 表示敌人单位
它们可以被:
- GE 授予/移除
- GA 监听/过滤
- AttributeSet 逻辑判断
- 网络同步/自动触发回调
二、核心结构组成
类名 | 作用 |
---|---|
FGameplayTag | 单个标签结构,底层是 FName |
FGameplayTagContainer | 标签容器,可包含多个标签 |
UGameplayTagsManager | 全局管理器,构建标签层级和注册表 |
GameplayTag.ini | 标签配置文件,集中定义标签结构 |
三、标签的底层原理
- FGameplayTag
这是标签的最小单元,本质是个 FName,但支持层级结构:
FGameplayTag StunTag = FGameplayTag::RequestGameplayTag("Status.Stunned");
层级结构以 . 分隔,例如:
Status
├── Status.Stunned
├── Status.Rooted
Ability
├── Ability.Magic
│ └── Ability.Magic.Fireball
支持“包含关系”判断:
StunTag.MatchesTag("Status") → true
- FGameplayTagContainer
容器类,表示“拥有的一组标签”:
FGameplayTagContainer Tags;
Tags.AddTag(FGameplayTag::RequestGameplayTag("Status.Stunned"));
-
可以用于:
-
判断是否包含某个标签或子标签
添加/移除标签
与其他容器做交集、并集等运算
四、标签系统的运行机制
GAS 中使用 Tag 的方式主要分为以下几类:
- 技能(GA)激活条件控制
AbilityTags: Ability.Fireball
ActivationBlockedTags: Status.Stunned
ActivationRequiredTags: State.CombatReady
激活前 GAS 会做自动检查:
if (OwnerHasTag(Status.Stunned)) {
BlockActivation();
}
- 效果(GE)的条件过滤
GrantedTags: Status.Stunned // 被应用时添加这个标签
OngoingTagRequirements:
Required: Target.IsAlive
Blocked: Target.HasShield
- 技能触发、监听和响应
使用 WaitGameplayEvent 监听具有某标签的 GameplayEvent:
WaitGameplayEvent(EventTag = "Event.OnHit")
- 网络同步与事件广播
GAS 会自动在网络上传输 TagContainer 变化,比如一个 GE 添加了 Status.Stunned,所有客户端都知道它被“眩晕”了。
五、Tag 系统与其他模块协同逻辑
模块 | 使用方式 |
---|---|
Ability(GA) | 控制是否能激活、是否中断 |
Effect(GE) | 控制能否应用、应用时授予标签 |
AttributeSet | 用来判定当前状态,比如不能回血 |
ASC | 保持一个 OwnedTags,动态更新角色状态 |
示例:火球技能不能在“沉默”状态下释放
AbilityTags = Ability.Magic.Fireball
ActivationBlockedTags = Status.Silenced
当角色被施加了 GE:Status.Silenced,该 GA 自动不能激活。
六、如何维护和组织标签:GameplayTags.ini
推荐统一维护所有标签,在 DefaultGameplayTags.ini 文件中注册:
[GameplayTags]
+GameplayTags=Ability.Magic.Fireball
+GameplayTags=Status.Stunned
+GameplayTags=Status.Silenced
+GameplayTags=Target.Friendly
+GameplayTags=Target.Enemy
优点:
- 自动提示 / 蓝图可选
- 防止拼写错误
- 支持导出层级树(调试友好)
七、底层调用逻辑示意(源码)
bool FGameplayTagContainer::HasTag(FGameplayTag TagToCheck, bool bExactMatch) const
{
for (const FGameplayTag& Tag : GameplayTags)
{
if (Tag.MatchesTag(TagToCheck)) return true;
}
return false;
}
bool FGameplayTag::MatchesTag(const FGameplayTag& OtherTag) const
{
return OtherTag == ThisTag || OtherTag.IsParentOf(ThisTag);
}
GAS 利用层级结构快速做匹配判断。
八、调试和可视化技巧
-
Gameplay Debugger GDT(按 ~ 打开)
显示当前角色所有 Active Tags -
ASC 的 GetOwnedGameplayTags()
随时可打印当前标签状态 -
蓝图中可用 “Has Matching Gameplay Tag”、“Add Gameplay Tag” 节点操作
九、使用规范建议
场景 | 推荐做法 |
---|---|
表示状态 | Status.xxx(如 Status.Stunned) |
分类技能 | Ability.Class.Type(如 Ability.Magic.Fireball) |
表示阻断 | Block.Action(如 Block.Jump) |
表示目标类型 | Target.Enemy / Target.Self |
表示 BUFF、DEBUFF | Effect.Buff.SpeedUp / Effect.Debuff.Slow |
总结:Tag 是 GAS 的“布尔变量 + 规则引擎”
-
不要写 if(状态==1),而是:
- 通过标签系统进行统一的语义控制、判定与过滤。
模块 | 使用 Tag 的方式 |
---|---|
GA | 激活限制、冷却中断、触发事件 |
GE | 应用判断、附加状态标签 |
ASC | 状态维护、网络同步 |
UI/逻辑 | 状态显示、行为约束 |