キーボードで動くゲームにゲームパッドを足すときは、スティックで歩く、被弾で震える、ポーズ画面をパッドだけで操作する、の3つがそろうと遊べる形になります。Godot では、アクションのデッドゾーン、振動の関数、ボタンのフォーカスで、これを作ります。
何も考えずにパッドを挿すと、スティックから指を離してもキャラがじわじわ歩き続けたり、ポーズを開いてもどのボタンも選べなかったりします。
この記事では、スティックの倒した量を速さに使う書き方、被弾で短く震わせる書き方、ポーズ画面をパッドだけで操作する方法を解説します。
この記事でわかること
- スティックから指を離しても動いてしまう理由と、その直し方
- デッドゾーンを設定する場所と、歩き用とメニュー用の値の違い
- ポーズ画面をパッドだけで操作するために、自分で書く1行
- 振動を1回だけ起こす書き方と、ポーズやパッドを抜いたときの後始末
動作確認環境: Godot 4.7(Windows)
スティックの入力とデッドゾーン
キーボードのキーは、押したか離したかの2択です。スティックは違います。どれだけ倒したかという量が、毎フレーム送られ続けます。

歩きでは、この量をそのまま速さに使います。浅く倒せばゆっくり、深く倒せば速く。キーボードでは作れない動きで、ゲームパッドを挿す価値の半分はここにあります。
問題は 0 のあたりです。使い込んだパッドは、指を離していても 0.05 から 0.15 くらいの値を出し続けることがあります。そのまま速さにすると、 誰も触っていないのにキャラが歩きます。
そこで、ある大きさより小さい量は「倒していない」として捨てます。この捨てる範囲が デッドゾーン です。

設定する場所は1か所です。プロジェクト設定の Input Map で、アクション(move_left のように、キーやスティックの向きにまとめて付けた名前)の行ごとに Deadzone が付いています。登録したイベントの側には、この設定はありません。
新しく作ったアクションは、最初から 0.2 になっています。歩きにはこの値が合います。0.1 まで下げると揺れが通り、0.5 まで上げると、かなり倒すまで歩き出しません。
移動の読み取りは1行です。
var direction := Input.get_vector("move_left", "move_right", "move_up", "move_down")
get_vector() が返すベクトルは、長さが最大で 1 です。斜めに倒しても、真横に倒したときと同じ速さで止まります。左右と上下を別々に読んで足すと、斜めだけ約1.4倍になります。
この関数はデッドゾーンも一緒に見てくれます。引数を省略すると、4つのアクションに設定された値の平均が使われます。
捨てたぶんは、残りを 0 から 1 へ割り直して返します。0.2 を捨てる設定でスティックを半分(0.5)倒すと、返ってくるのは 0.375 です。
メニューの操作とフォーカス
ポーズ画面では、同じスティックの扱いが逆になります。倒した量は自分で読みません。Godot が「次の項目へ1回」に変換したものを受け取ります。
いま枠が付いていて、決定を受け取る相手のことを フォーカス と呼びます。画面のどこに注目しているかの印で、パッドやキーボードで操作するときは、これが動きます。

ui_up や ui_down には、十字キーと左スティックが最初から入っています。これらの Deadzone は 0.5 で、歩き用の 0.2 より鈍くしてあります。指を乗せただけで項目が送られないようにするためです。
決定に使われるのは ui_accept です。こちらには、最初はキーボードのキー(Enter や Space)しか入っていません。プロジェクト設定の Input Map で Show Built-in Actions をオンにすると、ui_accept の行が見えます。行の + から「Joypad Buttons」を開き、「Joypad Button 0 (Bottom Action, Sony Cross, Xbox A, Nintendo B)」を足します。パッドの下のボタンです。ui_cancel に「Joypad Button 1」(右のボタン)を足すと、右のボタンで閉じられるようになります。
自分で書くのは1行だけです。

ポーズ画面を表示した直後に、最初のボタンへ grab_focus() を呼びます。これが無いと、どのボタンもフォーカスを持っていないので、スティックを倒しても枠が出ません。
focus_neighbor という項目もありますが、縦に3つ並べただけなら触らなくてかまいません。空のままにしておくと、Godot が位置から隣を探します。
キーボードと違って、スティックを倒し続けても、項目は1つしか動きません。1つ進むたびにスティックをいったん中央へ戻します。
振動の出し方
被弾したときの手応えは、1行で足ります。
Input.start_joy_vibration(device, 0.3, 0.7, 0.25)
第2引数は細かいモーター、第3引数は重いモーターの強さで、どちらも 0 から 1 です。第4引数は秒数です。被弾なら弱い側を 0.3、強い側を 0.7、長さを 0.25 秒くらいから試します。

長さに 0 を渡すと、すぐには止まりません。Windows では、約1分震え続けてから止まります。シーンを切り替えても残るので、止めたいところで Input.stop_joy_vibration(device) を呼びます。ポーズを開くときに止めておくと、メニューを選んでいるあいだ震え続けることがなくなります。
呼ぶ回数にも注意が要ります。start_joy_vibration() は呼ぶたびに、その時点から指定した長さの振動をやり直します。重なっている間ずっと呼ぶと、いつまでも終わりません。ダメージを1回適用した、その瞬間だけ呼びます。
送り先のデバイス番号(つながったパッドに 0 から振られる番号)は、Input.get_connected_joypads() で今つながっている番号を取って、全部へ送ります。番号は抜き差しで変わるので、0 と決め打ちすると、つながっているのに震えないことがあります。
振動の無いパッドもあります。震えないパッドへ start_joy_vibration() を呼んでも、エラーにはなりません。震えなくても遊べるように作っておけば足ります。
パッドの抜き差し
プレイ中にパッドを抜かれたとき、何を書く必要があるかは、想像より少なめです。
