# UCommandRouterComponent ## 基本信息 - **类型**: UCLASS(BlueprintSpawnableComponent, Blueprintable) - **父类**: UActorComponent, implements ICommandEndpoint - **源文件**: Plugins/CharacterControl/Source/CharacterControl/Public/CommandRouterComponent.h - **模块**: CharacterControl ## 功能概述 UCommandRouter 的 ActorComponent 包装器。创建 InternalRouter 作为默认子对象。通过将所有方法委托给 InternalRouter 来实现 ICommandEndpoint。BeginPlay 调用 AutoRegisterEndpoints,自动发现同 Actor 上的 ICommandEndpoint 同级组件并进行注册,跳过自身和已注册的端点。 ## 设计用意 无需 C++ 即可在 Actor 上挂载命令路由器的桥梁。自动注册实现"本地总线"模式:同一 Actor 上的所有端点组件自动通过此路由器连线。设计者添加组件 → 自动形成本地命令总线。 ## 职责范围 附加到 Actor 的路由器宿主。拥有并委托给 UCommandRouter。自动发现并注册同级端点。不实现路由逻辑(委托给 InternalRouter)。 ## 项目内依赖 | 依赖项 | 关系 | 源文件 | |--------|------|--------| | CommandEndpoint.h | #include | Plugins/CharacterControl/Source/CharacterControl/Public/CommandEndpoint.h | | CommandRouter.h | #include | Plugins/CharacterControl/Source/CharacterControl/Public/CommandRouter.h | ## 对外接口 UCommandRouterComponent 是将 UCommandRouter 挂载到 Actor 上的组件包装器。实现 ICommandEndpoint 接口(全部委托给 InternalRouter),使得挂载此组件的 Actor 本身可作为端点参与上级路由。 - **InternalRouter** (TObjectPtr, EditAnywhere, BlueprintReadOnly, Instanced): 暴露给蓝图的设计时属性,可在组件详情面板中查看/配置路由器的端点状态。作为默认子对象通过 CreateDefaultSubobject 创建 - **实现 ICommandEndpoint**: GetEndpointState、GetStateChangedDelegate、GetCommandOutputDelegate、ReceiveCommand 全部直接委托给 InternalRouter 的同名方法。这意味着对 UCommandRouterComponent 调用 ReceiveCommand 等价于向 InternalRouter 注入命令 UCommandRouterComponent 的核心价值在于 BeginPlay 自动调用 AutoRegisterEndpoints()。不需要手动注册端点 -- 只需将 UEndpointComponent 或 UCommandInputComponent 作为兄弟组件添加到同一 Actor 上,BeginPlay 时自动发现并注册。 ## 使用方法 UCommandRouterComponent 是"即插即用"的本地命令总线: - **创建默认子对象**: `Plugins/CharacterControl/Source/CharacterControl/Private/CommandRouterComponent.cpp:15` -- 构造函数中 `CreateDefaultSubobject("InternalCommandRouter")` - **BeginPlay 自动注册**: `Plugins/CharacterControl/Source/CharacterControl/Private/CommandRouterComponent.cpp:20-24` -- BeginPlay 调用 Super::BeginPlay 后立即执行 AutoRegisterEndpoints - **自动发现**: `Plugins/CharacterControl/Source/CharacterControl/Private/CommandRouterComponent.cpp:27-43` -- 遍历 Owner 的所有 UActorComponent,通过 `Implements()` 检查,跳过自身和已注册(委托已绑定)的端点,其余全部注册 - **端点自注册**: `Plugins/CharacterControl/Source/CharacterControl/Private/EndpointComponent.cpp:22-42` -- UEndpointComponent::BeginPlay 也会主动查找兄弟 UCommandRouterComponent 并注册 - **端点间通信**: 注册后的端点通过路由器互相收发命令。端点 A 调用 OutputCommand -> Router 接收 -> 匹配 -> 投递到端点 B 的 ReceiveCommand ## 用例 - **Actor 本地命令总线**: 在 Character 蓝图上添加 UCommandRouterComponent + UCommandInputComponent + UEndpointComponent(蓝图子类),BeginPlay 时自动完成连线,输入组件产出的命令自动匹配到端点组件 - **自动注册兄弟端点**: `Plugins/CharacterControl/Source/CharacterControl/Private/CommandRouterComponent.cpp:31-42` -- AutoRegisterEndpoints 遍历所有兄弟组件,调用 Implements() 检查接口实现,将未注册的端点通过 InternalRouter->RegisterEndpoint 注册 - **跳过已注册端点**: `Plugins/CharacterControl/Source/CharacterControl/Private/CommandRouterComponent.cpp:40` -- 通过 `GetCommandOutputDelegate().IsBound()` 判断端点是否已注册(委托已绑 = 已注册),避免重复注册 - **以路由器作为端点参与上级路由**: 由于 UCommandRouterComponent 实现 ICommandEndpoint 且全部委托给 InternalRouter,其他 Actor 上的上级路由器可以通过 TScriptInterface 将此组件注册为端点