Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Using InputEvent

それは何ですか?

通常、入力の管理は、OSやプラットフォームに関係なく複雑です。これを少し簡単にするために、特別な組み込み型、InputEvent が提供されています。このデータ型は、いくつかのタイプの入力イベントを含むように構成できます。入力イベントはエンジンを通過し、目的に応じて複数の場所で受信できます。

以下に簡単な例を示します。エスケープキーが押された場合にゲームを終了します:

func _unhandled_input(event):
    if event is InputEventKey:
        if event.pressed and event.keycode == KEY_ESCAPE:
            get_tree().quit()

However, it is cleaner and more flexible to use the provided InputMap feature, which allows you to define input actions and assign them different keys. This way, you can define multiple keys for the same action (e.g. the keyboard escape key and the start button on a gamepad). You can then more easily change this mapping in the project settings without updating your code, and even build a key mapping feature on top of it to allow your game to change the key mapping at runtime!

You can set up your InputMap under Project > Project Settings > Input Map and then use those actions like this:

func _process(delta):
    if Input.is_action_pressed("ui_right"):
        # Move right.

どのように機能しますか?

Every input event is originated from the user/player (though it's possible to generate an InputEvent and feed them back to the engine, which is useful for gestures). The DisplayServer for each platform will read events from the operating system, then feed them to the root Window.

The window's Viewport does quite a lot of stuff with the received input, in order:

../../_images/input_event_flow.webp
  1. If the Viewport is embedding Windows, the Viewport tries to interpret the event in its capability as a Window-Manager (e.g. for resizing or moving Windows).

  2. Next if an embedded Window is focused, the event is sent to that Window and processed in the Windows Viewport and afterwards treated as handled. If no embedded Window is focused, the event is sent to the nodes of the current viewport in the following order.

  3. First of all, the standard Node._input() function will be called in any node that overrides it (and hasn't disabled input processing with Node.set_process_input()). If any function consumes the event, it can call Viewport.set_input_as_handled(), and the event will not spread any more. This ensures that you can filter all events of interest, even before the GUI. For gameplay input, Node._unhandled_input() is generally a better fit, because it allows the GUI to intercept the events.

  4. Second, it will try to feed the input to the GUI, and see if any control can receive it. If so, the Control will be called via the virtual function Control._gui_input() and the signal "gui_input" will be emitted (this function is re-implementable by script by inheriting from it). If the control wants to "consume" the event, it will call Control.accept_event() and the event will not spread any more. Use the Control.mouse_filter property to control whether a Control is notified of mouse events via Control._gui_input() callback, and whether these events are propagated further.

  5. If so far no one consumed the event, the Node._shortcut_input() callback will be called if overridden (and not disabled with Node.set_process_shortcut_input()). This happens only for InputEventKey, InputEventShortcut and InputEventJoypadButton. If any function consumes the event, it can call Viewport.set_input_as_handled(), and the event will not spread any more. The shortcut input callback is ideal for treating events that are intended as shortcuts.

  6. If so far no one consumed the event, the Node._unhandled_key_input() callback will be called if overridden (and not disabled with Node.set_process_unhandled_key_input()). This happens only if the event is a InputEventKey. If any function consumes the event, it can call Viewport.set_input_as_handled(), and the event will not spread any more. The unhandled key input callback is ideal for key events.

  7. If so far no one consumed the event, the Node._unhandled_input() callback will be called if overridden (and not disabled with Node.set_process_unhandled_input()). If any function consumes the event, it can call Viewport.set_input_as_handled(), and the event will not spread any more. The unhandled input callback is ideal for full-screen gameplay events, so they are not received when a GUI is active.

  8. If no one wanted the event so far, and Object Picking is turned on, the event is used for object picking. For the root viewport, this can also be enabled in Project Settings. In the case of a 3D scene if a Camera3D is assigned to the Viewport, a ray to the physics world (in the ray direction from the click) will be cast. If this ray hits an object, it will call the CollisionObject3D._input_event() function in the relevant physics object (bodies receive this callback by default, but areas do not. This can be configured through Area3D properties). In the case of a 2D scene, conceptually the same happens with CollisionObject2D._input_event().

When sending events to its child and descendant nodes, the viewport will do so, as depicted in the following graphic, in a reverse depth-first order, starting with the node at the bottom of the scene tree, and ending at the root node. Excluded from this process are Windows and SubViewports.

../../_images/input_event_scene_flow.png

This order doesn't apply to Control._gui_input(), which uses a different method based on event location or focused Control.

Since Viewports don't send events to other SubViewports, one of the following methods has to be used:

  1. Use a SubViewportContainer, which automatically sends events to its child SubViewports after Node._input() or Control._gui_input().

  2. Implement event propagation based on the individual requirements.

GUIイベントもシーンツリーを上に移動しますが、これらのイベントは特定のコントロールを対象とするため、ターゲットコントロールノードの直接の先祖のみがイベントを受け取ります。

In accordance with Godot's node-based design, this enables specialized child nodes to handle and consume particular events, while their ancestors, and ultimately the scene root, can provide more generalized behavior if needed.

InputEventの構造

InputEvent は単なる基本組み込み型であり、何も表さず、イベントID(イベントごとに増加する)、デバイスインデックスなどの基本情報のみを含みます。

There are several specialized types of InputEvent, described in the table below:

イベント

説明

InputEvent

空の入力イベント。

InputEventKey

Contains a keycode and Unicode value, as well as modifiers.

InputEventMouseButton

ボタン、モディファイヤなどのクリック情報が含まれます。

InputEventMouseMotion

Contains motion information, such as relative and absolute positions and speed.

InputEventJoypadMotion

ジョイスティック/ジョイパッドのアナログ軸情報が含まれています。

InputEventJoypadButton

ジョイスティック/ジョイパッドのボタン情報が含まれます。

InputEventScreenTouch

マルチタッチのプレス/リリース情報が含まれています。(モバイルデバイスでのみ使用可能)

InputEventScreenDrag

マルチタッチドラッグ情報が含まれています。(モバイルデバイスでのみ使用可能)

InputEventMagnifyGesture

Contains a position, a factor as well as modifiers.

InputEventPanGesture

Contains a position, a delta as well as modifiers.

InputEventMIDI

Contains MIDI-related information.

InputEventShortcut

Contains a shortcut.

InputEventAction

汎用アクションが含まれています。これらのイベントは多くの場合、フィードバックとしてプログラマーによって生成されます。(詳細は以下)

アクション

Actions are a grouping of zero or more InputEvents into a commonly understood title (for example, the default "ui_left" action grouping both joypad-left input and a keyboard's left arrow key). They are not required to represent an InputEvent but are useful because they abstract various inputs when programming the game logic.

This allows for:

  • 入力が異なるさまざまなデバイス(PCのキーボード、コンソールのJoypadなど)で動作する同じコード。

  • 実行時に再構成される入力。

  • Actions to be triggered programmatically at run-time.

Actions can be created from the Project Settings menu in the Input Map tab and assigned input events.

すべてのイベントには、メソッド InputEvent.is_action()InputEvent.is_pressed() および InputEvent があります。

あるいは、ゲームコードからのアクションをゲームに返すことが望ましい場合があります(この良い例は、ジェスチャの検出です)。Inputシングルトンには、次のメソッドがあります: Input.parse_input_event()。通常は次のように使用します:

var ev = InputEventAction.new()
# Set as ui_left, pressed.
ev.action = "ui_left"
ev.pressed = true
# Feedback.
Input.parse_input_event(ev)

入力マップ

多くの場合、コードからの入力をカスタマイズして再マッピングすることが望まれます。ワークフロー全体がアクションに依存する場合、InputMap シングルトンは、実行時に異なるアクションを再割り当てまたは作成するのに理想的です。このシングルトンは保存されず(手動で変更する必要があります)、そのステートはプロジェクト設定(project.godot)から実行されます。したがって、このタイプの動的システムは、プログラマーが最適と考える方法で設定を保存する必要があります。