【Godot】一時停止と再開ボタンの作り方|pausedとProcess Mode
この記事について
一時停止はできるのに、再開ボタンまで反応しなくなった。Godotでは、ゲーム全体をpausedにしたとき、メニュー側にも停止が伝わることがあります。再開用のUIだけは停止中も処理できるように、Process Modeを分けます。
この記事では、横へ動く四角と経過時間を止め、画面の「再開する」ボタンで動きを再開する小さなサンプルを作ります。Godot 4.6.3のGDScriptを使います。外部画像や音声は不要で、項目名は英語表記です。
この記事でわかること
- SceneTree.pausedで動作を止め、falseで再開する方法
- 一時停止中だけ動かすメニューにWhen Pausedを設定する方法
- 停止前・停止中・再開後の経過時間を見比べる確認方法
基本手順
手順1:動く四角と時間表示を用意する
Compatibilityの新規プロジェクトを作成します。Project → Project Settings → Display → WindowでViewport Widthを640、Viewport Heightを480にします。2D Sceneを作り、ルートのNode2DをPauseDemoへ名前変更して、pause_demo.tscnとして保存します。
PauseDemoの子にNode2Dを追加してWorldにします。Worldの子にPolygon2Dを追加してMover、Labelを追加してTimeLabelにします。Moverは画像なしで四角を描画できるノードです。
MoverのInspectorでData → Polygonの配列を開き、Sizeを4にして、要素0を(-24, -24)、要素1を(24, -24)、要素2を(24, 24)、要素3を(-24, 24)にします。Transform → PositionはX=80、Y=260にします。Colorを見やすい水色にします。
TimeLabelのLayout → Transform → PositionをX=40、Y=40、SizeをX=460、Y=40にし、Textへ「経過時間: 0.0秒」を入れます。Theme Overrides → Font Sizes → Font Sizeは24にします。
PauseDemo (Node2D) └ World (Node2D) ├ Mover (Polygon2D) └ TimeLabel (Label)
Worldへworld.gdを付け、次のコードを入力します。
extends Node2D
var elapsed: float = 0.0
@onready var mover: Polygon2D = $Mover
@onready var time_label: Label = $TimeLabel
func _process(delta: float) -> void:
elapsed += delta
mover.position.x = 80.0 + fmod(elapsed * 100.0, 480.0)
time_label.text = "経過時間: %.1f秒" % elapsed
elapsedは動作中の経過時間です。Moverは1秒で100ピクセル進み、右側まで来ると左へ戻ります。fmod()で移動距離の余りを求めています。時間表示も同じ_process()内で更新するため、停止したかどうかを数字で確かめられます。

手順2:停止ボタンと再開用メニューを作る
PauseDemoの子にCanvasLayerを2つ追加し、HUDとPauseMenuにします。HUDの子へButtonを追加してPauseButtonにします。PauseMenuの子にはPanelを追加し、Panelの子へLabelとButtonを追加してPausedLabel、ResumeButtonに名前変更します。
PauseDemo (Node2D)
├ World (Node2D)
│ ├ Mover (Polygon2D)
│ └ TimeLabel (Label)
├ HUD (CanvasLayer)
│ └ PauseButton (Button)
└ PauseMenu (CanvasLayer)
└ Panel (Panel)
├ PausedLabel (Label)
└ ResumeButton (Button)
各ControlのLayout → Transformで、次のPositionとSizeを設定します。Panelの子の位置はPanelを基準とした値です。
- PauseButton:Position (40, 100)、Size (200, 56)、Text「一時停止」
- Panel:Position (260, 70)、Size (270, 140)
- PausedLabel:Position (20, 10)、Size (230, 40)、Text「一時停止中」
- ResumeButton:Position (20, 64)、Size (230, 56)、Text「再開する」
LabelとButtonのFont Sizeを24にします。PauseMenuのCanvasLayer → Layerを2にし、CanvasLayer → Visibleをオフにします。開始時はメニューを隠し、停止したときだけ表示させます。WorldとHUDは標準のProcess Modeのままにしてください。

手順3:PauseMenuだけWhen Pausedにする
SceneドックでPauseMenuを選びます。InspectorのNode → Processを開き、ModeをWhen Pausedに変更します。見つからない場合はInspectorの検索欄へ「process」と入力すると絞り込めます。
Panel、PausedLabel、ResumeButtonのProcess ModeはInheritのままにします。これでPauseMenu以下だけが、一時停止中に処理される枝になります。PauseDemo全体をAlwaysへ変更すると、Worldの動きまで継続する可能性があるので、設定するノードを確認してください。

When Pausedは「停止中にだけ処理する」、Alwaysは「停止中も通常時も処理する」設定です。今回の再開メニューは通常時には隠れていてよいので、When Pausedが合っています。Visibleをオフにすることと、処理を停止することは別の設定です。
手順4:停止と再開をボタンへ接続する
HUDへhud.gdを付け、次のコードを入力します。$”../PauseMenu”はHUDの親へ1つ戻って、兄弟のPauseMenuを探すパスです。
extends CanvasLayer
@onready var pause_menu: CanvasLayer = $"../PauseMenu"
func _ready() -> void:
$PauseButton.pressed.connect(_on_pause_pressed)
func _on_pause_pressed() -> void:
pause_menu.show()
get_tree().paused = true
「一時停止」を押すとメニューを表示し、get_tree().pausedをtrueにします。次に、PauseMenuへpause_menu.gdを付け、再開処理を書きます。
extends CanvasLayer
func _ready() -> void:
$Panel/ResumeButton.pressed.connect(_on_resume_pressed)
func _on_resume_pressed() -> void:
get_tree().paused = false
hide()
こちらはpausedをfalseに戻してメニューを隠します。今回は_ready()でシグナルを接続しているため、Signalsタブからの接続を重ねないでください。スクリプトを付ける場所も、停止側はHUD、再開側はPauseMenuです。
手順5:実行し、停止中の時間が変わらないことを確かめる
シーンと3つのスクリプトを保存し、Run Current Scene(Windows・Linuxの標準ショートカットはF6)を押します。四角が横へ動き、経過時間が増えることを確認してから「一時停止」をクリックします。
「一時停止中」と「再開する」が表示されたら、表示時刻を覚えて数秒待ちます。停止中は四角の位置と経過時間が変わりません。「再開する」をクリックすると、停止していた時点から時間が増え、四角も動き出します。


停止と再開をもう一度繰り返して、2回目も同じように動くか確認します。実行を終了して最初から起動し直すと、経過時間は0から始まり、メニューは隠れた状態です。このサンプルの時間は「実行してからの現実の時間」ではなく、「_process()が動いていた時間」です。
うまくいかないときの確認箇所
停止できるのに、再開ボタンが反応しない
最初にPauseMenuのProcess ModeがWhen Pausedか確認します。Inheritのままだと、停止中に再開ボタンの入力処理も止まってしまいます。ResumeButtonだけを確認するのではなく、その親のPauseMenuまで見てください。
次に、ResumeButtonのpressed接続と、pause_menu.gdがPauseMenuに付いているかを調べます。DebuggerにNode not foundが出る場合は、Panel/ResumeButtonの名前と親子関係を見直してください。
メニューは表示されるが、四角が動き続ける
Worldまたはその親のProcess ModeがAlwaysになっていないか確認します。WorldはInheritのまま、PauseMenuだけWhen Pausedに分けます。また、show()だけでは停止しません。hud.gdにget_tree().paused = trueがあるか確認してください。
再開ボタンを押したのに、メニューだけ消えてゲームが止まったまま
hide()だけが実行されていないか確認します。メニューを隠す処理に加えて、get_tree().paused = falseが必要です。逆にfalseへ戻すだけならゲームは再開しますが、メニューは表示されたままになります。
停止中に動かしたい物理オブジェクトが動かない
Process ModeのAlwaysは、停止中の物理処理まで自動的に復帰させる設定ではありません。今回の四角は座標を更新するだけのサンプルです。物理演算を使うゲームへ応用するときは、UIの継続処理と物理サーバーの停止を分けて考えます。
まとめ
一時停止の基本はpaused = true、再開はpaused = falseです。そのうえで、再開ボタンを含むPauseMenuへWhen Pausedを設定すると、ゲームを止めた状態でもメニューを操作できます。動く対象とメニューの枝を分け、経過時間と実際のクリックで停止・再開を確かめましょう。
参考:Godot 4.6公式ドキュメント:Pausing games and process mode
サイトアイコン-2-150x150.png)