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,45 @@
# UCommandRouterComponent
## 基本信息
- **类型**: UCLASS(BlueprintSpawnableComponent, Blueprintable)
- **父类**: UActorComponent, implements ICommandEndpoint
- **源文件**: Plugins/CharacterControl/Source/CharacterControl/Public/CommandRouterComponent.h
- **模块**: CharacterControl
## 功能概述
ActorComponent wrapper around UCommandRouter. Creates InternalRouter as default subobject. Implements ICommandEndpoint by delegating all methods to InternalRouter. BeginPlay calls AutoRegisterEndpoints which discovers ICommandEndpoint siblings and registers them, skipping self and already-registered endpoints.
## 设计用意
Bridge putting a command router on an Actor without C++. Auto-registration implements "local bus" pattern: all endpoint components on same actor auto-wire through this router. Designer adds component -> automatic local command bus.
## 职责范围
Actor-attached router host. Owns and delegates to UCommandRouter. Auto-discovers and registers sibling endpoints. Does NOT implement routing logic (delegated to 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> 将此组件注册为端点