# UCommandInputComponent ## 基本信息 - **类型**: UCLASS(BlueprintSpawnableComponent, Blueprintable) - **父类**: UEndpointComponent - **源文件**: Plugins/CharacterControl/Source/CharacterControl/Public/CommandInputComponent.h - **模块**: CharacterControl ## 功能概述 将增强输入(Enhanced Input)动作转换为 FCommandPacket 命令。BeginPlay 将 InputMappingContext 添加到本地玩家子系统,然后从 CommandData 绑定所有 InputAction。BuildPacket 将布尔值/一维轴/二维轴/三维轴值转换为 FVector3f。连续命令使用 Triggered(每帧触发),离散命令使用 Started。OnPacketBuilt 虚函数钩子用于检查/修改。默认跳数限制:连续命令为 3,离散命令为 5。 ## 设计用意 UE 增强输入与基于标签的路由之间的桥梁。将游戏逻辑与输入绑定解耦——系统通过标签订阅而非直接绑定。同一输入可基于状态触发不同响应。跳数限制的差异化反映了频率差异。 ## 职责范围 输入到命令的转换。绑定增强输入动作,将值转换为命令数据包,通过委托输出。不负责路由命令。 ## 项目内依赖 | 依赖项 | 关系 | 源文件 | |--------|------|--------| | EndpointComponent.h | #include (parent) | Plugins/CharacterControl/Source/CharacterControl/Public/EndpointComponent.h | | UInputCommandData | forward-declare (header) | Plugins/CharacterControl/Source/CharacterControl/Public/CommandInputComponent.h | | FInputCommand | forward-declare (header) | Plugins/CharacterControl/Source/CharacterControl/Public/CommandInputComponent.h | | InputCommandData.h | #include (in .cpp) | Plugins/CharacterControl/Source/CharacterControl/Public/InputCommandData.h | ## 对外接口 UCommandInputComponent 继承 UEndpointComponent,是 Enhanced Input 到命令路由系统的翻译器。挂载到 APlayerController 上,自动加载 InputMappingContext 并将输入动作绑定为命令。 **配置属性**: - **CommandData** (TObjectPtr, EditAnywhere, BlueprintReadOnly): 指向 UInputCommandData 资产,包含要加载的 InputMappingContext 和 FInputCommand 映射列表 **可重写方法**: - **BuildPacket(const FInputCommand&, const FInputActionInstance&) -> FCommandPacket** (virtual): 根据配置和运行时输入值构建命令包。默认实现:Boolean -> ZeroVector/OneVector, Axis1D -> X, Axis2D -> XY, Axis3D -> XYZ。连续命令 HopLimit=3,离散命令 HopLimit=5。C++ 子类可重写自定义构造逻辑 - **OnPacketBuilt(const FInputCommand&, FCommandPacket&)** (virtual): 钩子函数,在包构建完成、广播之前调用。子类可在此检查、修改或拦截命令包。默认实现为空 **继承自 UEndpointComponent 的接口**: - OnCommandReceived、OnEndpointStateChanged、OnCommandOutput、EndpointState 等全部可用。同时自动注册到兄弟 UCommandRouterComponent ## 使用方法 将 UCommandInputComponent 添加到 PlayerController,配置 CommandData 资产即可: - **BeginPlay 初始化**: `Plugins/CharacterControl/Source/CharacterControl/Private/CommandInputComponent.cpp:16-32` -- 获取 PlayerController,通过 UEnhancedInputLocalPlayerSubsystem 添加 InputMappingContext,调用 BindAllCommands - **EndPlay 清理**: `Plugins/CharacterControl/Source/CharacterControl/Private/CommandInputComponent.cpp:34-39` -- 调用 UnbindAllCommands 移除所有输入绑定,再调用 Super::EndPlay - **BuildPacket**: `Plugins/CharacterControl/Source/CharacterControl/Private/CommandInputComponent.cpp:41-80` -- 根据动作值类型转换输入值,设置 Meta 和载荷字段 - **BindAllCommands**: `Plugins/CharacterControl/Source/CharacterControl/Private/CommandInputComponent.cpp:82-116` -- 遍历 CommandData->InputCommands,使用 BindActionInstanceLambda 绑定。连续命令用 ETriggerEvent::Triggered,离散命令用 Started - **UnbindAllCommands**: `Plugins/CharacterControl/Source/CharacterControl/Private/CommandInputComponent.cpp:118-133` -- 遍历 BindingHandles 逐一 RemoveBindingByHandle 后清空数组 ## 用例 - **完整输入翻译**: `Plugins/CharacterControl/Source/CharacterControl/Private/CommandInputComponent.cpp:96-114` -- BindAllCommands 对每个 FInputCommand 绑定 lambda:BuildPacket 构建包 -> OnPacketBuilt 钩子修改 -> OnCommandOutput.ExecuteIfBound 广播。一条输入动作的完整流水线 - **连续命令(Triggered)**: `Plugins/CharacterControl/Source/CharacterControl/Private/CommandInputComponent.cpp:99-100` -- bIsContinuous 为 true 时绑定 ETriggerEvent::Triggered,每帧触发,用于移动、瞄准等模拟量操作 - **离散命令(Started)**: `Plugins/CharacterControl/Source/CharacterControl/Private/CommandInputComponent.cpp:101` -- bIsContinuous 为 false 时绑定 ETriggerEvent::Started,按一次触发一次,用于跳跃、射击等一次性动作 - **输入值类型转换**: `Plugins/CharacterControl/Source/CharacterControl/Private/CommandInputComponent.cpp:49-67` -- 根据 GetValueType() 将 Boolean/Axis1D/Axis2D/Axis3D 统一转为 FVector3f,实现多类型输入的标准化输出 - **InputMappingContext 加载**: `Plugins/CharacterControl/Source/CharacterControl/Private/CommandInputComponent.cpp:20-29` -- BeginPlay 中通过 UEnhancedInputLocalPlayerSubsystem::AddMappingContext 加载映射上下文