解决“键位乱写、手柄不响应、移动端没输入”三个痛点,教你用 InputMap 定义动作,一处配置多端通用,并附常见排查清单与代码模板。
为什么要用 InputMap 而不是硬编码按键
- 一套动作名对应多个设备,代码不再关心具体键位:
Input.is_action_pressed("move_left")。 - 便于改键、手柄/键鼠共存、移动端虚拟按钮接入。
- 动作可调节“按下/释放阈值”、可区分连续/一次性事件。
InputMap 核心概念
- 动作 (Action):自定义字符串,如
move_left、jump。 - 事件 (InputEvent):键盘、鼠标、手柄、触摸等输入的具体信号,挂在动作下。
- 查询 API:
is_action_pressed(持续)、is_action_just_pressed(边沿)、get_axis(组合轴)。
5 分钟完成基础配置
- 打开 Project → Project Settings → Input Map。
- 在 Action 栏输入
move_left、move_right、jump、attack,点击 Add。 - 选中
move_left,点击Add Event,按键盘 A 或 左方向键;再点一次添加手柄左摇杆负 X(按摇杆)。 move_right同理添加 D/右键 + 摇杆正 X。jump添加 Space + 手柄 South(如 X/A)。- 点击 Save,动作即存入项目。
推荐默认动作表(可直接粘贴)
- move_left / move_right / move_up / move_down
- jump / dash / attack / interact
- pause / ui_accept / ui_cancel (保留 UI 默认动作)
代码写法模板
var input_dir := Input.get_vector("move_left", "move_right", "move_up", "move_down")
velocity = input_dir * move_speed
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = -jump_speed
if Input.is_action_just_pressed("pause"):
get_tree().paused = !get_tree().paused
get_vector自动归一化并考虑对角线速度;适合 2D 顶视角和 3D 平面。- 改键后代码无需变化,支持键鼠/手柄同写。
手柄支持要点
- 摇杆事件是 InputEventJoypadMotion,添加时要推摇杆;
- 按键是 InputEventJoypadButton,按下对应键即可录入;
- 阈值:摇杆默认为 0.5,可在 Project Settings → Input Devices → Deadzone 调整。
鼠标常用事件
- 左键:添加
Mouse Button→ Left Button。 - 右键/中键滚轮同理。
- 鼠标移动用于相机:
func _input(event):
if event is InputEventMouseMotion:
rotate_y(-event.relative.x * mouse_sens)
触摸与虚拟按钮
- 在移动端导出时,UI 按钮可在脚本中
button.pressed.connect后Input.action_press("jump")触发动作:
func _on_jump_button_pressed():
Input.action_press("jump")
func _on_jump_button_released():
Input.action_release("jump")
- 这样代码仍然只看动作,不关心是触摸还是键盘。
动作强度与组合轴
Input.get_axis("move_left", "move_right")返回 -1 到 1,自动考虑手柄轴强度。- 可自定义阈值:
Input.get_action_strength("attack")返回 0~1,适合模拟扳机。
事件优先级与冲突
- Godot 按输入队列顺序处理,同一帧可能多次触发;如需阻断,使用
event.accept()。 - UI 捕获:Control 节点会优先处理 UI 输入。游戏内监听
_unhandled_input(event)以避免被 UI 吃掉。
常见问题排查清单
- 动作没触发:检查是否在运行时新建了场景但没保存 InputMap;尝试 Project → Reimport。
- 手柄不起作用:确认驱动识别(Editor 顶部工具栏有手柄图标),摇杆 Deadzone 过高也会导致无响应。
- 键位冲突:UI 与游戏共用
ui_accept等默认动作时,按钮获得焦点会触发;解决方案:分离 UI 动作或在_unhandled_input处理中止。 - 触摸延迟:移动端建议禁用鼠标仿真(Project Settings → Input Devices → Pointing → Emulate Mouse From Touch)。
进阶:运行时改键
func remap_jump_to(key: InputEventKey):
InputMap.action_erase_events("jump")
InputMap.action_add_event("jump", key)
ProjectSettings.save() # 如需持久化
- 可配合设置面板,让玩家自定义键位;记得在 UI 中提示“按任意键捕获”。
进阶:输入缓冲与踩空容错
- 结合动作查询可做缓冲:
var jump_buffer := 0.2
var last_jump_press := -1.0
func _process(delta):
if Input.is_action_just_pressed("jump"):
last_jump_press = 0
if last_jump_press >= 0:
last_jump_press += delta
if last_jump_press <= jump_buffer and is_on_floor():
do_jump()
last_jump_press = -1
- 通过动作名实现统一缓冲,键鼠/手柄都适用。
总结复盘
- 记牢动作优先:先在 Input Map 定义“动作名”,代码只读动作,不写具体键。
- 常用 API:
is_action_pressed/just_pressed、get_axis/get_vector、action_press/release(虚拟输入)。 - 排查从三处开始:动作是否存在、事件是否录入、是否被 UI 捕获。做到这些,键鼠/手柄/触摸即可一套代码通吃。

1033

被折叠的 条评论
为什么被折叠?



