使用 InputEvent

它是什么?

InputEvent. 此类型可被设置成包含多种类型的输入事件. 输入事件通过引擎传递, 可在多个位置接收, 具体位置取决于目的. 这里有一个简单的示例,Esc键被触发时关闭您的游戏: GDScript C#

  1. func _unhandled_input(event): if event is InputEventKey: if event.pressed and event.scancode == KEY_ESCAPE: get_tree().quit()
  1. public override void _UnhandledInput(InputEvent @event){ if (@event is InputEventKey eventKey) if (eventKey.Pressed && eventKey.Scancode == (int)KeyList.Escape) GetTree().Quit();}

InputMap 功能更简洁灵活,它允许您定义输入操作并分配不同的键。这样,您可以定义多个键的相同动作,例如键盘ESC键和游戏手柄上的启动按钮。然后,你可以在不更新代码的情况下轻松更改项目设置中的此映射,甚至在上面构建键映射功能,以便您的游戏在运行时更改键值映射! Project > Project Settings > Input Map 下设置您的输入映射, 然后使用以下操作: GDScript C#

  1. func _process(delta): if Input.is_action_pressed("ui_right"): # Move right.
  1. public override void _Process(float delta){ if (Input.IsActionPressed("ui_right")) { // Move right. }}

它的工作原理是什么?

SceneTree 是默认的主循环实现, 所以事件被提交给它.Godot提供了一个获取当前SceneTree对象的函数 : get_tree() . Viewport (场景树的第一个节点)开始查找.Viewport对接收到的输入做了很多事情, 顺序如下:

  1. Node._input() 函数将在任何覆写它的节点中被调用(在没有被 Node.set_process_input() 禁用的情况下 ). 如果任何函数消耗了该输入事件, 它可以调用 SceneTree.set_input_as_handled() , 该事件将不再传播. 这让您可以在GUI响应之前过滤事件. 对于游戏性的输入(如WASD控制移动), Node._unhandled_input() 通常更合适, 因为它允许GUI拦截事件.
  2. Control 将通过虚函数 Control._gui_input() 被调用并发出信号 “gui_input”(此函数可通过继承它的脚本重新实现). 如果控件想 “消耗” 该事件, 它将调用 Control.accept_event() 阻止事件的传播. 用 Control.mouse_filter 属性来控制 Control 是否通过 Control._gui_input() 回调接收鼠标事件的通知, 以及是否进一步传播这些事件.
  3. Node.set_process_unhandled_input() 禁用)。如果任何函数消耗了该事件, 它可以调用 SceneTree.set_input_as_handled() 来设置已经处理了该事件,它就将不再传播。未处理的输入回调是全屏游戏事件的理想选择,因为当GUI处于激活状态时不会收到它们。
  4. 摄像机 启用了 对象拾取 ,就会(从点击的射线方向)往物理世界中投射一条射线。(如果是根视图,则是在 项目设置 中启用。)如果这条射线命中了某个对象,就会调用相关物理对象的 CollisionObject._input_event() 函数(物理实体默认接受这个回调,区域则不会。可以使用 Area 的属性进行设置)。
  5. 最后, 如果事件未被处理, 它将被传递到树的下一个视区中, 否则将被忽略. 将事件发送到场景中的所有侦听节点时, 视区将以反向深度优先顺序执行: 从场景树底部的节点开始, 到根节点结束: GUI事件也在场景树上传播,但由于这些事件针对的是特定的控件,所以只有目标控件节点的第一个父节点才会收到该事件。 根据Godot基于节点的设计, 这使得专门的子节点能够处理和消费特定的事件, 而它们的父级节点, 以及最终的场景根节点, 可以在需要时提供更通用的行为.

    InputEvent剖析

    InputEvent 只是一个基本的内置类型, 它不代表任何东西, 只包含一些基本信息, 如事件ID(每个事件增加), 设备索引等. InputEvent有几种专门的类型, 如下表所述:

    Actions

    InputEvent可能代表也可能不代表预定义的动作. 动作很有用, 因为它们在编写游戏逻辑时抽象输入设备. 这允许:
  • 相同的代码可以在具有不同输入的不同设备上工作(例如,PC上的键盘, 控制台上的Joypad).
  • 输入要在运行时重新配置. 操作 选项卡的 项目设置 菜单中创建操作. InputEvent.is_action(), InputEvent.is_pressed() and InputEvent. Input.parse_input_event() . 通常这样使用它: GDScript C#
    1. var ev = InputEventAction.new()# Set as move_left, pressed.ev.action = "move_left"ev.pressed = true# Feedback.Input.parse_input_event(ev)
    1. var ev = new InputEventAction();// Set as move_left, pressed.ev.SetAction("move_left");ev.SetPressed(true);// Feedback.Input.ParseInputEvent(ev);

    InputMap

    InputMap 单例是在运行时重新分配或创建不同动作的理想选择. 这个单例不被保存(必须手动修改), 其状态从项目设置进行(project.godot). 所以任何这种类型的动态系统, 都需要以程序员认为最合适的方式来存储设置.