Files
loneseDocument/Plugins/CharacterControl/UCommandRouterComponent.md

4.5 KiB
Raw Blame History

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<UCommandRouter>("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<UCommandEndpoint>() 检查,跳过自身和已注册(委托已绑定)的端点,其余全部注册
  • 端点自注册: 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 将此组件注册为端点