mcpField
I
input-handling

input-handling

github.com/jame581開発889183 回インストール4 日前に更新
リポジトリ

input-handling について

Godot 4.3以降のゲーム開発向けに、GDScriptとC#の例で入力処理を解説するスキルです。イベント伝播やポーリングに加え、マウス、コントローラー、タッチ、実行時の再割り当てを扱います。

主な機能

  1. 01入力イベントとポーリング
  2. 02Input Mapのアクション設計
  3. 03マウスとゲームパッド入力
  4. 04タッチとマルチタッチ
  5. 05実行時のアクション再割り当て
  6. 06入力伝播と一時停止時の処理

活用シーン

  1. 01ゲームやUI入力に使うコールバックの選択
  2. 02キーボード、マウス、ゲームパッド操作の追加
  3. 03タッチ入力の実装とデスクトップでのテスト
  4. 04カスタムキー割り当ての保存

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jame581/godotprompter --skill input-handling

インストール後、Claude Code で/input-handlingを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
action-rebinding.md
event-propagation.md
gamepad.md
input-buffering.md
mouse.md
touch.md

詳細

Godot 4.3 以降の入力処理

すべての例は、非推奨 API を使わずに Godot 4.3 以降を対象としています。まず GDScript、次に C# を示します。

関連スキル: 入力で動く移動については player-controller、UI の入力フォーカスとナビゲーションについては godot-ui、カスタムキー割り当ての保存については save-load、タッチ入力とデスクトップ入力の適応については responsive-ui、XR コントローラーとハンドトラッキング入力については xr-development、モバイルセンサーとアプリのライフサイクルについては mobile-development を参照してください。


1. 基本概念

入力の流れ
Hardware Event (key, mouse, gamepad)
    ↓
Engine converts to InputEvent
    ↓
_input()              ← raw input, runs first
    ↓
UI Control nodes      ← _gui_input: buttons, sliders consume events
    ↓
_shortcut_input()     ← for global shortcuts
    ↓
_unhandled_key_input() ← unhandled key-only events
    ↓
_unhandled_input()    ← game input (movement, actions)
入力を処理する場所
メソッド用途実行タイミング
_input()カメラ操作、グローバルホットキー最初 — すべての処理より前
_shortcut_input()グローバルショートカット(一時停止、スクリーンショット)UI の後、未処理イベントの前
_unhandled_key_input()UI が処理しなかったキーイベントのみUI の後、キーのみ
_unhandled_input()ゲームプレイアクション(ジャンプ、攻撃、インタラクト)最後 — UI の処理後
_physics_process() 内の Input.is_action_pressed()継続的な移動該当なし — イベント駆動ではなく、ポーリング

経験則: 1 回限りのゲームアクション(ジャンプ、攻撃)には _unhandled_input() を使います。継続的な移動には、_physics_process() 内で Input をポーリングします。UI が入力を処理する前に入力が必要な場合(例:マウス操作)に限り、_input() を使います。

InputEvent の階層
InputEvent
├── InputEventFromWindow
│   ├── InputEventWithModifiers
│   │   ├── InputEventKey            ← keyboard
│   │   ├── InputEventMouse
│   │   │   ├── InputEventMouseButton ← mouse clicks
│   │   │   └── InputEventMouseMotion ← mouse movement
│   │   └── InputEventGesture        ← Magnify / Pan gestures
│   ├── InputEventScreenTouch        ← touchscreen tap
│   └── InputEventScreenDrag         ← touchscreen drag
├── InputEventJoypadButton     ← gamepad buttons
├── InputEventJoypadMotion     ← gamepad sticks/triggers
├── InputEventAction           ← synthetic action events
├── InputEventMIDI             ← MIDI devices
└── InputEventShortcut

2. Input Map の設定

キーコードを直接チェックする代わりに、Project > Project Settings > Input Map でアクションを定義します。これにより、ゲームロジックを特定のキーから切り離し、キー割り当ての変更が可能になります。

プロジェクトのデフォルトアクション

Godot には ui_accept、ui_cancel、ui_left、ui_right、ui_up、ui_down などの ui_* アクションが用意されています。これらは、UI コントロールでキーボードナビゲーションに使われます。ゲームプレイに使用することもできますが、競合を避けるため、カスタムアクションを作成することをおすすめします。

コードでアクションを追加する

InputMap.add_action() と InputMap.action_add_event() を使うと、実行時にアクションを作成できます。通常はオートロードの _ready() で、InputMap.has_action() による確認を挟んで作成します。アクションはエディターの Input Map で定義し、動的に生成するキー割り当てや MOD のサポートが必要な場合に限り、コードで追加してください。

GDScript と C# のコード例については、references/action-rebinding.md を参照してください。

推奨するアクション名

キー名ではなく、内容がわかるゲーム固有の名前を使います。

良い例悪い例理由
move_leftpress_a物理キーから切り離せます
attackleft_clickマウスとゲームパッドの両方で動作します
interactpress_eロジックを変更せずにキー割り当てを変更できます
sprinthold_shift入力デバイスに依存しません
pausepress_escapeゲームパッドの Start ボタンにも割り当てられます

3. 入力の読み取り — イベントとポーリング

イベント駆動(1 回限りのアクション)

ジャンプ、攻撃、インタラクト、一時停止など、1 回限りのアクションには _unhandled_input() を使います。

GDScript
func _unhandled_input(event: InputEvent) -> void:
    if event.is_action_pressed("jump"):
        _jump()
        get_viewport().set_input_as_handled()  # prevent further propagation

    if event.is_action_pressed("interact"):
        _interact()

    if event.is_action_pressed("pause"):
        get_tree().paused = not get_tree().paused
        get_viewport().set_input_as_handled()
C#
public override void _UnhandledInput(InputEvent @event)
{
    if (@event.IsActionPressed("jump"))
    {
        Jump();
        GetViewport().SetInputAsHandled();
    }

    if (@event.IsActionPressed("interact"))
        Interact();

    if (@event.IsActionPressed("pause"))
    {
        GetTree().Paused = !GetTree().Paused;
        GetViewport().SetInputAsHandled();
    }
}
ポーリング(継続的な入力)

押し続けるボタンやアナログ軸には、_physics_process() 内で Input シングルトンを使います。

GDScript
func _physics_process(delta: float) -> void:
    # Movement vector from 4 directional actions
    var direction := Input.get_vector("move_left", "move_right", "move_up", "move_down")
    velocity = direction * speed

    # Check if a button is held
    if Input.is_action_pressed("sprint"):
        velocity *= 1.5

    move_and_slide()
C#
public override void _PhysicsProcess(double delta)
{
    Vector2 direction = Input.GetVector("move_left", "move_right", "move_up", "move_down");
    Velocity = direction * Speed;

    if (Input.IsActionPressed("sprint"))
        Velocity *= 1.5f;

    MoveAndSlide();
}
主要な入力メソッド
メソッド戻り値用途
Input.is_action_pressed()bool押し続けるボタン(ダッシュ、しゃがむ、射撃)
Input.is_action_just_pressed()bool1回だけ実行するトリガー(ジャンプ、インタラクト)
Input.is_action_just_released()bool離したときのトリガー(ジャンプの可変カット)
Input.get_action_strength()floatアナログ入力の強度(0.0–1.0)
Input.get_axis()float単一軸(-1.0~1.0)
Input.get_vector()Vector22D 方向。長さは 1 に制限されます
event.is_action_pressed()bool_unhandled_input コールバック内で確認
event.is_action_released()bool_unhandled_input コールバック内で確認

_physics_process() 内の Input.is_action_just_pressed() は、キーがすでに離されていても、次の物理ティックで押されたことを報告します。ティックレートが低くてもタップが取りこぼされることはありませんが、1 ティック内に複数回押しても 1 回としてカウントされます。押すたびに処理する必要がある場合は、_unhandled_input() で検知してフラグを設定してください。

入力バッファリング

離散的なアクションをバッファリングすると、実行可能になる直前に行った入力(着地直前のジャンプなど)も有効になります。_unhandled_input() でアクションを検知し、短いタイマー(通常は 0.1 秒)とともにフラグを設定して、_physics_process() 内でそのフラグを消費してください。

GDScript と C# によるジャンプバッファの完全な実装については、references/input-buffering.md を参照してください。


4. マウス入力

カメラ操作には InputEventMouseMotion.relative(Input.MOUSE_MODE_CAPTURED 使用時)、クリックには InputEventMouseButton を使用します。マウスモードは VISIBLE、HIDDEN、CAPTURED、CONFINED です。Input.set_custom_mouse_cursor(texture, shape, hotspot) でカスタムカーソルを設定できます。

感度と反転切り替えを備えたカメラ操作、マウスモードの切り替え、ボタンイベント、形状のバリエーションを備えたカスタムカーソルなど、GDScript と C# の完全な手順については、references/mouse.md を参照してください。


5. コントローラー/ゲームパッドのサポート

実行時の検出には Input.get_connected_joypads()、ホットプラグには Input.joy_connection_changed シグナルを使用します。移植性を高めるには、ジョイパッドのボタンイベントを使った Input Map アクションを使用してください。アナログスティックでは、Input.get_vector("left", "right", "up", "down", deadzone) が、長さを制限した Vector2 を返します。デッドゾーンは組み込みです。

コントローラーの検出、デッドゾーンを考慮したアナログ入力の読み取り、start_joy_vibration による振動、モーションセンサー、UI プロンプトの切り替えに使用する最後の入力デバイスの検出など、GDScript と C# の手順については、references/gamepad.md を参照してください。

Godot 4.7 以降: ジョイパッドのモーションセンサー — Input.get_joy_accelerometer(device)/get_joy_gyroscope(device)(どちらも Vector3)は、has_joy_motion_sensors() で利用可能か確認し、set_joy_motion_sensors_enabled() で有効にします。手順は references/gamepad.md を参照してください。振動の状態を照会できるようになりました — Input.has_joy_vibration(device) に加え、get_joy_vibration_strength/duration/remaining_duration() を使用できます。JoyButton に JOY_BUTTON_MISC2(21)から JOY_BUTTON_MISC6(25)が追加されます(C#:JoyButton.Misc2…)。新しいプロジェクト設定 input_devices/joypads/ignore_joypad_on_unfocused_application(デフォルトは false)を有効にすると、アプリのフォーカスが外れている間、ジョイパッド入力(モーションセンサーを含む)と LED の変更が無視され、振動が停止します。


6. タッチ入力

タップ/リリースには InputEventScreenTouch、指でのドラッグには InputEventScreenDrag を使用します。マルチタッチは event.index で追跡します。デスクトップでテストするには、プロジェクト設定 → 入力デバイス → ポインティング → マウスからタッチをエミュレートを有効にします。タッチスクリーンで UI が動作するように、タッチからマウスをエミュレートはデフォルトで有効です。

GDScript と C# によるタッチイベントの手順、および画面上のスティック VirtualJoystick(Godot 4.7 以降)については、references/touch.md を参照してください。


7. 実行時のアクション再割り当て

手順は3つです。(1)「再割り当て」モード中に _input を使ってユーザーが選択したキーを取得します。(2)InputMap.action_erase_events(action) を呼び出した後、InputMap.action_add_event(action, new_event) を呼び出します。(3)ConfigFile を使って保存し、起動時に読み込みます。

ConfigFile の保存/読み込みや、一般的な「キーを押してください」という入力取得 UI を含む、GDScript と C# による再割り当ての一連の流れについては、references/action-rebinding.md をご覧ください。


8. 入力の消費と伝播

入力はシーンツリーの逆順(Scene ドックで一番下にあるノードが最初で、ルートが最後)に伝播します。イベントを消費した後に get_viewport().set_input_as_handled() を呼び出すと、ほかのノードへの伝播を止められます。一時停止中は、process_mode が PROCESS_MODE_ALWAYS または PROCESS_MODE_WHEN_PAUSED のノードだけが入力を受け取ります。

伝播の停止、ノードの処理順序、一時停止中の入力受信についての GDScript と C# の手順は、references/event-propagation.md をご覧ください。


9. よくある問題

症状原因解決方法
アクションが認識されないInput Map にアクション名が定義されていないProject > Project Settings > Input Map でアクションを追加します
短時間に連続して押しても1回としてカウントされる_physics_process で is_action_just_pressed() をポーリングしているため、複数の押下が同じティックにまとめられる離散的なアクションは _unhandled_input() で取得します
UI を開いても入力が反応する_unhandled_input() ではなく _input() を使っているUI が先にイベントを消費するよう、_unhandled_input() に切り替えます
メニューの上からマウスルックが反応するモードを確認せずに _input() でマウスの動きを処理しているif Input.mouse_mode == Input.MOUSE_MODE_CAPTURED で処理を制御します
ゲームパッドのスティックがドリフトするデッドゾーンが低すぎる、または設定されていないInput Map でアクションごとにデッドゾーンを設定します(0.2 が適切な初期値です)
コントローラーが検出されないゲーム開始前に接続されていないjoy_connection_changed シグナルに接続し、ホットプラグを処理します
キーの再割り当てで修飾キーが取得されるShift/Ctrl/Alt 単独の入力を除外していないキーコードが修飾キーであるイベントをスキップします
デスクトップでタッチ入力が機能しない「Emulate Touch From Mouse」が無効になっているProject Settings > Input Devices > Pointing で有効にします
一時停止中にポーズメニューが入力を無視するノードの process_mode が INHERIT(親とともに一時停止)になっているポーズメニューを PROCESS_MODE_ALWAYS に設定します
1回押すとアクションが2回実行される同じアクションを _input と _unhandled_input の両方で確認しているアクションごとにコールバックを1つ選びます

⚠️ Godot 4.7 で変更されました: マウスとキーボードのデバイス ID が 0 から InputEvent.DEVICE_ID_MOUSE(32)および InputEvent.DEVICE_ID_KEYBOARD(16)に変更されました。これは、一部のジョイパッドがデバイス ID として 0 を使用するためです。キーボード/マウス入力を検出するために event.device == 0 を確認するコードは、気付かないうちに動作しなくなります。定数と比較するか、イベントの型(代わりに event is InputEventKey)を確認してください。4.7 移行ガイドをご覧ください。


10. 実装チェックリスト

  • すべてのゲームプレイ操作が Input Map で定義されています。ゲームロジックに生のキーコードは使用しません
  • 離散的な操作(ジャンプ、攻撃)には _physics_process() でのポーリングではなく、_unhandled_input() を使用します
  • 継続的な入力(移動、スプリント)には _physics_process() 内で Input.get_vector() / Input.is_action_pressed() を使用します
  • メニュー表示中に視点が回転しないよう、マウス視点操作では Input.mouse_mode == MOUSE_MODE_CAPTURED を条件にします
  • コントローラーに対応するため、各 Input Map アクションにキーボードとゲームパッドの両方の割り当てがあります
  • ゲームパッドのデッドゾーンは Input Map でアクションごとに設定します(新しいアクションの場合、4.3 では 0.5、4.4 以降では 0.2)
  • ポーズメニューのノードは process_mode = PROCESS_MODE_ALWAYS に設定され、ポーズ中も入力を受け取ります
  • 伝播させないイベントを消費した後に get_viewport().set_input_as_handled() を呼び出します
  • キーボードとゲームパッドの UI プロンプトを切り替えて表示する場合は、入力デバイスの検出機能があります
  • キー割り当ての変更は、ゲーム起動時に user:// から読み込まれ、そこに保存されます

コメント