ボタンを押したらジャンプする。押している間だけ右へ走る。離した瞬間にチャージ攻撃を撃つ。
どれも「入力を見る」処理ですが、必要な判定タイミングは違います。ここを混ぜると、ジャンプボタンを押しっぱなしにしただけで着地後にまた跳ぶ、決定ボタンを長押ししてメニューが一気に進む、チャージ攻撃が押した瞬間に発射される、といった違和感につながります。

この記事では、Godotでよく使う3つの入力判定を、ゲームの実装例に結びつけて整理します。
この記事でわかること
is_action_pressed()、is_action_just_pressed()、is_action_just_released()の違い- 移動、ジャンプ、可変ジャンプ、チャージ攻撃での使い分け
_physics_process()と_unhandled_input()の使い分け- 入力処理で起きやすい失敗と、その避け方
3つの入力判定をタイムラインで理解する
Godotの Input.is_action_*() 系は、InputMapに登録したアクション名を使って入力状態を調べます。
| メソッド | trueになるタイミング | 使う場面 |
|---|---|---|
Input.is_action_just_pressed("jump") | 押された瞬間だけ | ジャンプ、攻撃開始、決定、メニューを開く |
Input.is_action_pressed("move_right") | 押されている間ずっと | 移動、長押し、チャージ、連射 |
Input.is_action_just_released("jump") | 離された瞬間だけ | 可変ジャンプ、チャージ解放、ドラッグ終了 |
覚え方はシンプルです。
- just_pressed: 押した瞬間の1回
- pressed: 押している間ずっと
- just_released: 離した瞬間の1回
たとえば、ジャンプ開始は「押した瞬間」だけで十分です。押している間ずっとジャンプ処理を実行すると、着地した瞬間にまた跳ぶような挙動になります。
一方、左右移動は「押している間ずっと」速度を与える必要があります。移動に just_pressed を使うと、キーを押した最初の瞬間だけしか反応せず、キャラクターが思うように動きません。
まずInputMapでアクション名を使う
入力は、できるだけキー名ではなく InputMapのアクション名 で扱います。
# 避けたい例: キーが固定される
Input.is_key_pressed(KEY_SPACE)
# よい例: InputMapのjumpアクションを見る
Input.is_action_just_pressed("jump")
"jump"、"move_left"、"attack" のような名前で扱うと、あとからキーボード、ゲームパッド、キーコンフィグに対応しやすくなります。
設定場所は「プロジェクト設定」→「Input Map」です。次の記事のInputMap管理ともつながるので、ここでは「スクリプト内にキーコードを直接書かない」ことだけ押さえてください。
実装例1: 移動とジャンプ
プラットフォーマーやトップダウンアクションでは、入力判定の使い分けがそのまま操作感になります。

左右移動は押している間ずっと必要なので、Input.get_axis() を使います。ジャンプは押した瞬間だけなので、is_action_just_pressed() を使います。
extends CharacterBody2D
const SPEED := 260.0
const JUMP_VELOCITY := -420.0
var gravity: float = ProjectSettings.get_setting("physics/2d/default_gravity")
func _physics_process(delta: float) -> void:
if not is_on_floor():
velocity.y += gravity * delta
# ジャンプ開始は「押した瞬間」に1回だけ
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = JUMP_VELOCITY
# 左右移動は「押している間」ずっと方向を見る
var direction := Input.get_axis("move_left", "move_right")
if direction != 0.0:
velocity.x = direction * SPEED
else:
velocity.x = move_toward(velocity.x, 0.0, SPEED)
move_and_slide()
Input.get_axis("move_left", "move_right") は、左なら -1、右なら 1、何も押していなければ 0 を返すため、左右移動のような連続入力に向いています。
ここでジャンプに is_action_pressed("jump") を使うと、ボタンを押しっぱなしにして着地した瞬間、またジャンプが発生しやすくなります。ゲームによっては「押しっぱなし連続ジャンプ」を意図的に採用することもありますが、普通のジャンプ開始なら just_pressed が基本です。
実装例2: 可変ジャンプ
可変ジャンプは、ボタンを短く押すと低く跳び、長く押すと高く跳ぶ仕組みです。多くの2Dアクションで使われます。
考え方は次の通りです。
- 押した瞬間にジャンプを開始する
- 上昇中にボタンを離したら、上向き速度を弱める
- 押し続けた場合は、そのまま高く跳ぶ
extends CharacterBody2D
const SPEED := 260.0
const JUMP_VELOCITY := -420.0
const SHORT_JUMP_MULTIPLIER := 0.45
var gravity: float = ProjectSettings.get_setting("physics/2d/default_gravity")
func _physics_process(delta: float) -> void:
if not is_on_floor():
velocity.y += gravity * delta
if Input.is_action_just_pressed("jump") and is_on_floor():
# まず通常のジャンプを開始する
velocity.y = JUMP_VELOCITY
if Input.is_action_just_released("jump") and velocity.y < 0.0:
# 上昇中に離したら、上向き速度を弱めて低いジャンプにする
velocity.y *= SHORT_JUMP_MULTIPLIER
var direction := Input.get_axis("move_left", "move_right")
velocity.x = direction * SPEED
move_and_slide()
velocity.y < 0.0 を条件にしているのは、Godotの2Dでは上方向がマイナスだからです。落下中にジャンプボタンを離しても、もう上昇していないため短くする必要はありません。
この実装は小さく見えますが、操作感への影響は大きいです。プレイヤーが足場の手前で短く跳ぶ、敵を避けるために軽く跳ぶ、といった細かい調整ができるようになります。
実装例3: チャージ攻撃
チャージ攻撃は、3つの判定をかなり分かりやすく使います。
- 押した瞬間: チャージ開始
- 押している間: チャージ時間を増やす
- 離した瞬間: 攻撃を発射する

extends Node2D
const MAX_CHARGE_TIME := 2.0
var is_charging := false
var charge_time := 0.0
func _process(delta: float) -> void:
if Input.is_action_just_pressed("charge_attack"):
# 押した瞬間にチャージ状態を初期化する
is_charging = true
charge_time = 0.0
if is_charging and Input.is_action_pressed("charge_attack"):
# 押している間だけチャージを進める
charge_time = min(charge_time + delta, MAX_CHARGE_TIME)
update_charge_effect(charge_time / MAX_CHARGE_TIME)
if is_charging and Input.is_action_just_released("charge_attack"):
# 離した瞬間に、溜めた量を使って攻撃する
var power := charge_time / MAX_CHARGE_TIME
fire_charge_shot(power)
is_charging = false
charge_time = 0.0
update_charge_effect(0.0)
func update_charge_effect(rate: float) -> void:
# 本番では色、拡大率、エフェクト量などを変える
scale = Vector2.ONE * lerp(1.0, 1.4, rate)
func fire_charge_shot(power: float) -> void:
print("fire power: %.2f" % power)
チャージ攻撃でよくある失敗は、is_action_pressed() だけで開始も発射も処理しようとすることです。押している間ずっと発射処理が走ったり、チャージ時間のリセットが毎フレーム起きたりします。
入力の状態を「開始」「継続」「終了」に分けると、コードもゲームの動きも読みやすくなります。
ポーリングとイベント駆動の使い分け
ここまで使ってきた Input.is_action_*() は ポーリング です。毎フレーム「今この入力はどうなっているか」を確認します。
一方、Godotには _input(event) や _unhandled_input(event) のような イベント駆動 の入力処理もあります。これは入力が発生したときにGodotから渡される InputEvent を処理する方式です。

| 方法 | 向いている処理 | 例 |
|---|---|---|
Input.is_action_*() | 毎フレーム状態を見たい処理 | 移動、ジャンプ、チャージ、照準 |
_unhandled_input(event) | 入力が来た瞬間だけ扱いたい処理 | ポーズ、メニュー、UI外クリック |
たとえばポーズメニューは、毎フレーム移動のように状態を見続ける必要はありません。入力イベントとして受け取ると自然です。
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("pause"):
# UIに処理されなかったpause入力だけを拾う
get_tree().paused = not get_tree().paused
_unhandled_input() は、Control系UIが先に入力を処理したあと、まだ処理されていない入力だけを受け取ります。ゲーム画面全体のキャンセルやポーズには便利です。
ただし、キャラクター移動のように「押され続けている状態」を毎フレーム使う処理は、_physics_process() でポーリングした方が分かりやすいです。
よくあるつまずき
決定ボタンにpressedを使ってメニューが連続で進む
UIの「決定」は、基本的に1回の入力です。is_action_pressed("ui_accept") を使うと、押しっぱなしの間ずっと決定処理が走ります。
# UIの決定は押した瞬間だけにする
if Input.is_action_just_pressed("ui_accept"):
confirm_selected_item()
長押しで高速スクロールしたい場合は pressed を使うこともありますが、その場合は入力間隔を制御するタイマーを入れると暴走しにくくなります。
物理移動を_processに書いて挙動が揺れる
CharacterBody2D の velocity や move_and_slide() を使う処理は、基本的に _physics_process() に書きます。物理更新と同じタイミングで動かすためです。
UI表示、チャージエフェクト、メニュー切り替えのように物理と直接関係しない処理は _process() でも構いません。
just_pressedを移動に使って一瞬しか動かない
左右移動や照準移動のように、押している間ずっと反応してほしい処理に just_pressed を使うと、入力開始の1回だけしか動きません。
「単発か、継続か」を先に決めると間違いにくいです。
| 操作 | 判定 |
|---|---|
| ジャンプ開始 | just_pressed |
| 左右移動 | pressed / get_axis |
| チャージ中 | pressed |
| チャージ発射 | just_released |
| UI決定 | just_pressed |
| ドラッグ終了 | just_released |
おまけ: 先に知っておくと良いこと
入力バッファやコヨーテタイムは次の段階
操作感をさらに良くするなら、ジャンプ入力を少しだけ保存する 入力バッファ や、足場から離れた直後でも少しだけジャンプを許す コヨーテタイム を使うことがあります。
ただし、これは just_pressed の代わりではありません。まず just_pressed で「押した瞬間」を正しく拾い、その入力を数フレーム保存する、という順番です。
キーボードは同時押しに限界がある
キーボードによっては、複数キーの同時押しで一部の入力が拾えないことがあります。これはコードのミスではなく、キーボード側の制約で起きる場合があります。
アクションゲームで斜め移動、ジャンプ、攻撃を同時に使う場合は、ゲームパッド対応やキー配置の見直しも考えると安全です。
入力名はゲームの意味で付ける
"space" や "left_click" のような物理キー名ではなく、"jump"、"attack"、"dash" のようなゲーム内の意味で名前を付けると、あとから入力方法を差し替えやすくなります。
まとめ
is_action_just_pressed()は、押した瞬間だけ。ジャンプ、攻撃開始、UI決定に使うis_action_pressed()は、押している間ずっと。移動、長押し、チャージ中に使うis_action_just_released()は、離した瞬間だけ。可変ジャンプ、チャージ解放、ドラッグ終了に使う- 物理移動は
_physics_process()、メニューやポーズは_unhandled_input()も候補 - 入力名はInputMapのアクション名で扱い、キーコードを直接書きすぎない
入力処理は地味ですが、ゲームの触り心地を決める重要な部分です。「押した瞬間」「押している間」「離した瞬間」を分けて考えるだけで、操作の意図がかなり読みやすくなります。