コントローラー、ゲームパッド、ジョイスティック
Godot supports hundreds of controller models out of the box. Controllers are supported on Windows, macOS, Linux, Android, iOS, and HTML5.
ステアリングホイール、ラダーペダル、HOTAS などのより特殊なデバイスはあまりテストされておらず、常に期待どおりに動作するとは限らないことに注意してください。これらのデバイスのフォースフィードバックをオーバーライドする機能もまだ実装されていません。これらのデバイスのいずれかにアクセスできる場合は、ためらわずに GitHub でバグ報告をお願いします。
このガイドでは、次の内容について学習します:
キーボードとコントローラーの両方の入力をサポートする入力ロジックを作成する方法。
コントローラーがキーボード/マウス入力とは異なる動作をさせる方法
Godotのコントローラーに関する問題のトラブルシューティング
ユニバーサル入力のサポート
Godotの入力アクション システムのおかげで、Godotは別個のコード パスを記述することなく、キーボードとコントローラーの両方の入力をサポートできるようになります。スクリプトでキーやコントローラー ボタンをハードコーディングする代わりに、プロジェクト設定で 入力アクション を作成し、指定されたキーとコントローラーの入力を参照します。
入力アクションについては、InputEvent (入力イベント) ページで詳しく説明されています。
注釈
キーボード入力とは異なり、アクション (一人称ゲームで周囲を見回すなど) に対してマウスとコントローラーの両方の入力をサポートするには、これらを個別に処理する必要があるため、異なるコード実装が必要になります。
どの入力メソッドを使用すればよいですか?
アナログに対応した入力を取得するには3つの方法があります。
2つの軸 (ジョイスティックやWASDキーなど) を方向として取得したいときは
Input.get_vector()を使用します。
# `velocity` will be a Vector2 between `Vector2(-1.0, -1.0)` and `Vector2(1.0, 1.0)`.
# This handles deadzone in a correct way for most use cases.
# The resulting deadzone will have a circular shape as it generally should.
var velocity = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
# The line below is similar to `get_vector()`, except that it handles
# the deadzone in a less optimal way. The resulting deadzone will have
# a square-ish shape when it should ideally have a circular shape.
var velocity = Vector2(
Input.get_action_strength("move_right") - Input.get_action_strength("move_left"),
Input.get_action_strength("move_back") - Input.get_action_strength("move_forward")
).limit_length(1.0)
// `velocity` will be a Vector2 between `Vector2(-1.0, -1.0)` and `Vector2(1.0, 1.0)`.
// This handles deadzone in a correct way for most use cases.
// The resulting deadzone will have a circular shape as it generally should.
Vector2 velocity = Input.GetVector("move_left", "move_right", "move_forward", "move_back");
// The line below is similar to `get_vector()`, except that it handles
// the deadzone in a less optimal way. The resulting deadzone will have
// a square-ish shape when it should ideally have a circular shape.
Vector2 velocity = new Vector2(
Input.GetActionStrength("move_right") - Input.GetActionStrength("move_left"),
Input.GetActionStrength("move_back") - Input.GetActionStrength("move_forward")
).LimitLength(1.0);
両方向に移動できる1つの軸 (フライトスティックのスロットルなど) の場合、または別の軸を個別に取得したい場合は
Input.get_axis()を使用します。
# `walk` will be a floating-point number between `-1.0` and `1.0`.
var walk = Input.get_axis("move_left", "move_right")
# The line above is a shorter form of:
var walk = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
// `walk` will be a floating-point number between `-1.0` and `1.0`.
float walk = Input.GetAxis("move_left", "move_right");
// The line above is a shorter form of:
float walk = Input.GetActionStrength("move_right") - Input.GetActionStrength("move_left");
トリガー入力や一方向の入力など、他のタイプのアナログ入力の場合は
Input.get_action_strength()を使用します。
# `strength` will be a floating-point number between `0.0` and `1.0`.
var strength = Input.get_action_strength("accelerate")
// `strength` will be a floating-point number between `0.0` and `1.0`.
float strength = Input.GetActionStrength("accelerate");
コントローラボタン、マウスボタン、キーボードキーなどのデジタル入力 ("押された" または "押されていない") の場合は Input.is_action_pressed() を使用します。
# `jumping` will be a boolean with a value of `true` or `false`.
var jumping = Input.is_action_pressed("jump")
// `jumping` will be a boolean with a value of `true` or `false`.
bool jumping = Input.IsActionPressed("jump");
注釈
前のフレームで入力が「ちょうど」押されたかどうかを知る必要がある場合は Input.is_action_just_pressed() を使用してください。入力が保持されている限り true を返す Input.is_action_pressed() とは異なり、 Input.is_action_just_pressed() はボタンが押された後の1フレームの間だけ true を返します。
振動 (バイブレーション)
振動 (触覚フィードバック とも呼ばれます) は、ゲームの感触を高めるために使用できます。たとえばレーシング ゲームでは、車が現在走行している路面を振動で伝えたり、衝突時に突然の振動を発生させたりできます。
ゲームパッドの振動を開始するには、 Input.start_joy_vibration メソッドを使用します。振動を早期に停止するには、Input.stop_joy_vibration を使用します (開始時に継続時間が指定されていない場合に便利です)。
モバイル デバイスでは Input.vibrate_handheld を使用して、(ゲームパッドとは別に) デバイス自体を振動させることもできます。Androidではプロジェクトをエクスポートする前にAndroidエクスポート プリセットで VIBRATE 権限を有効にする必要があります。
注釈
振動は特定のプレーヤーにとって不快な場合があります。振動を無効にできるようにするか、振動の強度を下げるためのゲーム内スライダーを必ず提供してください。
キーボード/マウスとコントローラー入力の違い
キーボードとマウスの入力処理に慣れている方は、コントローラーが特定の状況下でどのように動作するかに驚くかもしれません。
デッドゾーン
キーボードやマウスとは異なり、コントローラーは アナログ 入力を備えた軸(Axis)を提供します。アナログ入力の利点は、アクションの柔軟性がさらに高まることです。 0.0 と 1.0 の強度のみを提供できるデジタル入力とは異なり、アナログ入力は 0.0 と 1.0 の間の*任意の*強度を提供できます。しかしデッドゾーンがない場合、コントローラーの物理的な構造により、アナログ軸の結果が 0.0 になることが殆どないことが欠点です。代わりに 0.062 などの0に近い値が残ります。この現象は ドリフト として知られており、古いコントローラーや故障したコントローラーではより顕著になる可能性があります。
実際の例としてレーシングゲームを考えてみましょう。アナログ入力のおかげで、車を一方向または別の方向にゆっくりと操縦できます。ただしデッドゾーンがないと、プレイヤーがジョイスティックに触れていなくても、車は自動的にゆっくりと前進してしまいます。これは方向軸の強度が期待したときに 0.0 にならないためです。このとき車が勝手に前進することを望まないため、 デッド ゾーン 値に 0.2 を定義します。これにより強度が 0.2 よりも低い入力がすべて無視されます。理想的なデッド ゾーンは、ジョイスティックのドリフトによって引き起こされる入力を無視できるほど十分に高い値ですが、プレーヤーからの実際の入力を無視できないほど十分に低い値です。
Godot はこの問題に対処するためのデッドゾーンシステムを内蔵しています。デフォルト値は 0.5 ですが、プロジェクト設定の インプットマップ タブでアクションごとに調整できます。 Input.get_vector() では、オプションの 5 番目のパラメータとしてデッドゾーンを指定できます。指定しない場合、ベクトル内のすべてのアクションから平均デッドゾーン値が計算されます。
"エコー"イベント
キーボード入力とは異なり、方向パッドなどのコントローラーボタンを押したままにしても、一定の間隔で繰り返される入力イベント ("エコー"イベントとも呼ばれます) は**生成されません**。これはオペレーティング システムがコントローラー入力の"エコー"イベントをそもそも送信しないためです。
コントローラーのボタンにエコーイベントを送信させたい場合は、コードで InputEvent オブジェクトを生成し、定期的に Input.parse_input_event() を使用してそれらを解析する必要があります。これは Timer ノードの助けを借りて実現できます。
ウインドウフォーカス
キーボード入力とは異なり、コントローラー入力はフォーカスされていないウィンドウを含む、オペレーティングシステム上の すべて のウィンドウで検出されます。
これは サードパーティの分割画面機能 には便利ですが、悪影響を与える可能性もあります。プレイヤーが別のウィンドウと対話しているときに、誤ってコントローラー入力を実行中のプロジェクトに送信してしまう可能性があります。
プロジェクトウィンドウにフォーカスがないときにイベントを無視したい場合は、次のスクリプトで Focus という 自動読み込みスクリプト を作成し、それを使用してすべての入力をチェックする必要があります。
# Focus.gd
extends Node
var focused := true
func _notification(what: int) -> void:
match what:
NOTIFICATION_APPLICATION_FOCUS_OUT:
focused = false
NOTIFICATION_APPLICATION_FOCUS_IN:
focused = true
func input_is_action_pressed(action: StringName) -> bool:
if focused:
return Input.is_action_pressed(action)
return false
func event_is_action_pressed(event: InputEvent, action: StringName) -> bool:
if focused:
return event.is_action_pressed(action)
return false
次に Input.is_action_pressed(action) の代わりに Focus.input_is_action_pressed(action) を使用します。 action は入力アクションの名前です。また event.is_action_pressed(action) の代わりに Focus.event_is_action_pressed(event, action) を使用します。 event はInputEventの参照、 action は入力アクションの名前です。
パワーセーブ防止
キーボードやマウスの入力とは異なり、コントローラーの入力はスリープや省電力モード (一定時間が経過した後に画面をオフにする機能) を**防止しません**。
これに対処するために、Godot はプロジェクトの実行中にデフォルトで省電力モードの防止を有効にします。ゲームパッドでプレイしているときにシステムのディスプレイがオフになっていることに気付いた場合は、プロジェクト設定の 表示 > ウィンドウ > 省エネルギー > 画面を常に点灯 のチェックを確認してください。
Linux では省電力モードを防止するには、エンジンが D-Bus を使用できる必要があります。 Flatpak 内でプロジェクトを実行する場合は、サンドボックスの制限によりデフォルトでこれが不可能になる可能性があるため、D-Bus がインストールされており、到達可能であるかどうかを確認してください。
トラブルシューティング
参考
GitHubで コントローラーサポートに関する既知の問題 のリストを確認できます。
コントローラーが Godot に認識されません。
まずコントローラーが他のアプリケーションによって認識されていることを確認します。 Gamepad Tester Web サイトを使用して、コントローラーが認識するかどうかを確認できます。
Windows では Godot は一度に最大4つのコントローラのみをサポートします。これは Godot が使用する XInput API が一度にサポートするコントローラーが4つまでに制限されているためです。この制限を超える追加のコントローラーは Godot によって無視されます。
My controller works on a given platform, but not on another platform.
Linux
If you're using a self-compiled engine binary, make sure it was compiled with
udev support. This is enabled by default, but it is possible to disable udev
support by specifying udev=no on the SCons command line. If you're using an
engine binary supplied by a Linux distribution, double-check whether it was
compiled with udev support.
Controllers can still work without udev support, but it is less reliable as regular polling must be used to check for controllers being connected or disconnected during gameplay (hotplugging).
HTML5
HTML5 controller support is often less reliable compared to "native" platforms. The quality of controller support tends to vary wildly across browsers. As a result, you may have to instruct your players to use a different browser if they can't get their controller to work.