GODOT的input相关用法

1. _input_event 方法

  • 所属节点类型Area2DCollisionObject2D(如 Sprite2DRigidBody2D)等具有碰撞检测能力的节点。

  • 触发条件

    • 当输入事件(如鼠标点击、触摸)发生在该节点的 碰撞形状(CollisionShape2D)范围内 时触发。
    • 必须满足以下条件:
      1. 节点启用了 input_ray_pickable(或 input_pickable,Godot 4.0+)。
      2. 输入事件未被其他节点“吞噬”(例如没有子节点拦截事件)。
  • 典型用途

    • 检测玩家点击/触摸游戏中的特定物体(如按钮、宝箱、传送门)。
    • 需要基于物理位置触发交互时使用。
  • 示例代码

    1
    2
    3
    4
    # 在 Area2D 节点中
    func _input_event(viewport: Viewport, event: InputEvent, shape_idx: int) -> void:
    if event is InputEventMouseButton and event.pressed:
    print("点击了此区域!")

2. _input 方法

  • 所属节点类型:任意节点(如 NodeCharacterBody2D)。

  • 触发条件

    • 全局输入事件,无论事件发生在屏幕何处,都会触发。
    • 无论玩家是否点击了某个物体,只要输入动作发生(如按下键盘、鼠标移动),就会调用。
  • 典型用途

    • 处理全局按键(如 ESC 打开菜单、WASD 控制角色移动)。
    • 需要响应与场景位置无关的输入时使用。
  • 示例代码

    1
    2
    3
    4
    # 在任意节点中
    func _input(event: InputEvent) -> void:
    if event.is_action_pressed("jump"):
    print("玩家按下了跳跃键!")

3. _unhandled_input 方法

  • 所属节点类型:任意节点。

  • 触发条件

    • 仅当输入事件未被其他节点处理(即未被 _input_input_event 中的逻辑标记为 handled)时触发。
    • 通常用于处理未被其他逻辑“拦截”的事件。
  • 典型用途

    • 实现全局的后备输入处理(例如未聚焦到 UI 时的按键响应)。
  • 示例代码

    1
    2
    3
    func _unhandled_input(event: InputEvent) -> void:
    if event.is_action_pressed("pause"):
    print("暂停游戏(未被其他逻辑处理)")

4. _unhandled_key_input 方法

  • 所属节点类型Control 节点(如 UI 元素)。

  • 触发条件

    • 专门处理未被 UI 元素处理的键盘输入事件。
    • 当焦点不在任何 UI 控件上时触发。
  • 典型用途

    • 在 UI 系统中处理全局快捷键(如 F1 打开帮助)。
  • 示例代码

    1
    2
    3
    4
    # 在 Control 节点中
    func _unhandled_key_input(event: InputEvent) -> void:
    if event.is_action_pressed("fullscreen"):
    toggle_fullscreen()

关键差异对比表

方法触发条件适用节点类型典型用途
_input_event输入发生在节点的碰撞范围内Area2D 等物理节点物体点击交互(如按钮、传送门)
_input全局输入事件任意节点全局按键控制(如 WASD、ESC)
_unhandled_input未被其他逻辑处理的输入事件任意节点后备输入处理
_unhandled_key_input未被 UI 处理的键盘事件Control 节点UI 系统的全局快捷键

执行顺序与优先级

  1. _input_event 优先触发(当输入发生在碰撞范围内)。
  2. _input 全局处理。
  3. _unhandled_input 最后触发(仅处理未被标记为 handled 的事件)。
  4. _unhandled_key_input 仅针对 UI 的键盘输入。

常见错误与解决方案

  1. _input_event 未被触发
    • 检查 input_ray_pickable 是否启用。
    • 确保碰撞层(Collision Layer)和玩家的碰撞掩码(Collision Mask)重叠。
  2. 输入事件被重复处理
    • _input 中调用 get_viewport().set_input_as_handled() 标记事件为已处理,避免传播到其他方法。
  3. UI 和游戏输入的冲突
    • 使用 _unhandled_key_input 处理游戏快捷键,确保 UI 焦点逻辑正确。

代码示例:综合使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 玩家角色移动(全局输入)
func _input(event: InputEvent) -> void:
if event.is_action_pressed("move_left"):
velocity.x = -speed

# 点击宝箱打开(区域输入)
func _input_event(viewport: Viewport, event: InputEvent, shape_idx: int) -> void:
if event.is_action_pressed("interact"):
open_chest()

# 全局暂停(未被处理的输入)
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("pause"):
pause_game()