输入映射与触发
自动关联目录:输入映射与触发
官方依据:官方 Gameplay Systems → Input 分类;具体条目因分类页 JS 渲染无法枚举,本篇按引擎模块组织。与 GAS 的绑定见 UGameplayAbility。
1. 定位
Enhanced Input 是 UE5 的输入系统:把"按键"与"意图"解耦——按键是 Input Action,如何响应由 Trigger 决定,何时生效由 Input Mapping Context 决定。
一句话定位:旧输入系统是"键 → 函数",Enhanced Input 是"键 → 意图 →(触发条件)→ 处理"。中间多的一层,正是它值钱的地方。
2. 结构:四个概念
| 概念 | 作用 |
|---|---|
| Input Action(IA) | 一个"意图"(跳跃、开火、移动)。带值类型(bool / float / 2D / 3D) |
| Input Mapping Context(IMC) | IA 与物理按键的映射表,可动态添加/移除 |
| Trigger | 决定 IA 何时触发(按下、按住、连点、长按、和弦) |
| Modifier | 对输入值做变换(死区、取反、缩放、转成世界方向) |
物理按键 ──► IMC(映射到 IA)──► Trigger 判定 ──► Modifier 变换 ──► 绑定函数3. 用法
// 组件
UPROPERTY(EditDefaultsOnly)
UInputMappingContext* DefaultMappingContext;
UPROPERTY(EditDefaultsOnly)
UInputAction* FireAction;
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* IC)
{
UEnhancedInputComponent* EIC = CastChecked<UEnhancedInputComponent>(IC);
EIC->BindAction(FireAction, ETriggerEvent::Triggered, this, &AMyCharacter::OnFire);
}
void AMyCharacter::BeginPlay()
{
if (APlayerController* PC = Cast<APlayerController>(GetController()))
{
UEnhancedInputLocalPlayerSubsystem* Sub =
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer());
Sub->AddMappingContext(DefaultMappingContext, 0); // 优先级 0
}
}| 触发事件 | 时机 |
|---|---|
Started | 开始触发 |
Ongoing | 触发条件进行中但未完成 |
Triggered | 每帧(满足条件时) |
Completed | 完成 |
Canceled | 中断 |
4. Trigger 类型
| Trigger | 行为 | 适用 |
|---|---|---|
Down | 按下即触发(默认) | 普通按键 |
Pressed | 只在按下瞬间 | 菜单确认 |
Released | 只在松开瞬间 | 松手动作 |
Hold | 按住达到时长 | 蓄力 |
HoldAndRelease | 按住后松开 | 蓄力释放 |
Tap | 短时间点击 | 轻点区分 |
Chorded Action | 组合键 | Shift+点击 |
Combo | 序列 | 连招输入 |
蓄力技能应该配 Hold / HoldAndRelease,而不是在代码里自己计时——自己计时会脱离输入系统的取消路径。
5. Modifier
| Modifier | 作用 |
|---|---|
Dead Zone | 手柄摇杆死区 |
Negate | 取反 |
Scalar | 缩放 |
Swizzle Input Axis Values | 轴交换(2D→1D 等) |
World Space | 转到世界方向(配合相机) |
FOV Scaling | 按 FOV 缩放灵敏度 |
6. 与 GAS 绑定
| 方式 | 特点 |
|---|---|
老做法:BindAbilityActivationToInputComponent + 输入 ID | 键位与技能耦合,改键要改代码 |
| 推荐:Enhanced Input → 按 Ability 类/标签激活 | 输入与技能解耦,改键位不用改技能 |
// 输入回调里激活 GAS 能力(解耦写法)
void AMyCharacter::OnFire(const FInputActionValue& Value)
{
if (ASC)
{
ASC->TryActivateAbilityByClass(FireAbilityClass); // 或按 Tag
}
}7. 参数
| 设置 | 作用 |
|---|---|
| IMC 优先级 | AddMappingContext(Context, Priority),高优先级先处理 |
bConsumeInput | 是否消费输入(阻止继续传递) |
| Player Mappable Key Settings | 支持玩家改键 |
Input Trigger 的阈值 | Hold 时长、Tap 时间窗等 |
8. 代价与权衡
| 设计 | 收益 | 代价 | 什么时候不该用 |
|---|---|---|---|
| 多一层 IMC | 运行时切换键位方案(步行/驾驶/UI) | 配置比旧系统多 | 极简原型可直接绑键 |
| Trigger 声明式 | 蓄力/连点/组合键不用写计时代码 | 需要理解各种 Trigger 语义 | 简单按下即触发用 Down 即可 |
| Modifier | 死区、灵敏度、坐标转换统一处理 | 链太长难调试 | 只在必要时加 |
| 与 GAS 解耦 | 改键不改技能 | 多一层调用 | 小型项目直接按输入 ID 更快 |
| 多个 IMC 并存 | 场景化切换 | 优先级冲突要注意 | 太多 IMC 会失控 |
9. 踩坑与排查
| 坑 | 现象 | 怎么验证 |
|---|---|---|
忘了 AddMappingContext | 输入完全不响应 | 这是 Enhanced Input 最高频的问题 |
| 绑了 IMC 但优先级被压 | 部分输入无效 | 检查 IMC 优先级与 bConsumeInput |
用了 Triggered 但想要只触发一次 | 每帧都调 | 改 Started / Completed |
| 蓄力自己在代码里计时 | 脱离取消路径 | 用 Hold Trigger |
| 手柄漂移 | 没配 Dead Zone | 加 Dead Zone Modifier |
| 只在本地测试 | 多端/分屏失效 | 用 ULocalPlayer 而非 index 0 |
| 在 Pawn 上绑定但切换角色 | 输入失效 | 绑定应在 Controller 或重绑(见 Pawn/Controller) |
| IMC 没移除 | 切场景后输入冲突 | 切换时 RemoveMappingContext |
10. 排查顺序
1. 完全没反应?→ 是否 AddMappingContext
2. 部分没反应?→ IMC 优先级 / bConsumeInput 被消费
3. 触发次数不对?→ Trigger 事件类型(Started vs Triggered)
4. 值不对?→ Modifier 链
5. 手感不对?→ Trigger 阈值(Hold 时长、Tap 窗口)参考
许可协议:CC BY
作者:Davids
本文链接:https://hustjjd.github.io/55778ed2.html
更新于:2026年10月10日