5.7 KiB
UCommandRouter
基本信息
- 类型: UCLASS(BlueprintType, EditInlineNew, DefaultToInstanced)
- 父类: UObject, implements ICommandEndpoint
- 源文件: Plugins/CharacterControl/Source/CharacterControl/Public/CommandRouter.h
- 模块: CharacterControl
功能概述
Core command routing engine. Manages child endpoint registry (TMap<FGuid, FEndpointEntry>). Implements tag-based matching with two modes: continuous (tag + ContinuousFriendly check) and discrete (tag ALL/ANY matching). Tag aggregation system merges child tags upward with ref-counting. Hop-limit guarded dispatch. Upward propagation for child output commands. Self-identity protection prevents circular registration.
设计用意
Heart of the plugin. Tag-based publish-subscribe bus replacing hard references. Hierarchical tree topology support (routers inside routers). Hop-limit prevents infinite loops. Tag aggregation enables efficient parent-level filtering. EditInlineNew/DefaultToInstanced for embedding in components.
职责范围
Command routing and endpoint management. Registers/unregisters endpoints. Matches and dispatches commands. Aggregates and manages tag subscriptions. Does NOT generate commands (input components do that).
项目内依赖
| 依赖项 | 关系 | 源文件 |
|---|---|---|
| CommandEndpoint.h | #include | Plugins/CharacterControl/Source/CharacterControl/Public/CommandEndpoint.h |
对外接口
UCommandRouter 是命令路由系统的核心引擎。作为 UObject(EditInlineNew, DefaultToInstanced) 且实现 ICommandEndpoint,它既可以嵌入组件又可以参与上级路由。蓝图和 C++ 均可调用以下 UFUNCTION:
端点管理(BlueprintCallable):
- RegisterEndpoint(TScriptInterface) -> bool: 注册一个端点。检查 GUID 有效性、重复注册、自注册防护。注册成功后绑定端点的两个委托并执行标签聚合。返回 false 表示注册失败
- UnregisterEndpoint(const FGuid&) -> bool: 按 GUID 注销端点。解绑委托、移除标签聚合、从注册表删除
- UnregisterEndpointByInterface(TScriptInterface) -> bool: 按接口指针注销端点,内部提取 GUID 后转调 UnregisterEndpoint
- ClearAllEndpoints(): 批量注销所有已注册端点。遍历收集所有端点后逐个调用 UnregisterEndpointByInterface
- GetEndpointCount() -> int32: 返回当前已注册端点数量
路由器自身配置(BlueprintCallable):
- SetRouterState(const FEndpointState&): 设置路由器作为端点时的配置。只更新 InterestedTags/bIsActive/bIsContinuousFriendly/bIsAsynchronous 字段,保留 EndpointGuid。更新后广播 StateChangedDelegate
- GetRouterState() -> FEndpointState: 返回当前路由器的端点状态
命令输入(BlueprintCallable):
- InputCommand(const FCommandPacket&): 向路由器注入命令,直接调用 ReceiveCommand 触发路由逻辑。可用于外部系统或上级路由器向本路由器投递命令
委托(public field):
- StateChangedDelegate (FOnEndpointStateChanged): 路由器自身状态变更时广播
- CommandOutputDelegate (FOnCommandOutput): 路由器作为端点向上级输出的命令通过此委托广播
使用方法
UCommandRouter 通常不直接使用,而是通过 UCommandRouterComponent 包裹后挂载到 Actor:
- 组件嵌入选框:
Plugins/CharacterControl/Source/CharacterControl/Private/CommandRouterComponent.cpp:15-- UCommandRouterComponent 通过 CreateDefaultSubobject 创建 InternalRouter - 端点注册入口:
Plugins/CharacterControl/Source/CharacterControl/Private/CommandRouter.cpp:45-84-- RegisterEndpoint 的完整注册流程 - 命令分发:
Plugins/CharacterControl/Source/CharacterControl/Private/CommandRouter.cpp:13-31-- ReceiveCommand 入口:HopLimit 检查 -> 递减 -> 按类型分发 - 离散路由:
Plugins/CharacterControl/Source/CharacterControl/Private/CommandRouter.cpp:164-197-- RouteDiscreteCommand 遍历注册表,提取离散元数据,对每个匹配端点投递 - 连续路由:
Plugins/CharacterControl/Source/CharacterControl/Private/CommandRouter.cpp:199-218-- RouteContinuousCommand 遍历注册表,对每个 bIsContinuousFriendly 且 Tag 匹配端点投递 - 端点注册:
Plugins/CharacterControl/Source/CharacterControl/Private/EndpointComponent.cpp:38-- UEndpointComponent::BeginPlay 找到兄弟 UCommandRouterComponent 后调用Router->InternalRouter->RegisterEndpoint(this)
用例
- 命令注入:
Plugins/CharacterControl/Source/CharacterControl/Private/CommandRouter.cpp:145-162-- OnRegisteredEndpointOutputCommand 接收子端点产出的命令:上行命令先投递本地再转发上级,非上行命令直接投递本地端点 - 端点注册完整流程:
Plugins/CharacterControl/Source/CharacterControl/Private/CommandRouter.cpp:45-84-- 验证 -> 注册 -> 委托绑定(BindDynamic) -> 标签聚合(AddEndpointToAggregation),全在 RegisterEndpoint 中完成 - 上行传播:
Plugins/CharacterControl/Source/CharacterControl/Private/CommandRouter.cpp:148-155-- bIsUpward 命令处理:拷贝命令清除上行标志后本地投递,同时对原始命令做额外 HopLimit 递减后通过 CommandOutputDelegate 向上转发 - 标签聚合更新:
Plugins/CharacterControl/Source/CharacterControl/Private/CommandRouter.cpp:137-143-- OnRegisteredEndpointStateChanged 收到端点状态变更后调用 UpdateEndpointInAggregation 做差分更新 - 自注册防护:
Plugins/CharacterControl/Source/CharacterControl/Private/CommandRouter.cpp:65-69-- RegisterEndpoint 检查端点 GUID 是否等于自身 GUID,防止路由器将自己注册为子端点造成环路