总览
Game Features 上线前只问一句话:能不能开、能不能关、关完有没有残留。 如果答案不确定,就先别把它用于线上活动、DLC 或赛季功能。
常用命令
| 命令 | 用途 |
|---|---|
ListGameFeaturePlugins | 列出插件和当前状态,可加 -activeonly、-csv |
LoadGameFeaturePlugin Name | 加载并激活 |
DeactivateGameFeaturePlugin Name | 停用但保留已加载状态 |
UnloadGameFeaturePlugin Name | 卸载 |
CancelGameFeaturePlugin Name | 取消正在进行的状态变化 |
TerminateGameFeaturePlugin Name | 终止状态机 |
GameFeaturePlugin.PrintLoadStats | 打印 GFP 加载包统计 |
ModularGameplay.DumpGameFrameworkComponentManagers | Dump Receiver、Component、Request |
关键 CVar
| CVar | 用途 |
|---|---|
GameFeaturePlugin.AsyncLoad | 控制异步加载 |
GameFeaturePlugin.ForceAsyncLoad | Policy 层强制异步 |
GameFeaturePlugin.EnableAssetStreaming | 资源流送相关 |
GameFeaturePlugin.EnableBatchProcessing | 批量状态推进 |
GameFeaturePlugin.UseNewExecutor | 新状态机执行器 |
GameFeaturePlugin.TrackLoadStats | 跟踪加载统计 |
GameFeaturePlugin.DebugGFPName | 指定调试 GFP 名称 |
这些不是都要改。默认先用日志和 Dump,只有定位加载/执行器问题时再动 CVar。
多人项目检查
| 问题 | 检查方法 |
|---|---|
| 服务器是否也激活该包 | Listen/Dedicated 分别 ListGameFeaturePlugins |
| Client-only 组件是否没上服务器 | Dump Component Manager |
| Ability 是否服务器授予、客户端预测 | GAS debug + GameplayTag 检查 |
| UI/输入是否只在本地玩家添加 | 本地双人和远程客户端测试 |
| 停用时是否清 Ability/IMC/UI | Deactivate 后重复 Dump |
不要只在单机 PIE 测 Game Feature。至少测 Standalone、Listen Server、Dedicated Server、客户端重连、地图切换。
回滚策略
线上功能包必须能回滚:
- 新包默认
Registered,由配置或服务器指令激活。 - 激活前预加载并检查 Result。
- 激活失败不切 UI 状态,给玩家 fallback。
- Deactivate 能撤输入、UI、组件、Ability、数据源。
- 如果停用失败,有日志和报警,不要静默失败。
活动玩法尤其要有“开关配置”。不能靠发新包才能关闭事故功能。
使用案例:线上活动临时关闭
假设 Feature_Season12_Rift 的奖励结算出现问题,运营配置先禁止新玩家激活该 Feature;在线玩家收到配置后,客户端移除活动 UI 和输入,服务器停用奖励发放组件和 DataRegistrySource。已有未结算数据进入补偿队列,而不是直接丢失。这个流程能跑通,Game Feature 才算真的有回滚价值。
架构分析
生产环境里 Game Feature 是“带生命周期的变更单元”。它不只是代码组织方式,还承担风险隔离:一个玩法包失败时,应该能阻止继续激活、能撤销运行时注入、能保留必要数据、能给玩家 fallback。调试命令和 Dump 不是装饰,而是证明“这个变更单元边界清楚”的工具。
生产目录规范
Plugins/GameFeatures/<FeatureName>/
Config/Tags/
Content/
DA_GameFeatureData_<FeatureName>
Data/
UI/
Input/
Abilities/
Maps/
Source/<FeatureName>Runtime/
Tests/
命名建议:
- 插件:
Feature_Season12_Rift - Tag:
Feature.Season12.Rift - GameFeatureData:
DA_GFD_Season12_Rift - Action:
GFA_AddSeason12RiftUI - 组件:
USeason12RiftComponent
上线检查清单
ListGameFeaturePlugins能看到目标包。LoadGameFeaturePlugin后所有 Action 生效。DeactivateGameFeaturePlugin后组件、输入、UI、Ability、DataRegistrySource 都清理。ModularGameplay.DumpGameFrameworkComponentManagers没有残留错误 Receiver/Request。- Dedicated Server 没加载 Client-only UI 资源。
- 新玩家中途加入时能获得正确组件和输入。
- 地图切换后组件请求仍然正确或按设计被清掉。
- Cook 产物包含所有软引用资源。
- 激活失败 Result 被显示/记录,并有 fallback。
常见坑
- 只测试加载,不测试停用。
- 多次 Load/Deactivate 后组件数量递增。
- 地图切换后 GameInstance 保留请求,但旧 World 的对象已失效。
- 客户端激活了 UI,服务器没激活 Ability,表现和权威脱节。
- Action 停用等待异步,但 delegate 永远不回调,状态机卡住。
源码依据
GameFeaturesSubsystem.cpp 注册了 List/Load/Deactivate/Unload/Release/Cancel/Terminate 和 DebugState 控制台命令。GameFeaturePluginStateMachine.cpp 定义了 GameFeaturePlugin.* 系列 CVar 和 Trace 事件。GameFrameworkComponentManager.cpp 注册 ModularGameplay.DumpGameFrameworkComponentManagers,会输出 Receivers、Components、Requests 等调试信息。
源码路径索引
GameFeatures/Private/GameFeaturesSubsystem.cppGameFeatures/Private/GameFeaturePluginStateMachine.cppModularGameplay/Private/Components/GameFrameworkComponentManager.cppGameFeatures/Public/GameFeaturesProjectPolicies.hGameFeatures/Public/GameFeatureStateChangeObserver.h