GameFeature功能使用备忘
主要概念
加载状态
- Installed:代表“内容在磁盘上/已下载到位、系统允许你去装载它”。但此时 Pak 还可能没 mount,所以 UE 的资产系统未必能通过路径找到它的 Content。
- Mount(挂载):是让 Pak/目录进入虚拟文件系统,使得
/PluginName/...之类的资源路径变得可见。只有 mount 之后,很多资源引用(尤其硬引用链、以及软引用的实际 Load)才更可能成功。
加载顺序流程图
1 | flowchart LR |
GameFeatures 插件的 4 个 CurrentState
这四个状态本质上是 GameFeature 插件状态机 的关键里程碑,用来描述一个 GFP 从“可发现”到“可用/生效”的过程;它们也直接决定了 跨 GFP 资产引用 在运行时是否会因为未挂载/未加载而失败。
- Installed(已安装/可用)
- 含义:插件对系统来说“存在且可被安装/卸载管理”。如果是可选下载内容(DLC/Chunk/可选 Pak),此状态通常表示已完成安装步骤。知道有光盘,但没读取光盘。
- 你能依赖什么:还 不保证 Content 已 mount,所以此时去加载资产路径通常仍不可靠。
- Registered(已注册/已发现)
- 含义:插件已被识别并完成注册;对应的
GameFeatureData能被找到,系统知道“这个 GFP 有哪些 Actions/规则”。光盘插入了光驱,可以读取它,但是里面啥不知道。 - 你能依赖什么:一般仍 不保证资产已可加载(很多项目里 mount 发生在后续阶段或紧随其后),但可以进行“声明式”的准备(例如建立要执行哪些 Actions 的清单)。
- Loaded(已加载)
- 含义:插件内容已准备到“可以加载资产/类”的程度(典型情况下包括 Pak 已 mount、资产包路径可解析)。进入了游戏,但是游戏功能没用。
- 你能依赖什么:此时 软引用/硬引用的目标资产才有较大概率能成功解析与加载;跨 GFP 的 Content 引用若要求 B(另外一个GFP插件资产) 的资产可用,至少需要 B 达到
Loaded。
- Active(已激活/已生效)
- 含义:
GameFeatureData中的 Actions 已实际执行并对游戏世界产生效果(例如添加组件、注册能力/输入、注入数据、启用系统等)。游戏的玩法已经加载 - 你能依赖什么:除“资产可加载”外,还能依赖“玩法逻辑已经注册/启用”。跨 GFP 依赖如果不仅是资产,还需要 B 的系统在运行时提供服务(比如注册表、Subsystem、组件注入),通常要求 B 达到
Active。
三种“引用”
资产硬引用(Hard Reference)
- 例:材质实例
MI直接指定另一个 GFP 里的Parent Material;蓝图默认值直接指向外部资产等。 - 特点:会形成固定的加载依赖链;如果目标资产不可用,会在加载时出问题。
- 例:材质实例
资产软引用(Soft Reference)
- 例:
TSoftObjectPtr/ Path 引用;Primary Asset Id;DataAsset 内记录路径但不立刻加载。 - 特点:只有在解析/加载时才需要目标资产可用;更适合“按需加载”。
- 例:
代码/模块依赖(C++ Module Dependency)
- 例:
A的*.Build.cs或*.uplugin里把B模块作为依赖。 - 特点:属于编译期/链接期依赖;通常意味着“不可拆分”。
- 例:
本文重点讨论 资产层(Content)跨 GFP 引用。
GameFeatureAsset
GameFeatureAsset(通常为 GameFeatureData)是 GameFeature 插件的入口资产,用于声明该功能在 Registered/Loaded/Active 阶段要执行的 Actions、注入的组件/能力/数据,以及可选的依赖与卸载逻辑;运行时以它驱动插件状态机。
- 每一个 GameFeature 插件至少需要一个 GameFeatureAsset 作为入口(通常放在
Content/目录下)。
GameFeaturesActions

激活这个插件,就会执行的一些玩法。
GameFeaturesAssetManager

开启这个插件虚幻会去加载的资源。
Rules是优先级问题。比如下载了部分,就可以进行游玩了。
lang: “zh-CN”
使用逻辑
开启插件需要的内容GameFeature、Modualr Gameplay。
允许 / 限制 / 不推荐:判定标准
允许(推荐)
- GFP 内部自引用:
GFP A引用GFP A/Content的资产。 - GFP 引用引擎内容(如
Engine Content)在很多项目中是可接受的(取决于团队规范)。 - GFP 引用“共享内容插件/基础内容包”(非 GFP 或作为明确基础依赖的 GFP),并确保它在游戏启动时就被挂载。
允许但不推荐(高耦合、易踩坑)
- GFP A 引用 GFP B 的 Content,但没有明确保证
B在A之前被安装/挂载/激活。- 在编辑器里经常“看起来没问题”,但运行时按需加载时可能失败。
- 会削弱 GFP 的可插拔性(A 不能独立启用/禁用)。
会被 GameFeatures 运行时逻辑“限制”(可能直接失败)
- A 激活时就需要解析/加载 B 的资产,但 B 未挂载(pak 未 mount、plugin 未 install)。
- 常见表现:软引用加载失败、硬引用加载时找不到包、或触发意外的依赖加载顺序问题。
注意:这类“限制”通常不是“编译时报错”,而是 运行时加载链/挂载顺序导致的不确定性。
依赖关系流程图(Mermaid)
说明:
- 实线:建议/允许
- 虚线:允许但不推荐(除非你明确控制加载顺序或声明依赖)
- 红色:运行时逻辑限制,可能失败(B 未挂载/未激活时被引用)
1 | flowchart LR |
Debug
Debug方案
用 Reference Viewer 检查 A 的关键资产是否硬引用到 B。
可以点击那个小眼睛,然后“ShowAssetPath”,来看每一个引用和被引用资产的路径。
确认运行时:
- A 激活前,B 是否已
Install + Mount + Activate? - 若 B 未激活,A 是否仍能独立运行?
- A 激活前,B 是否已
若无法保证顺序:把共享资产上移到共享插件/基础包。
一个GameFeature引用另一个GameFeature的Content,但在UI上检查不出哪里有引用
表面上看起来这两个没有执行的节点人畜无害。



但实际上: 它是从ABP_Main_Youan_DNA_C直接拷贝过来的两个节点。
编辑器的UI中并没有直接显示这两个节点一些信息(从哪里拷贝过来) 并且这个叫Livelinksubject的变量,在当前蓝图中不存在,所以该节点信息没有更新。 又因为这个节点没有接通,所以Compile的时候不会识别到这个问题报错。 所以导致引用的时候莫名其妙地应用了GameFeatures YouAn的内容。
这个故事告诉我们一个道理: 不要留下废的蓝图节点。
材质相关引用
材质/材质实例常见的跨 GFP 引用方式是:
MI_A(在 GFP A)以M_B(在 GFP B)作为 Parent Material 或引用了 B 中的 Material Function / Texture。
这会产生 硬引用链,意味着:
- A 的某些资产被加载时,B 的资产也必须可用;
- 如果按需激活流程里 B 没有先 mount,A 的加载可能直接失败。
建议处理方式(按优先级):
把公共材质基类/材质函数/共享贴图迁移到共享内容位置
- 例如:
Plugins/SharedAssets/Content/...(普通内容插件) - 或建立一个“明确基础依赖的 GFP”(但它就成了所有依赖方的前置条件)。
- 例如:
保留跨 GFP 引用,但显式声明/保证加载顺序
- 在你们的 GameFeature 管理逻辑中实现:激活 A 前先安装/激活 B。
- 适用场景:A 与 B 本就打包为一组功能,无法独立启停。
改为软引用 + 激活时解析
- 让 A 不在编辑期形成硬引用链;在激活阶段通过路径/Primary Asset 解析并加载。