总览
当项目变大,问题会从“怎么选结果”变成“同一个逻辑在不同角色、皮肤、武器包、DLC 下返回不同资产”。如果每个包复制一张 Chooser 表,维护会很痛。ProxyTable 和嵌套 Chooser 就是用来降低这种重复的。
ProxyAsset 是“我要的东西”
UProxyAsset 可以理解成一个抽象请求:我要 Proxy.Combo.Light02.Montage,但具体给哪段 Montage,由当前 ProxyTable 决定。
它包含:
| 字段 | 用途 |
|---|---|
| Type | 期望输出类型 |
| ResultType | Object/Class |
| ContextData | 解析时需要的上下文 |
| Guid | 稳定 Key |
ProxyTable 是“这个内容包给的实现”
UProxyTable 里有多条 FProxyEntry,每条把 ProxyAsset 映射到一个 FObjectChooserBase 值。这个值可以是具体资产,也可以是 Evaluate Chooser、Nested Chooser、其它 ObjectChooser。
比如同一个 Proxy:
Proxy.Combo.Light02.Montage
不同表可以映射成:
DefaultHeroProxyTable -> AM_Default_Light02
SamuraiSkinProxyTable -> AM_Samurai_Light02
IceSwordProxyTable -> CHT_IceSword_Light02_Variants
LookupProxy 怎么用
动画节点或 Chooser Result 里可以使用 Lookup Proxy。运行时根据 Context 找到合适的 ProxyTable,再解析 ProxyAsset。蓝图侧有 EvaluateProxyAsset,也有 MakeLookupProxy 和 MakeLookupProxyWithOverrideTable。
初学可以先用显式 OverrideTable,项目成熟后再建立“当前角色/皮肤/武器拥有哪张 ProxyTable”的上下文规则。
嵌套 Chooser vs 独立 Chooser
| 方式 | 适合 |
|---|---|
| Nested Chooser | 同一个资产里小范围分支,方便一起编辑 |
| Evaluate Chooser | 可复用的大分支,多个系统共享 |
| ProxyTable | 内容包覆盖、皮肤/武器/角色变体 |
不要用 ProxyTable 替代所有表。ProxyTable 解决间接映射和覆盖,Chooser 解决上下文决策。
使用案例:玩家连招 + 皮肤动画覆盖
战斗流程:
- Gameplay Chooser 选中
Move.Sword.Light02。 - MoveData 里引用一个 ProxyAsset:
Proxy.Move.Light02.Montage。 - 当前角色皮肤提供
SkinProxyTable。 - LookupProxy 解析出
AM_Samurai_Light02。 - 如果皮肤没有覆盖,继承表回退到默认 Montage。
玩家连招档案不需要关心皮肤资产;皮肤包也不需要修改玩家的连招配置。
使用案例:Game Feature 武器包
一个武器包可以带自己的 ProxyTable:
WeaponPack_IceSword
PT_IceSword_ComboAssets
CHT_IceSword_LightVariants
DA_Move_IceSpin
AM_IceSpin_A
AM_IceSpin_B
Game Feature 激活后,把这张 ProxyTable 加入角色或装备上下文。Chooser 表仍然请求同一个 ProxyAsset,但解析结果变成冰剑包里的资产。
架构分析
Proxy 的价值是解耦“语义”和“实现”。语义是 Light02 Montage,实现是某个资产或某张子表。大型项目里语义最好稳定,内容包可以替换实现。这样玩家档案、技能表、动画表、皮肤包不需要互相硬引用。
常见坑
- ProxyAsset 太细,项目里出现成百上千个难维护 Key。
- ProxyTable 继承链太深,调试不知道最终来自哪张表。
- 用 ProxyTable 做条件判断,结果表和选择职责混乱。
- Proxy 返回类型和调用方期望不一致。
- Game Feature 停用后还持有 ProxyTable 强引用,内容包卸不干净。
源码依据
UProxyAsset 声明 Type、ResultType、ContextData 和 Guid。UProxyTable 运行时有 RuntimeValues,编辑器期有 Entries 和 InheritEntriesFrom。FProxyEntry 的 ValueStruct 是 FObjectChooserBase,因此 Proxy 可以解析到具体对象,也可以继续 Evaluate Chooser。UProxyTableFunctionLibrary 提供 EvaluateProxyAsset、MakeLookupProxy 和带 OverrideTable 的版本。
源码路径索引
Engine/Plugins/Chooser/Source/ProxyTable/Public/ProxyAsset.hEngine/Plugins/Chooser/Source/ProxyTable/Public/ProxyTable.hEngine/Plugins/Chooser/Source/ProxyTable/Public/ProxyTableFunctionLibrary.hEngine/Plugins/Chooser/Source/ProxyTable/Internal/LookupProxy.hEngine/Plugins/Chooser/Source/Chooser/Public/Chooser.hEngine/Plugins/Chooser/Source/Chooser/Private/Chooser.cpp