Unity ゲーム開発 生成AI

Unity素人がAI活用で進める独学個人ゲーム開発 #11_一時停止機能の作成

本記事では、ChatGPTを活用してUnityの一時停止を実装した過程を紹介します。

記事の目的

前回、アイテムによって自機が増加する仕組みの実装を行いました。
前回記事 ⇒ #10_アイテムの実装③

まだまだ遊べる状態ではありませんが、なんだかんだゲームっぽい画面になってきました。

今回は少し脇道にそれて一時停止機能を作成していきます。

一時停止機能といえばこんな機能を持っているイメージです。

  • ゲームの進行を完全に停止させる。
  • そのまま続けるか、リタイアしてゲームから退出するか、もしくは最初からやり直すリスタートを選択できる。
  • オプションを変更できる。

これが(シューティングゲームにおける)一時停止に求められる主な機能かと思います。
それでは実際に作っていきましょう。

一時停止機能

一時停止の実装

突然の来客や呼び出しに応じるため、1人用のゲームであれば欲しい機能ですよね。
素早い判断が求められるゲームには難易度を保つためにわざと削っているイメージがあります。(ソウルシリーズとか)
今回作成中のシューティングゲームについても判断を求められるように作ってはいますが、一時停止したからといってそこまで有利にならない気がしますので今回はこの機能があった方がよさそうです。早速やっていきましょう。

一時停止機能を実装したいです。
まず、Escを押した時にゲームの進行が止まるような機能の作り方を教えてください。

ChatGPTの回答(クリックで展開)

了解しました!
Unityで Escキーでゲームを一時停止する機能 を実装する基本的な手順を説明します。

実装の流れ
1️⃣ Time.timeScale を使ってゲームの進行を止める
2️⃣ InputでEscキーを検知する
3️⃣ UI(ポーズメニューなど)を表示する(任意)

🔧 基本実装例
以下はシンプルな実装例です。


using UnityEngine;

public class PauseManager : MonoBehaviour
{
    private bool isPaused = false;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            TogglePause();
        }
    }

    void TogglePause()
    {
        isPaused = !isPaused;

        if (isPaused)
        {
            Time.timeScale = 0f;  // ゲーム進行を止める
            Debug.Log("Game Paused");
            // ここでポーズUIを表示する処理も追加できます
        }
        else
        {
            Time.timeScale = 1f;  // ゲーム進行を再開
            Debug.Log("Game Resumed");
            // ポーズUIを非表示にする処理も追加できます
        }
    }
}
        

💡 解説
✅ Time.timeScale
・1f → 通常の速度(デフォルト)
・0f → 全ての Time.deltaTime に依存する動作が停止する(例: Update内の移動やアニメーション)

注意:Time.timeScale では以下は止まりません。
・Update() 内の処理自体(if文やInput検知など)
・FixedUpdate() も停止する
・Animator で Update Mode が Unscaled Time になっているもの

Time.timeScaleは時間の速度に倍率をかける機能とのこと。
"0fにする→時間が動かなくなる→Time.deltatimeが止まる→シーンが止まる"
のような働きのようですね。

とりあえず止まるようになりましたが、突然ぴたりと止まり、再度Escを押すことで突然動き始めます。

再開、リスタート、リタイアの実装

一時停止中に

  • 再開:ゲームを再開する
  • リスタート:最初からやり直す
  • リタイア:ゲームから退出する

を選択できるようにします。
個人的には再開は押してから1秒ほど待機時間があってから再開するのが好きです。
また、リスタート、リタイアについては「本当にいいですか」のような確認が必要かと思います。

一時停止中用のUIを作成したいです。
再開、リスタート、リタイアを選択できるようにしてください。

また、それぞれには以下の機能を付けてください。
再開:一時停止の解除、また、選択してから1秒ほど経ってから再開するようにしてください
リスタート:シーンの最初からにすべての状態を戻す。選択してから本当にリスタートしていいか聞く
リタイア:シーンから退出してタイトルに戻る。選択してから本当にリタイアしていいか聞く

ChatGPTの回答(クリックで展開)

とても良い要件です!
以下に段階的な実装案を用意しました。

機能一覧と要件整理
1️⃣ ポーズメニューUI
・再開
・リスタート(要確認)
・リタイア(要確認)

2️⃣ 各機能の詳細
・再開 → 1秒待ってから一時停止解除
・リスタート → 確認後、現在のシーンを再読み込み
・リタイア → 確認後、タイトルシーンに戻る

🔨 実装手順の流れ
1️⃣ ポーズ用Canvasを作る(PauseCanvas)
・Panel+Button3つ(Resume, Restart, Retire)
・確認用Panel(Restart用 / Retire用)

2️⃣ PauseManagerスクリプトを書く
・EscキーでポーズON/OFF
・ボタンのOnClickに各メソッドを登録

3️⃣ ボタン処理を作る
・Resume → 1秒後解除
・Restart → 確認後、SceneManagerで再読み込み
・Retire → 確認後、SceneManagerでタイトルに戻る

💥 サンプルスクリプト


using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using System.Collections;

public class PauseManager : MonoBehaviour
{
    public GameObject pauseMenu;
    public GameObject confirmPanel;
    public Text confirmText;
    private bool isPaused = false;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            if (!isPaused)
                PauseGame();
            else
                ResumeGameInstant();
        }
    }

    public void PauseGame()
    {
        isPaused = true;
        Time.timeScale = 0f;
        pauseMenu.SetActive(true);
    }

    public void ResumeGameInstant()
    {
        isPaused = false;
        Time.timeScale = 1f;
        pauseMenu.SetActive(false);
    }

    public void ResumeGameDelayed()
    {
        StartCoroutine(ResumeAfterDelay(1f));
    }

    private IEnumerator ResumeAfterDelay(float delay)
    {
        yield return new WaitForSecondsRealtime(delay);
        ResumeGameInstant();
    }

    public void RestartGame()
    {
        ShowConfirmation("本当にリスタートしますか?", () =>
        {
            Time.timeScale = 1f;
            SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        });
    }

    public void RetireGame()
    {
        ShowConfirmation("本当にリタイアしてタイトルに戻りますか?", () =>
        {
            Time.timeScale = 1f;
            SceneManager.LoadScene("TitleScene"); // タイトルシーン名を適宜変更
        });
    }

    private void ShowConfirmation(string message, System.Action onConfirm)
    {
        confirmPanel.SetActive(true);
        confirmText.text = message;

        Button yesButton = confirmPanel.transform.Find("YesButton").GetComponent<Button>();
        Button noButton = confirmPanel.transform.Find("NoButton").GetComponent<Button>();

        yesButton.onClick.RemoveAllListeners();
        noButton.onClick.RemoveAllListeners();

        yesButton.onClick.AddListener(() =>
        {
            confirmPanel.SetActive(false);
            onConfirm.Invoke();
        });

        noButton.onClick.AddListener(() =>
        {
            confirmPanel.SetActive(false);
        });
    }
}
        

🛠 Unityエディタ側の設定
✅ PauseCanvas
・Panel(背景半透明)
・ResumeButton
・RestartButton
・RetireButton
・ConfirmPanel(非表示)
・Text(確認メッセージ用)
・YesButton
・NoButton

✅ PauseManager
・pauseMenu に PauseCanvasのPanelをアタッチ
・confirmPanel に ConfirmPanelをアタッチ
・confirmText に ConfirmPanel内のTextをアタッチ
・各ボタンの OnClick に以下を割り当て:
ResumeButton → PauseManager.ResumeGameDelayed()
RestartButton → PauseManager.RestartGame()
RetireButton → PauseManager.RetireGame()

管理人
管理人
ちょっとずつChatGPTに渡すプロンプトが長くなってきました。
仕様から考えさせると割と痛い目にあいがちな気がしている故の対応です。
仕様を考えてそれに対応したコードを出力させるのが賢い使い方なのかな~と考えています。

Canvas設定


今のところ画像のようになっていますが、上記のチャットだと何をどうすればいいのかよくわかりませんでしたので聞いていきます。

どれを選択して作成すればいいかも含めてUI階層をまとめてください。

ChatGPTの回答(クリックで展開)

とても良いリクエストです!
以下に Unityエディタで作るUI階層まとめ(必要な要素と作成手順)を整理しました。

作成するUI階層まとめ


PauseCanvas (Canvas)
├── PausePanel (Panel) ← ゲーム一時停止中のメニュー本体
│   ├── ResumeButton (Button)
│   ├── RestartButton (Button)
│   └── RetireButton (Button)
└── ConfirmPanel (Panel) ← リスタート/リタイア確認用(最初は非表示)
    ├── MessageText (Text or TextMeshProUGUI)
    ├── YesButton (Button)
    └── NoButton (Button)
        

🛠 作成手順(Unityエディタでの具体的操作)
1️⃣ Canvas作成
Hierarchy → 右クリック → UI → Canvas → 名前を PauseCanvas に変更

2️⃣ PausePanel作成
PauseCanvas の下に
右クリック → UI → Panel → 名前を PausePanel に変更
PausePanel に背景色(例えば黒+アルファ50%)をつける

3️⃣ PausePanel内のボタン作成
PausePanel の下で
・右クリック → UI → Button → 名前を ResumeButton
・右クリック → UI → Button → 名前を RestartButton
・右クリック → UI → Button → 名前を RetireButton
Button内の Text(または TextMeshProUGUI)を編集して表示名を「再開」「リスタート」「リタイア」に変更

4️⃣ ConfirmPanel作成
PauseCanvas の下で
・右クリック → UI → Panel → 名前を ConfirmPanel に変更
・ConfirmPanel は最初は 非表示(Inspectorのチェックを外す or SetActive=false)
中に以下を配置
・右クリック → UI → Text → 名前を MessageText(または TextMeshPro → TextMeshPro - Text)
・右クリック → UI → Button → 名前を YesButton
・右クリック → UI → Button → 名前を NoButton

🎨 UIの並び・配置(例)
PausePanel → 縦に3つのボタンを並べる(Vertical Layout Groupを使うと楽)
ConfirmPanel → 上にメッセージ、下にYes / Noボタンを横並び(Horizontal Layout Groupを使うと楽)

💥 まとめ(何を選べばいい?)
✅ Canvas → PauseCanvas
✅ Panel → PausePanel, ConfirmPanel
✅ Button → ResumeButton, RestartButton, RetireButton, YesButton, NoButton
✅ Text → MessageText(または TextMeshProUGUI推奨)

📦 オススメ(TextMeshPro使用)
もしTextの見た目にこだわりたい場合:
Textではなく TextMeshPro → TextMeshPro - Text を使う(最初のインポート時に確認が出ます)


こんな感じになりました。

色の設定はColorから。アルファ50%は透明度を変えて半透明にするという指示だと思うので、Aのスライダーを真ん中に合わせています。

設定は終わりましたが、現在の画面を見ると画像のようになりました。

左下に謎の□があります。

フォント設定

ここでエラー表示を確認していきます。

The character with Unicode value \u529B was not found in the [LiberationSans SDF] font asset or any potential fallbacks. It was replaced by Unicode character \u25A1 in text object [リタイア].
UnityEngine.Debug:LogWarning (object,UnityEngine.Object)

ChatGPTの回答(クリックで展開)

このワーニングは、TextMesh Pro のフォントアセット(ここでは LiberationSans SDF)が日本語のを含んでいないため、代わりに四角い空白マーク(□)を表示している、という意味です。

解決策:日本語も扱えるフォントアセットを用意する

日本語対応のフォントファイルを用意
例えば「Noto Sans CJK JP」や「Yu Gothic UI」など、CJK(中国語・日本語・韓国語)をサポートする OTF/TTF フォントを入手します。

TextMesh Pro フォントアセットを新規作成
Project ビューで Create → TextMeshPro → Font Asset を選択。
先ほどの日本語フォントファイルをドラッグ&ドロップして、
Character Set を「Unicode Range: すべて」または「Custom Range(s)」にして 0x4E00-0x9FFF(基本漢字)などを指定。
設定後、Generate ボタンでフォントアトラスを作成します。

Label で使うフォントアセットを切り替え
Item プレハブの TextMeshProUGUI コンポーネント(label)の Font Asset 欄を、先ほど作成した日本語対応のアセットに置き換えます。

フォントフォールバックを設定(任意)
複数のフォントアセットを使い分けたい場合、
TextMesh Pro の Font Asset インスペクタで Fallback Font Asset リストに追加しておくと、
プライマリにない文字だけ自動でフォールバックして表示してくれます。

まとめ
原因:LiberationSans には日本語グリフがない
対処:日本語対応フォントで Font Asset を作り直し、TextMesh Pro に割り当てる
ポイント:必要な Unicode 範囲(0x4E00-0x9FFF)を含めてビルドすれば、漢字もカタカナ・ひらがなも表示できます

これで日本語の文字も正しくレンダリングされるようになります!

TextMeshProの基本フォントが日本語に対応していないようです。
タイトル画面を実装したときは「PRESS ANY BUTTON」と表示したため大丈夫でしたが、ここは日本語で実装しようとしたためエラーが出てしまったようですね。

そこで日本語対応のものを持ってくればいいよと言われましたが入手方法が分かりません。

例えば「Noto Sans CJK JP」や「Yu Gothic UI」など、CJK(中国語・日本語・韓国語)をサポートする OTF/TTF フォントを入手します。

どうやればいいですか?

ChatGPTの回答(クリックで展開)

「Noto Sans CJK JP」や「Yu Gothic UI」を入手する方法はいくつかあります。以下では、代表的な2つの方法をご紹介します。

方法①:Google の「Noto Sans CJK JP」をダウンロードして使う
🔹 ダウンロードページにアクセス
・Google の Noto フォント GitHub リポジトリ
https://github.com/googlefonts/noto-cjk
・または Google Fonts から
https://fonts.google.com/noto/specimen/Noto+Sans+JP

🔹 フォントファイルを入手
・GitHub 上の「Releases」タブから最新版 ZIP をダウンロードし、展開
・あるいは Google Fonts の「Download family」ボタンで ZIP を取得

🔹 .otf/.ttf ファイルを確認
展開後のフォルダに NotoSansCJKjp-Regular.otf などが含まれています

🔹 Unity プロジェクトに追加
・Unity エディタの Project ビューの Assets フォルダを右クリック
・「Show in Explorer (macOS では Reveal in Finder)」 を選択し、OS 標準のフォルダ表示を開く
・ダウンロードした .otf または .ttf ファイルを、直接この Assets フォルダ内にドラッグ&ドロップ
・Unity に戻ると自動でインポートされます

方法②:Windows 標準の「Yu Gothic UI」を使う
🔹 Windows のフォントフォルダを開く
・エクスプローラーのアドレスバーに C:\Windows\Fonts と入力して開く

🔹 Yu Gothic UI を探す
・フォント一覧から Yu Gothic UI Regular(または Bold/Italic など)を右クリック
・「コピー」 を選択

🔹 Unity プロジェクトの Assets 配下に貼り付け
・Project ビューの Assets を右クリック → 「Show in Explorer」
・開いたフォルダにコピーしたフォントファイル(例 YuGothicUI-Regular.ttf)を貼り付け

フォントのインポート確認
Unity エディタに戻ると、新しく追加した .otf/.ttf ファイルが Assets に表示されます。
これを右クリック → Create → TextMeshPro → Font Asset でフォントアセット化して、
TextMeshProUGUI の Font Asset に設定すれば、日本語も問題なく表示できるようになります。

今回は方法①で紹介されている「Noto Sans CJK JP」をダウンロードして使ってみます。
Googleが出している様々な言語の基本フォントのようなものらしいので、感謝しつつ使わせてもらいましょう。


ダウンロードしてprojectウインドウに入れたもののここから操作が分かりません。

Unityでフォントを設定する方法を詳しく解説してください

ChatGPTの回答(クリックで展開)

とても良い質問です!
Unity で TextMeshPro(TMP)を使って「特定のフォントを設定する方法」を詳しく解説します。

以下は UI TextMeshPro (TextMeshProUGUI) を例に説明します。

ステップ 1:日本語対応フォントをインポートする
1️⃣ 日本語対応の .ttf または .otf ファイル(例:NotoSansCJKjp-Regular.otf)を入手。
→ Google Fonts などからダウンロード。

2️⃣ Unity の Assets フォルダにドラッグ&ドロップしてインポート。

ステップ 2:TextMeshPro用 SDF Font Asset を作成する
普通のフォントファイルはそのままでは使えません。
TextMeshPro 専用の Font Asset (SDF) に変換します。

具体手順:
1️⃣ 上部メニューから:
Window → TextMeshPro → Font Asset Creator

2️⃣ 開いた「Font Asset Creator」ウィンドウで:
・Source Font File:インポートしたフォント(例:NotoSansCJKjp-Regular.otf)
・Sampling Point Size:0(自動計算)
・Padding:5(デフォルトでOK)
・Packing Method:Optimum

3️⃣ Character Set
・Unicode Range(例:0x4E00–0x9FFF、基本漢字)
・または Custom Characters(必要な文字列だけ入れる)

4️⃣ Atlas Resolution
・1024 以上(文字数が多ければ2048以上)

5️⃣ Render Mode
・SDF または SDF8(推奨)

6️⃣ Generate Font Atlas ボタンを押す。
7️⃣ Save Font Asset ボタンを押して保存。

保存後、Projectビューに Aa アイコンの Font Asset が作成されます。

ステップ 3:TextMeshProUGUI にフォントを設定する
1️⃣ Hierarchy で対象の TextMeshProUGUI オブジェクトを選択。

2️⃣ Inspector で:
Main Settings → Font Asset
ここに先ほど作った Font Asset をドラッグ&ドロップ。

これでそのオブジェクトは日本語対応のフォントになります。

ChatGPTで指定しているUnicodeRangeからの導入は色々あってできず、1日以上時間を使ってしまいました……
この方法じゃできないと言っても同じ方法しか提示してくれなかったため、最終的にはFontAssetCreatorについて解説しているサイトを紹介してもらい別の方法を試しました。

代替としてCustomCharactersに日本語のリストをぶち込んで生成するという方法に至っています。

これで□からちゃんとした文字に変換されるようになりました。

FontAssetCreatorの各項目についてもまとめておこうと思います。

FontAssetCreatorメモ
項目 意味
Source Font File インポート済みのフォントファイルを選択
Sampling Point Size フォントを何ポイントサイズでサンプリング(読み取り)するか。基本は AutoSizing
Padding 各文字の周囲に付ける余白。基本的に 5 でOK
Packing Method 文字をAtlas(画像シート)に並べるときの最適化方法。Optimum は最も効率よく詰め込み、Fast は早く生成できるが質は落ちる
Character Set どの文字を Font Asset に含めるか決める。Unicode Range (Hex) は Unicode 対応文字を、Custom Character は入力した文字を含める。今回は Custom Character で生成
Atlas Resolution 出力される Atlas 画像の解像度。低いと文字が入りきらず、高いとメモリ負担・ビルドサイズが増える。今回はほぼすべての日本語をカバーするため 8192 を使用
Render Mode フォントをどの形式で生成するか



管理人
管理人
今回は提示されたフォントをそのまま使用しましたが、世界観の表現にフォントは意外と大事な気がしています。あっていると嬉しいですし、逆にあっていないとフォントが世界観を崩すことような感覚も覚えます。(レトロゲーのリマスターでやたら高解像度の文字が出てくるとビックリしたり)
そのため、必要だと感じたらゲームの雰囲気にあるフォントに変えようかと思います。

一時停止時のUI切り替え

現状、上の画像のように一時停止したときだけ出てきてほしい文字が画面中央に鎮座し続けます。

続いてなにをするべきか教えてください

ChatGPTの回答(クリックで展開)

とてもいい流れです!
ここまでで UI階層設計が完成したので、次は Unity上でそれらを実装・連携するステップに進みましょう。

次にやること(ステップ順)

1️⃣ UnityでUIを実際に配置する
Unityの Hierarchy で次のように作る:
・Canvas → PauseCanvas
├─ Panel → PausePanel
│ ├─ ResumeButton
│ ├─ RestartButton
│ └─ RetireButton
└─ Panel → ConfirmPanel(初期は非表示)
  ├─ MessageText(または TextMeshProUGUI)
  ├─ YesButton
  └─ NoButton

👉 ポイント
PausePanelは画面中央に、半透明の背景をつける。
ConfirmPanelも中央に、ただし SetActive(false) で初期は非表示。

2️⃣ PauseManager スクリプトを作成・アタッチ
・Assets → Scripts フォルダを作る(なければ)
・その中に PauseManager.cs を作成する
・作成したスクリプトを PauseCanvas にアタッチする

3️⃣ スクリプトの変数をInspectorに接続する
PauseManagerのpublic変数に以下をドラッグでアタッチ:
・pauseMenu → PausePanel
・confirmPanel → ConfirmPanel
・confirmText → MessageText(または TextMeshProUGUI)

4️⃣ ボタンのOnClickイベントを設定する
・各ボタンの Button コンポーネント → On Click() に PauseCanvasをドラッグ
・呼び出す関数を設定:
ResumeButton → PauseManager → ResumeGameDelayed()
RestartButton → PauseManager → RestartGame()
RetireButton → PauseManager → RetireGame()
※YesButton/NoButtonは動的にスクリプト側で登録される(ShowConfirmation内で登録済み)

5️⃣ 確認用の「TitleScene」を作る(またはシーン名を確認)
Retire(リタイア)用に戻るタイトル画面のシーンを作成するか、
スクリプト中の "TitleScene" にあわせる。
例:


SceneManager.LoadScene("TitleScene");
        

🔧 (任意)おすすめ設定
・PauseCanvas の Canvas Component → Render Mode → Screen Space - Overlay
・PauseCanvas の Canvas Group → Interactable / Blocks Raycasts を使って切り替え管理

PauseManager.csについてTextしか受け付けない状態だったのでスクリプトを変更しました。
public Text confirmText; ⇒ public TextMeshProUGUI confirmText;


各オブジェクトをアタッチ


各ボタンのOnClick()から選択

最終的にこんな形になりました。

機能自体は問題なく使えるようになっていそうです。
ただし、自分が実装していた画面よりかなり小さくなってしまいました。後々直します。

オプション変更機能

ゲーム中(特に初めてプレイするときなど)に音量調整がしたくなったり、キーコンフィグが気になったりするのはよくあることです。そこでいちいちタイトル画面に戻って設定して~というのは手間に思う場合が多いはずです。

一時停止中にオプション変更が可能なようにしたいです。まだ中身は作っていませんがとりあえず見た目だけ作りたいです。

ChatGPTの回答(クリックで展開)

とてもいい進め方です!
まずは「ポーズ中に表示するオプション画面の見た目」を作りましょう。

UI階層の例


PauseCanvas (Canvas)
├── PausePanel (Panel)
│   ├── ResumeButton (Button)
│   ├── RestartButton (Button)
│   ├── RetireButton (Button)
│   └── OptionButton (Button) ←★ 新規追加
├── ConfirmPanel (Panel)
│   ├── MessageText (TextMeshProUGUI)
│   ├── YesButton (Button)
│   └── NoButton (Button)
└── OptionPanel (Panel) ←★ 新規追加
    ├── OptionTitle (TextMeshProUGUI)
    ├── Placeholder1 (TextMeshProUGUI) ←例:「音量設定(後で実装予定)」
    ├── Placeholder2 (TextMeshProUGUI) ←例:「画面設定(後で実装予定)」
    └── BackButton (Button) ← オプション画面を閉じるボタン
        

💥 PauseManager.cs(完全版例)


using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using TMPro;
using System.Linq;

public class PauseManager : MonoBehaviour
{
    public GameObject pauseMenu;
    public GameObject confirmPanel;
    public GameObject optionPanel;
    public TextMeshProUGUI confirmText;
    private bool isPaused = false;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            if (optionPanel.activeSelf)
            {
                CloseOptions();
            }
            else if (!isPaused)
            {
                PauseGame();
            }
            else
            {
                ResumeGameInstant();
            }
        }
    }

    public void PauseGame()
    {
        isPaused = true;
        Time.timeScale = 0f;
        pauseMenu.SetActive(true);
    }

    public void ResumeGameInstant()
    {
        isPaused = false;
        Time.timeScale = 1f;
        pauseMenu.SetActive(false);
        optionPanel.SetActive(false);
        confirmPanel.SetActive(false);
    }

    public void ResumeGameDelayed()
    {
        StartCoroutine(ResumeAfterDelay(1f));
    }

    private System.Collections.IEnumerator ResumeAfterDelay(float delay)
    {
        yield return new WaitForSecondsRealtime(delay);
        ResumeGameInstant();
    }

    public void RestartGame()
    {
        ShowConfirmation("本当にリスタートしますか?", () =>
        {
            Time.timeScale = 1f;
            SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        });
    }

    public void RetireGame()
    {
        ShowConfirmation("本当にリタイアしてタイトルに戻りますか?", () =>
        {
            Time.timeScale = 1f;
            SceneManager.LoadScene("TitleScene");
        });
    }

    private void ShowConfirmation(string message, System.Action onConfirm)
    {
        pauseMenu.SetActive(false);
        optionPanel.SetActive(false);
        confirmPanel.SetActive(true);
        confirmText.text = message;

        var buttons = confirmPanel.GetComponentsInChildren<Button>(true);
        if (buttons == null || buttons.Length == 0)
        {
            Debug.LogError("ConfirmPanel 内に Button コンポーネントが見つかりません!");
            return;
        }

        Button yesButton = buttons.FirstOrDefault(b => b.name == "YesButton");
        Button noButton = buttons.FirstOrDefault(b => b.name == "NoButton");

        if (yesButton == null || noButton == null)
        {
            Debug.LogError("YesButton または NoButton が見つかりません!");
            return;
        }

        yesButton.onClick.RemoveAllListeners();
        noButton.onClick.RemoveAllListeners();

        yesButton.onClick.AddListener(() =>
        {
            confirmPanel.SetActive(false);
            onConfirm.Invoke();
        });

        noButton.onClick.AddListener(() =>
        {
            confirmPanel.SetActive(false);
            pauseMenu.SetActive(true);
        });
    }

    public void OpenOptions()
    {
        pauseMenu.SetActive(false);
        optionPanel.SetActive(true);
    }

    public void CloseOptions()
    {
        optionPanel.SetActive(false);
        pauseMenu.SetActive(true);
    }
}
        

ポイント
・OptionPanelは最初は非表示にする
・OptionButtonのOnClickには OpenOptions() を設定
・OptionPanelのBackButtonのOnClickには CloseOptions() を設定

これで「見た目だけ」のオプション画面がポーズ中に開閉できるようになります!

Textだけの設定だったのでボタンでの設定に変更しましたが、とりあえず表示だけは作成しました。

おまけ_使えそうなプロンプト



①このスクリプトを1文ずつ解説をお願いします。長くなった場合は分割してください。
スクリプトの読み取りが上手くできないときに使える。愚直に"{"で1行取っているところも解説してくれる。

②C#とUnityの実装の観点からコードの解説をしてください。
出力されたスクリプトの読み取りで使える。①と違ってUnityの標準機能だったりを解説してくれる。

③参考にしたサイトのURLを記載してください。
(実際はよく知らないけど)よくあるプロンプトだと思っています。これがあることでChatGPTが読み取りきれなかった情報も拾えるようになったりする。

  • この記事を書いた人

たげお

ソロゲームもオンラインゲームも対戦ゲームもソシャゲも楽しむ雑食ゲーマー。特筆して好きなジャンルはRPG、FPS。最近は格ゲーにお熱。 思い出のゲームは『FF9』

-Unity, ゲーム開発, 生成AI
-, , ,