目录

Unreal - Tag与GameplayTag

1. Actor Tags:基础但脆弱的“老兵”

Actor Tags 是定义在 AActor 类中的一个简单字符串数组: TArray<FName> Tags;

特点:

  • 实现简单:你可以直接在 Actor 的 Details 面板里手动输入任何字符串。
  • 扁平化结构:它是完全平等的字符串列表,没有层级关系。
  • 低门槛:不需要任何前置配置。

致命弱点:

  • 拼写地狱(Typo-Prone):你在代码里检查 "Stunned",但策划在编辑器里手抖打成了 "Stuned"。编译器不会报错,但你的逻辑会莫名其妙地失效。
  • 缺乏逻辑关联:如果你想检查一个角色是否处于“任何负面状态”,你必须手动列出 "Stunned", "Frozen", "Burned"。你无法通过类似“所有的 Debuff”这样的母概念来查询。
  • 性能瓶颈:在大规模查询时,字符串比较的效率远低于数值比较。

2. Gameplay Tags:结构化与高性能的“现代派”

Gameplay Tags 是随 GAS 系统一同发扬光大的高级标签系统。它不再是随手乱写的字符串,而是需要在项目设置中注册的规范化数据

特点:

  • 层级结构(Hierarchical):支持 A.B.C 的格式。例如 State.Debuff.Stun
  • 高性能:虽然我们在编辑器里看到的是文字,但其底层会被转换为唯一的 32位整数 ID。这意味着在执行“是否拥有该标签”的检查时,本质上是极快的整数比对。
  • 强类型安全:你只能从预定义的列表中选择标签,彻底杜绝了拼写错误。
  • 容器化(Container):配套的 FGameplayTagContainer 支持强大的位运算,可以瞬间判断“包含全部”、“包含任意”或“不包含”。

3. 核心差异对决

特性 Actor Tags (FName Tags) Gameplay Tags
底层数据 FName (字符串) int32 (整数 ID)
结构形态 扁平数组 (Flat) 树状层级 (Hierarchical)
容错率 极低 (拼写错误无提醒) 极高 (IDE/编辑器自动补全)
查询性能 一般 极快
逻辑深度 仅支持精确匹配 支持父子包含关系(匹配 A 即可匹配 A.B)
管理方式 散落在各个 Actor 实例中 中心化管理 (Data Table 或 .ini)

4. 为什么 GAS 选择了 Gameplay Tags?

GAS 的核心灵魂是 “基于状态的逻辑切换”。如果没有 Gameplay Tags,GAS 几乎无法工作。

A. 模糊匹配的威力

假设你的技能要求“目标不能处于任何 Debuff 状态”。

  • 使用 Actor Tags:你需要检查目标是否不含标签 A、B、C…(如果以后新加了 D 状态,所有技能代码都要改)。
  • 使用 Gameplay Tags:你只需要检查目标是否拥有 State.Debuff。无论子级是 Stun 还是新加的 Sleep,只要它属于 State.Debuff 的子树,系统就能自动识别。

B. 数据驱动的解耦

Gameplay Tags 允许策划在不触碰 C++ 代码的情况下,通过修改 GE(Gameplay Effect)里的标签组合,直接改变技能的互斥、中止和叠加逻辑。

C. 网络同步优化

由于 Gameplay Tags 内部是整数,它在网络传输时的开销远小于发送长字符串,这对于高频同步的多人对战游戏至关重要。


5. 什么时候该用哪种?

  • 使用 Actor Tags 的场景

    • 非常简单的原型开发。
    • 非游戏逻辑的简单标记(例如:标识场景中哪些物体是“可抓取的”)。
    • 由于历史原因残留的旧插件接口。
  • 使用 Gameplay Tags 的场景(推荐)

    • 所有的战斗系统、技能系统、状态系统
    • UI 数据的分类与筛选。
    • 复杂的交互逻辑(如:只有手持 Item.Key.Blue 的玩家才能打开 Door.Blue)。

结语

如果说 Actor Tags 是路边随处可见的便利贴,那么 Gameplay Tags 就是图书馆里的索引系统。

对于追求严谨、性能和可扩展性的虚幻开发者来说,尽快抛弃 Actor Tags 并全面拥抱 Gameplay Tags,是迈向高级架构师的必经之路。


版权声明:本文为原创技术博客,转载请注明出处。