This commit is contained in:
meishibiezb
2026-06-04 21:37:53 +08:00
parent b0d2a0e2e7
commit 29a3f77908
63 changed files with 4068 additions and 1 deletions

View File

@@ -0,0 +1,63 @@
# 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<ICommandEndpoint>) -> bool**: 注册一个端点。检查 GUID 有效性、重复注册、自注册防护。注册成功后绑定端点的两个委托并执行标签聚合。返回 false 表示注册失败
- **UnregisterEndpoint(const FGuid&) -> bool**: 按 GUID 注销端点。解绑委托、移除标签聚合、从注册表删除
- **UnregisterEndpointByInterface(TScriptInterface<ICommandEndpoint>) -> 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防止路由器将自己注册为子端点造成环路