UE5.8 Enhanced Input 专题系列

UE5.8 Enhanced Input 专题(五):C++/蓝图绑定与输入栈

讲清 EnhancedInputComponent 的 BindAction、BindActionValue、Lambda、动态绑定、输入组件优先级、消费输入、清理绑定和 Actor/World Subsystem 场景。

总览

UEnhancedInputComponent 是 Action 事件真正派发到 gameplay 的地方。它不是 Mapping Context;Mapping Context 负责“哪个键触发哪个 Action”,Input Component 负责“Action 触发时调用哪个函数”。

UE5.8 Enhanced Input 专题(五):C++/蓝图绑定与输入栈 配图
Action 事件最终进入 EnhancedInputComponent,输入组件栈决定谁先收到。

BindAction 的几种写法

无参数函数适合跳跃这类动作:

EIC->BindAction(JumpAction, ETriggerEvent::Started, this, &ACharacter::Jump);

带值函数适合移动和视角:

EIC->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyCharacter::Move);

带 Instance 函数适合蓄力、调试和需要事件信息的动作:

EIC->BindAction(ChargeAction, ETriggerEvent::Ongoing, this, &AMyCharacter::UpdateCharge);

Lambda 适合短生命周期工具或测试,但生产项目别把复杂 gameplay 都塞进 Lambda:

EIC->BindActionValueLambda(DebugAction, ETriggerEvent::Triggered,
    [this](const FInputActionValue& Value)
    {
        ToggleDebugOverlay(Value.Get<bool>());
    });

BindActionValue

如果你不想每次触发都回调,只想在 Tick 或别的系统里读当前值,可以用 BindActionValue,然后 GetBoundActionValue

EIC->BindActionValue(MoveAction);
const FVector2D Axis = EIC->GetBoundActionValue(MoveAction).Get<FVector2D>();

适合持续读取相机输入、自由飞行、编辑器工具;普通角色移动用回调更直观。

输入组件栈

UE 的 PlayerController 会维护 InputComponent Stack。源码测试 InputStackOrder 创建了三个 UEnhancedInputComponent,优先级 10、5、-1,验证高优先级先收到同一个 Action。另一个测试 InputStackConsumption 给高优先级绑定调用 SetShouldConsume(true),低优先级绑定就不会触发。

这意味着你可以让“交互中的小游戏面板”临时 Push 一个高优先级 InputComponent,结束时 Pop 掉,而不是在角色输入里写一堆 if (bInPanel)

消费输入

UInputActionbConsumeInput,绑定对象本身也可以设置 consume。需要注意,源码注释说 EnhancedInputComponent 的绑定不会像旧系统那样天然消费所有输入;更推荐用 Mapping Context 优先级表达“高层输入覆盖低层输入”。

FEnhancedInputActionEventBinding& Binding =
    EIC->BindActionValueLambda(ConfirmAction, ETriggerEvent::Triggered, OnConfirm);
Binding.SetShouldConsume(true);

清理绑定

动态创建组件或临时模式时,要在退出时清理:

EIC->ClearBindingsForObject(this);
// 或者保存 binding handle 后 RemoveBindingByHandle

UEnhancedInputComponent 还提供 ClearActionEventBindingsClearActionValueBindingsClearDebugKeyBindingsClearActionBindings

Actor 没有 PlayerController 怎么办

UE5.8 有 UEnhancedInputWorldSubsystem,源码注释说它用于没有 owning PlayerController 的 Actor 输入代理,例如某个门在特定按键组合下响应。它是 Experimental,并且 Actor 必须 Enable Input。普通角色、Pawn、玩家控制的交互都优先用 LocalPlayerSubsystem。

使用案例:交互面板临时接管输入

玩家打开一个撬锁面板:保留角色的 Look,但面板要接管 A/D、Space、Esc。做法是加 IMC_Lockpick 高优先级,再 Push 一个面板 InputComponent 绑定 Confirm/Cancel/Rotate。面板关闭时 Remove Context、Pop 或 Clear 绑定。不要在角色 Move 回调里判断当前是否撬锁。

常见坑

  • 绑定在 Actor Component 里,但组件销毁后没清理绑定,回调指向失效对象。
  • 多个组件都绑同一个 Action,忘了谁优先级高。
  • 想用 InputComponent 消费解决所有冲突,但 Mapping Context 优先级没有设计。
  • 在服务器专用环境执行本地输入绑定,LocalPlayer 不存在。
  • 用旧 BindAxis/BindAction 混在 Enhanced Input 里,源码默认删除了 legacy binding helper,除非定义 ENHANCED_INPUT_ALLOW_LEGACY_BINDING

源码依据

EnhancedInputComponent.h 暴露多组 BindActionBindActionValue、Lambda、清理和移除 API。InputBindingTest.cpp 验证了 InputComponent 优先级顺序和绑定消费。UEnhancedInputWorldSubsystem 注释说明它服务于没有 owning PlayerController 的 Actor 输入场景,并标记 Experimental。

源码路径索引

  • EnhancedInput/Public/EnhancedInputComponent.h
  • EnhancedInput/Source/InputEditor/Private/Tests/InputBindingTest.cpp
  • EnhancedInput/Public/EnhancedInputSubsystems.h