46 lines
4.5 KiB
Markdown
46 lines
4.5 KiB
Markdown
# 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<UCommandRouter>, 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<UCommandEndpoint>() 检查接口实现,将未注册的端点通过 InternalRouter->RegisterEndpoint 注册
|
||
- **跳过已注册端点**: `Plugins/CharacterControl/Source/CharacterControl/Private/CommandRouterComponent.cpp:40` -- 通过 `GetCommandOutputDelegate().IsBound()` 判断端点是否已注册(委托已绑 = 已注册),避免重复注册
|
||
- **以路由器作为端点参与上级路由**: 由于 UCommandRouterComponent 实现 ICommandEndpoint 且全部委托给 InternalRouter,其他 Actor 上的上级路由器可以通过 TScriptInterface<ICommandEndpoint> 将此组件注册为端点
|