「ゲームを終わる」「ウィンドウの×」などでアプリを終了するときに「ダイアログ」を表示させます。
セーブシステム時に実装したダイアログですが、保留分を作っていきます。
プロジェクトのまとめ
目的
- ウィンドウの「×」ボタン、Alt+F4、ゲーム内の終了ボタンを押したときに
即終了ではなく確認ダイアログを表示する - 「はい」で終了、「いいえ」でキャンセル
- 全シーンで統一した終了フローを実現
実装のコア要素
■ QuitManager(Sys_QuitManager)新規スクリプト
- 終了要求の受付・フラグ管理・終了処理
- シングルトン化して DontDestroyOnLoad で全シーン対応
- 重複配置されても破棄されるので安全
■ Sys_DialogManager
- UI_PanelBase を継承した既存ダイアログを使用
- 「はい」を押すと QuitManager.DoQuit() を呼ぶ
- 「いいえ」を押すと閉じるだけ
■ Application.wantsToQuit
- ×ボタン / Alt+F4 など、OS側の終了要求をフック
- 一旦キャンセルしてダイアログ表示
QuitManagerの仕組み
■ フラグ管理
- isQuitting → 終了処理が重複しないように制御
- isDialogOpen → ダイアログの多重表示を防止
■ 主要メソッド
- RequestQuit() → ゲーム内終了ボタン用
- OnWantsToQuit() → ウィンドウ閉じ / Alt+F4 フック
- AskQuit() → Sys_DialogManager にダイアログ表示
- ForceQuit() → 実際に終了(エディタ・ビルド対応)
■ Singleton + DontDestroyOnLoad
- タイトルシーンに配置するだけで全シーン対応
- 次のシーンに置いても破棄される → 重複問題解消
シーン構成のポイント
- タイトルシーン:Sys_QuitManager を配置(必須)
- 次のシーン以降:配置不要
- Sys_DialogManager は各シーンに UI として存在していることを想定
動作フロー
ユーザー操作
└─ ×ボタン / Alt+F4 / ゲーム内終了ボタン
│
▼
Sys_QuitManager.RequestQuit() / OnWantsToQuit()
│
▼
Sys_DialogManager.Instance.Show("本当に終了しますか?", QuitManager.ForceQuit)
│
├─ はい → ForceQuit() → アプリ終了
└─ いいえ → ダイアログ閉じる
注意点
- ダイアログ未設定だと強制終了されるので、Sys_DialogManager は必須
- Editor では EditorApplication.isPlaying = false、ビルドでは Application.Quit()
- 二重終了防止フラグを必ず確認
今回の設計の価値
- 終了処理を 完全に一元化
- UI_Manager / Stack とも自然に連携可能
- シーン切り替え後も動作保証
- 重複配置しても安全(Singleton で破棄)
- 拡張性が高く、将来的に「セーブ確認」「タイトルに戻る確認」なども追加可能
改善★0411
■ 改修目的
ESCキーによるゲーム終了機能の追加と、それに伴う既存バグの修正。
■ 変更ファイル一覧
| ファイル | 変更内容 |
|---|---|
| Sys_QuitManager.cs | ESCキー追加・各種ガード処理 |
| Sys_DialogManager.cs | onNoオプション引数追加 |
| Sys_SaveManager.cs | IsSavingフラグ追加 |
■ 各ファイルの変更詳細
Sys_QuitManager.cs
- using UnityEngine.InputSystem 追加(旧Input.GetKeyDownは使用不可)
- Update() にESCキー検知を追加(Keyboard.current.escapeKey.wasPressedThisFrame)
- isDialogOpen フラグを追加し、終了ダイアログの二重表示を防止
- escKeyEnabled フラグを追加し、Inspectorまたは外部スクリプトからESCを無効化可能に
- Update() と OnWantsToQuit() の両方で以下を統一した挙動に
- 他UIが開いている場合は CloseAll() で閉じてから終了ダイアログを表示
- セーブ中は終了操作を完全に無視
Sys_DialogManager.cs
- Show(string message, Action onYes, Action onNo = null) に onNo をオプション引数として追加
- OnNoClicked() で onNoCallback?.Invoke() を呼ぶように変更
- 既存の Show(message, onYes) の呼び出しは変更不要
Sys_SaveManager.cs
- IsSaving プロパティを追加
- SaveRoutine() の開始時に IsSaving = true、完了時に IsSaving = false
- AutoSaveRoutine() にも同様に追加
■ 終了操作ごとの挙動まとめ
| 操作 | 他UIなし | 他UIあり | セーブ中 |
|---|---|---|---|
| ウィンドウ閉じるボタン | 終了ダイアログ表示 | 他UIを閉じて終了ダイアログ | 無視 |
| Alt+F4 | 終了ダイアログ表示 | 他UIを閉じて終了ダイアログ | 無視 |
| 終了ボタン | 終了ダイアログ表示 | 終了ダイアログ表示 | 終了ダイアログ表示 |
| ESCキー | 終了ダイアログ表示 | 他UIを閉じて終了ダイアログ | 無視 |
■ 発見・修正した既存バグ
ダイアログ被り問題
他のUIが開いている状態でAlt+F4やウィンドウ閉じるボタンを押すと終了ダイアログが重なっていた。OnWantsToQuit() に IsBlocked チェックと CloseAll() を追加して修正。
セーブ中の強制終了問題
セーブのスクリーンショット撮影中(コルーチン)に終了操作が走ると、
スクリーンショットが欠ける可能性があった。
IsSaving フラグで終了操作をセーブ完了まで無視するよう修正。
■ 注意事項・今後の考慮点
- escKeyEnabled は SetEscKeyEnabled(false) で外部から無効化できる。
ムービー再生中など、ESCを別用途に使いたい場面が出た場合に活用すること - Sys_DialogManager.Show() を新たな箇所から呼ぶ際、
Noボタンでフラグや状態を戻す必要がある場合は onNo コールバックを必ず渡すこと - UI_PanelBase.Open() は Sys_InputManager.Block() を呼ぶ設計のため、新しいUI画面を追加する際は必ず UI_PanelBase を継承し Open()/Close() 経由で表示・非表示を制御すること

コメント