总览
UGameFeatureAction 是 Game Feature 的执行单元。GameFeatureData 只是一张清单,Action 才是真正改变世界、组件、数据、UI、网络或调试工具的地方。
生命周期先记这个表
| 回调 | 适合做什么 | 注意 |
|---|---|---|
OnGameFeatureRegistering | 注册轻量数据、编辑器预览、路径登记 | 不要加载大量运行时资产 |
OnGameFeatureLoading | 预备即将激活的资源 | 处理软引用和 bundle |
OnGameFeatureActivating(Context) | 把功能应用到世界 | 最常写业务逻辑 |
OnGameFeatureActivated | 激活完成后通知 | 不要做会失败的核心逻辑 |
OnGameFeatureDeactivating(Context) | 拆组件、拆输入、拆 UI、取消异步 | 必须完整清理 |
OnGameFeatureUnloading | 释放加载期资源 | 和 Loading 对称 |
OnGameFeatureUnregistering | 撤销注册期数据 | 和 Registering 对称 |
引擎内置 Action 速查
| Action | 适合 |
|---|---|
Add Components | 给 Pawn、Controller、GameState 等动态加组件 |
DataRegistry | 启用/停用整套 DataRegistry |
DataRegistrySource | 给已有 Registry 添加 DataTable/CurveTable 来源 |
AddWorldPartitionContent / AddWPContent | 加载 World Partition 内容或 Content Bundle |
AddCheats | 给 CheatManager 添加扩展 |
AddChunkOverride | 修改 Chunk 分配,用于打包/分发 |
Create Iris Network Filter | 给 Iris 注册网络过滤器 |
Add Attribute Defaults | AbilitySystemGameFeatureActions 里给 GAS 属性默认表 |
Lyra 的 Action 不全是引擎内置
Lyra 很适合学习,但要分清“引擎能力”和“项目实现”。例如 Lyra 的:
GameFeatureAction_AddAbilitiesGameFeatureAction_AddInputContextMappingGameFeatureAction_AddInputBindingGameFeatureAction_AddWidgetGameFeatureAction_WorldActionBase
这些是 Lyra 项目代码,不是 GameFeatures 插件直接提供的通用类。你的项目可以照着思路写自己的版本。
使用案例:活动模式包
一个活动模式通常需要:
| 需求 | 推荐 Action |
|---|---|
| 给 PlayerState 加活动积分组件 | Add Components |
| 加活动任务表/奖励表 | DataRegistrySource |
| 给 HUD 加活动入口 | 自定义 AddWidget Action |
| 给玩家加活动技能 | 自定义 AddAbilities Action 或 Lyra 风格 |
| 加活动地图区域 | AddWorldPartitionContent |
| 内部测试命令 | AddCheats |
不要把这些全写到一个超大 Action。一个 Action 做一种职责,停用清理才简单。
Data Validation 很重要
很多内置 Action 都实现了 IsDataValid,例如 Add Components 会检查 ActorClass 和 ComponentClass 是否为空,DataRegistrySource 会检查表类型和 Registry 名。你写自定义 Action 也应该做校验,因为 GameFeatureData 往往由策划或技术美术配置。
#if WITH_EDITOR
EDataValidationResult UGameFeatureAction_AddRifleUI::IsDataValid(FDataValidationContext& Context) const
{
EDataValidationResult Result = Super::IsDataValid(Context);
if (ReticleWidgetClass.IsNull())
{
Context.AddError(NSLOCTEXT("GameFeatures", "MissingReticle", "ReticleWidgetClass is missing."));
Result = EDataValidationResult::Invalid;
}
return Result;
}
#endif
架构分析
Action 的重点不是“能打开”,而是“能关干净”。任何在 Activating 里注册的东西,都必须在 Deactivating 或 Unregistering 里撤销。注册 delegate 要保存 handle;添加组件要保存 request handle;创建 UI 要保存 widget handle;授予 Ability 要保存 spec handle;添加 Mapping Context 要保存玩家和 context 关系。
如果你找不到停用时怎么清理,说明这个逻辑可能不适合 Game Feature,或者需要先补一层可撤销接口。
常见坑
- 把所有功能塞进一个巨型 Action,停用时不知道哪些东西来自哪里。
- 只实现
OnGameFeatureActivating()老接口,忘记新接口带 Context,更难处理多世界。 - 在 Registering 阶段同步加载大量资产,导致启动卡顿。
- 自定义 Action 注册 delegate 后不保存 handle,Deactivate 无法解绑。
- 把 Lyra 的类名写进自己的文章/项目,却没把 Lyra 代码移植过来。
源码依据
UGameFeatureAction 定义了 Registering、Loading、Activating、Activated、Deactivating、Unloading、Unregistering。引擎内置 Action 分布在 GameFeatures/Public,例如 AddComponents、DataRegistry、DataRegistrySource、AddWorldPartitionContent、AddCheats、AddChunkOverride、IrisFilterGameFeatureAction。AbilitySystemGameFeatureActions 插件提供 UGameFeatureAction_AddAttributeDefaults。
源码路径索引
GameFeatures/Public/GameFeatureAction.hGameFeatures/Public/GameFeatureAction_AddComponents.hGameFeatures/Public/GameFeatureAction_DataRegistry.hGameFeatures/Public/GameFeatureAction_DataRegistrySource.hGameFeatures/Public/GameFeatureAction_AddWorldPartitionContent.hGameFeatures/Public/GameFeatureAction_AddCheats.hGameFeatures/Public/IrisFilterGameFeatureAction.hExperimental/AbilitySystemGameFeatureActions/Public/GameFeatureAction_AddAttributeDefaults.h