スポンサーリンク
UnityUnityメモ

Unityで「一時停止(ポーズ)」を正しく実装する完全ガイド|Time.timeScaleの落とし穴と対策

Unity
  1. はじめに
  2. 1. Unityにおける「ポーズ」の基本的な考え方
    1. 「止まる処理」と「止まらない処理」が存在する
    2. Update と FixedUpdate の違いを理解することが第一歩
    3. ポーズは「状態管理」の問題でもある
  3. 2. Time.timeScaleとは?仕組みと影響範囲を正確に理解しよう
    1. Time.timeScaleは「時間の速さ」を決める値
    2. Time.timeScaleの影響を受けるもの
    3. Time.timeScaleの影響を受けないもの(超重要)
    4. unscaledDeltaTimeという「別の時間軸」
    5. Time.timeScaleはシーンを跨いでも保持される
  4. 3. 基本実装:Time.timeScaleを使ったシンプルなポーズ機能
    1. ① PauseManagerスクリプトを作成する
    2. ② ポーズ状態を管理する変数を用意する
    3. ③ ポーズ/再開を切り替えるメソッドを作る
    4. ④ キー入力でポーズを切り替える
    5. ⑤ GameObjectにアタッチする
  5. 4. ポーズメニューUIの作成と連携方法
    1. ① CanvasとPanelを作成する
    2. ② テキストとボタンを配置する
    3. ③ ポーズメニューを初期状態で非表示にする
    4. ④ PauseManagerからUIを制御する
    5. ⑤ ボタンとスクリプトを紐付ける
  6. 5. Time.timeScaleだけでは足りない理由(よくある落とし穴)
    1. 落とし穴① Update内の処理が動き続ける
    2. 落とし穴② オーディオが止まらない
    3. 落とし穴③ アニメーションが止まらない/止まり方がおかしい
    4. 落とし穴④ Rigidbody再開時の挙動が不自然になる
    5. 落とし穴⑤ シーン遷移時のtimeScaleリセット忘れ
  7. 6. 各要素を正しく止める実践テクニック
    1. 6-1. Update内の処理を安全に止める方法
    2. 6-2. オーディオを正しく停止・再開する
    3. 6-3. アニメーション・Tweenを正しく制御する
  8. 7. 一歩進んだ設計:拡張性の高いポーズ管理
    1. 7-1. ポーズは「イベント」として扱う
    2. 7-2. インターフェース(IPausable)を使う設計
    3. 7-3. イベント駆動(Observerパターン)でさらに柔軟に
    4. 7-4. シングルトンPauseManagerは「使いどころ」を選ぶ
  9. 8. シーン遷移・外部アセット使用時の注意点
    1. 8-1. シーン遷移時は必ずTime.timeScaleをリセットする
    2. 8-2. ポーズ中にシーンを切り替える設計に注意
    3. 8-3. 外部アセットは「timeScaleの影響」を必ず確認する
    4. 8-4. ポーズ中の入力処理にも注意する
  10. まとめ
  11. よくある質問(FAQ)
    1. 関連記事:

はじめに

Unityでゲームを作っていると、ほぼ確実に必要になるのが「一時停止(ポーズ)」機能ですよね。

プレイヤーがトイレに行ったり、設定を変更したり、ちょっと一息ついたり…。 ポーズは遊びやすさを大きく左右する重要な機能です。

でも、いざ実装しようとするとこんな経験、ありませんか?

  • Time.timeScale = 0 にしたのに Update が普通に動いている
  • ゲームは止まったのに BGMだけ鳴り続けている
  • UIやアニメーションが なぜか動き続ける

実はこれ、Unityの仕様を知らないと必ずハマるポイントなんです。 Unityには「このボタンを押せばゲームが完全に止まる」という万能な仕組みは用意されていません。

つまりポーズ機能は、
「すべてを止める」のではなく、「止めるべきものを正しく制御する」
という設計が必要になります。

この記事では、

  • Time.timeScale の正しい仕組み
  • なぜそれだけでは不十分なのか
  • UI・音・アニメーションを含めた実践的なポーズ実装
  • 中〜大規模開発でも破綻しない設計の考え方

を、解説していきます。

「とりあえず動いた」ポーズから、
「安心して使える」ポーズ機能へステップアップしたい方は、ぜひ最後まで読んでみてくださいね ✨




1. Unityにおける「ポーズ」の基本的な考え方

まず最初に大事なお話からしますね ☝️ Unityにおける「ポーズ」は、ゲーム全体を一瞬で完全停止する魔法ではありません。

ここを勘違いしたまま実装を進めると、あとで必ず混乱します。

Unityのポーズ実装で押さえるべき本質は、とてもシンプルで、

「Unityは時間の流れを止めるエンジンであって、処理そのものを止めるエンジンではない」

という点です。

つまり、

  • 時間の影響を受ける処理
  • 時間とは無関係に動く処理

この2つが、最初からはっきり分かれて存在しているんですね。


「止まる処理」と「止まらない処理」が存在する

Unityでは、ゲーム中の処理がすべて同じルールで動いているわけではありません。

代表的な例を挙げると、こんな感じです。

  • 止まるもの:物理演算、Time.deltaTime を使った移動処理
  • 止まらないものUpdate() 自体、UI操作、Time.unscaledDeltaTime を使った処理

ここでよくある勘違いが、

Time.timeScale = 0 にしたら Update が呼ばれなくなる」

というものですが、これは完全に誤りです。

Update は、時間が止まっていても毎フレーム必ず呼ばれ続けます

だからこそ、

  • 入力処理が動き続ける
  • 条件分岐が実行され続ける
  • 意図しない処理がポーズ中も進む

といった現象が起きるんですね。


Update と FixedUpdate の違いを理解することが第一歩

ポーズ実装を正しく理解するためには、 Update と FixedUpdate の役割の違いを避けて通れません。

ここが曖昧なままだと、

  • 「なんでこれは止まって、こっちは止まらないの?」
  • 「物理だけ止まって挙動がおかしい…」

と、原因不明のバグに見えてしまいます。

この2つの違いについては、こちらの記事でとても丁寧に解説しています👇

この記事を一度読んでおくと、 「ポーズ中に何が止まって、何が止まらないのか」が一気にクリアになりますよ。


ポーズは「状態管理」の問題でもある

もうひとつ大事なのが、 ポーズは時間制御だけの問題ではないという点です。

実際のゲームでは、

  • ポーズ中は入力を受け付けない
  • 敵AIの思考を止めたい
  • 演出やSEは一部だけ動かしたい

といった状態による分岐が必ず発生します。

そのためポーズは、

「今、ゲームはプレイ中なのか?ポーズ中なのか?」

という状態管理(ステート管理)として考える必要があります。

この考え方ができるようになると、 後半で解説する「拡張性の高いポーズ設計」もスッと理解できるようになります 😊




2. Time.timeScaleとは?仕組みと影響範囲を正確に理解しよう

ここからは、Unityでポーズ実装を語るうえで避けて通れない存在Time.timeScale について詳しく見ていきましょう。

「ポーズ=Time.timeScaleを0にするもの」 というイメージを持っている方も多いと思いますが、 それは半分正解で、半分不正解です。


Time.timeScaleは「時間の速さ」を決める値

まず大前提として、Time.timeScale

Unity内の「時間の進み方の倍率」を指定するプロパティ

です。

  • Time.timeScale = 1.0f → 通常速度
  • Time.timeScale = 0.5f → 半分のスピード(スロー演出など)
  • Time.timeScale = 0.0f → 時間が進まない(ポーズ)

つまり、時間を止めているのではなく、0倍速にしている、 というイメージが一番しっくりきます。


Time.timeScaleの影響を受けるもの

では、Time.timeScale を0にすると、 具体的に何が止まるのでしょうか?

代表的なのは、次のような処理です。

  • 物理演算(Rigidbody / Collider)
  • FixedUpdate()
  • Time.deltaTime を使った移動・処理

たとえば、

  • transform.Translate(speed * Time.deltaTime)
  • Rigidbody に力を加える処理

こういった処理は、Time.timeScale = 0 にすると 見事にピタッと止まります

「お、ちゃんと止まったじゃん!」 と、ここで安心してしまう人がとても多いです 😅


Time.timeScaleの影響を受けないもの(超重要)

ここが最大の落とし穴です。

Time.timeScaleすべての処理に影響するわけではありません

影響を受けない代表例はこちら。

  • Update() メソッド自体
  • UI操作(Button / EventSystem)
  • Time.unscaledDeltaTime を使った処理
  • 一部のアニメーション・Tween

特に重要なのが、もう一度言いますが、

Update() は timeScale が 0 でも毎フレーム呼ばれ続けます

という点です。

なので Update の中に、

  • 入力判定
  • 状態更新
  • 条件分岐による処理

が書かれていると、 ポーズ中でも普通に実行されてしまうんですね。

これが、

  • ポーズ中に操作できてしまう
  • 内部的な状態だけ進んでしまう

といった「見えないバグ」の正体です。


unscaledDeltaTimeという「別の時間軸」

Unityには、Time.deltaTime とは別に

Time.unscaledDeltaTime

という値が用意されています。

これは、

Time.timeScaleの影響を受けない「リアル時間ベースのdeltaTime」

です。

そのため、

  • ポーズ中でも動くUIアニメーション
  • フェードイン・フェードアウト
  • ポーズメニューの演出

といった処理では、 あえて unscaledDeltaTime を使うケースが多くなります。

この「時間が2系統ある」という考え方を理解すると、 ポーズ設計が一気に楽になりますよ。


Time.timeScaleはシーンを跨いでも保持される

これも実務でよく事故るポイントです。

Time.timeScale の値は、 シーンをロードしても自動では元に戻りません

つまり、

  • ポーズ中にタイトルへ戻る
  • 次のシーンをロードする

といった場面で Time.timeScale = 1 に戻し忘れると、

「次のシーンが完全に止まったまま」

という恐ろしい状態になります…。

このあたりの時間管理を含めて、 Time系を体系的に理解したい方は、こちらも参考になります👇


ここまでで、

  • なぜ Time.timeScale だけでは不十分なのか
  • なぜ「止まるもの」と「止まらないもの」が出てくるのか

が、かなりクリアになったと思います。

次は、 「じゃあ実際どうやってポーズを作るの?」 という疑問に答えるため、

👉 Time.timeScaleを使った基本的なポーズ実装 を、コード付きで解説していきますね 😊




3. 基本実装:Time.timeScaleを使ったシンプルなポーズ機能

ここからは、いよいよ実装に入っていきます ✨ まずは一番シンプルで、多くの人が最初に採用する Time.timeScale を使ったポーズ実装から作ってみましょう。

この章の目的は、

  • 最低限「ポーズ/再開」ができる状態を作る
  • 後の改善ポイントを理解しやすくする

という土台作りです。


① PauseManagerスクリプトを作成する

まずはポーズ状態を管理する専用スクリプトを用意します。

プロジェクトウィンドウを右クリックし、 「Create」→「C# Script」 を選んで、

PauseManager

という名前のスクリプトを作成してください。

このスクリプトが、 「今ゲームがポーズ中かどうか」を管理する中枢になります。


② ポーズ状態を管理する変数を用意する

次に、ポーズ中かどうかを判定するための変数を用意します。

基本はとてもシンプルで、 bool を1つ持たせるだけです。


bool isPaused = false;

この変数が、

  • true → ポーズ中
  • false → プレイ中

という状態を表します。

「Time.timeScale を見るんじゃダメなの?」 と思うかもしれませんが、 状態管理用の変数は必ず別に持つのがおすすめです。

理由は、後半の拡張設計でハッキリしてきます 😊


③ ポーズ/再開を切り替えるメソッドを作る

次に、ゲームを止める処理と、再開する処理をそれぞれ用意します。


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

public void ResumeGame()
{
    Time.timeScale = 1f;
    isPaused = false;
}

やっていることはとても単純で、

  • ポーズ時:timeScale を 0 にする
  • 再開時:timeScale を 1 に戻す

それに合わせて、 isPaused の状態も更新しています。

この2つのメソッドがあれば、 「止める」「戻す」という基本動作は完成です。


④ キー入力でポーズを切り替える

次は、実際にポーズを切り替えるきっかけを作ります。

今回は例として、 Escapeキー を押したらポーズ/再開を切り替えるようにしてみましょう。


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

ここで大事なのが、

Updateはポーズ中でも動き続ける

という前提を、あえて利用している点です。

だからこそ、 ポーズ中でもキー入力を受け取って「再開」できるわけですね。


⑤ GameObjectにアタッチする

最後に、このスクリプトをシーンに配置します。

Hierarchyウィンドウを右クリックして、

「Create Empty」

で空のGameObjectを作成し、

GameManagerPauseManager

といった分かりやすい名前を付けましょう。

そこに、作成した PauseManager スクリプトを ドラッグ&ドロップ でアタッチします。

これで、

  • Escapeキーでポーズ
  • もう一度押すと再開

という最低限のポーズ機能が完成しました 🎉


ただし……ここで終わりではありません。

この状態だと、

  • Update内の処理は動き続ける
  • BGMやSEは止まらない
  • アニメーションが暴れることがある

といった実戦では困る問題がまだ山ほど残っています。

次は、 👉 ポーズ中であることが一目でわかる「UI」の作成 に進んでいきましょう 😊




4. ポーズメニューUIの作成と連携方法

ポーズ機能を実装したら、次に必要になるのが 「今ポーズ中ですよ」とプレイヤーに伝えるUIです。

キー操作だけで止まる仕組みはできましたが、 画面に何も表示されなければ、

  • 本当に止まっているのか分からない
  • どうやって再開すればいいか迷う

という状態になってしまいます。

ここでは、 ポーズメニュー用のUIを作り、PauseManagerと連携する ところまでを解説します。


① CanvasとPanelを作成する

まずはポーズメニュー用のUIを配置するための土台を作ります。

Hierarchyウィンドウを右クリックして、

「UI」→「Canvas」

を選択してください。

Canvasが作成されたら、その子オブジェクトとして、

「UI」→「Panel」

を追加します。

この Panel が、 ポーズ中に表示されるメニュー全体になります。


② テキストとボタンを配置する

次に、Panelの中に必要なUI要素を配置していきます。

  • 「PAUSED」などのテキスト
  • 再開用のボタン(Resume)
  • 終了用のボタン(Quit)

最低限、このあたりがあれば十分です。

UIの見た目は、 ゲームの印象を大きく左右するポイントなので、

「自分で作るのが大変だな…」 「それっぽいデザインにしたいな…」

と感じたら、 既製のUIアセットを使うのも全然アリですよ。

特に、カジュアルゲーム系のポーズメニューなら、 こちらのアセットはかなり使いやすいです👇

GUI Pro – Casual Game

✅Unityアセットストアでチェックする

ボタンやパネルが一式そろっているので、 配置するだけで「ちゃんとしたゲーム感」が出ます 😊


③ ポーズメニューを初期状態で非表示にする

次に、とても重要な設定です。

ポーズメニューは、 ゲーム開始時は表示されていてはいけません

そのため、Hierarchy上で

ポーズメニュー用の Panel(または Canvas)を非アクティブ

にしておきます。

チェックボックスをオフにするだけでOKです。


④ PauseManagerからUIを制御する

次に、スクリプトからUIを操作できるようにします。

PauseManagerに、 ポーズメニュー用のGameObjectを参照する変数を追加しましょう。


[SerializeField]
GameObject pauseMenuUI;

Inspector上で、 先ほど作成した Panel(または Canvas)を この変数にドラッグ&ドロップします。

そして、ポーズ/再開のメソッドを少しだけ修正します。


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

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

これで、

  • ポーズ時にメニュー表示
  • 再開時にメニュー非表示

が自動で切り替わるようになりました。


⑤ ボタンとスクリプトを紐付ける

最後に、UIのボタンとスクリプトをつなげます。

Resumeボタンを選択し、 Inspectorの Button コンポーネントにある

On Click()

に、PauseManagerをアタッチします。

そして、関数として

ResumeGame()

を指定してください。

これで、

  • Escapeキーでポーズ
  • ボタンで再開

という、実用的なポーズメニューが完成です 🎉

ただし、この段階でもまだ完璧ではありません。

次は、👉 「Time.timeScaleだけでは足りない理由」 を、実際に起こりがちなトラブルと一緒に見ていきましょう。




5. Time.timeScaleだけでは足りない理由(よくある落とし穴)

ここまでで、

  • Time.timeScale を使ったポーズ切り替え
  • ポーズメニューUIの表示・非表示

は一通り実装できました。

「もうこれで完成でしょ?」 と思いたくなるところですが…… 実はここからが本番です 😅

実務や公開レベルのゲームでは、 Time.timeScale だけに頼ったポーズ実装は、 ほぼ確実に問題を引き起こします。


落とし穴① Update内の処理が動き続ける

何度も出てきていますが、 Update() はポーズ中でも止まりません

たとえば Update の中に、

  • プレイヤー入力
  • 状態遷移
  • フラグの切り替え

が書かれていると、

見た目は止まっているのに、内部の状態だけ進む

という非常に厄介な状態になります。

これが原因で、

  • ポーズ解除後に突然ワープする
  • 敵の状態が壊れる

といった「再現しづらいバグ」が生まれます。


落とし穴② オーディオが止まらない

Time.timeScale は、

オーディオの再生には影響しません

そのため、

  • BGMが鳴り続ける
  • 環境音だけ流れ続ける

といった状態になります。

「ポーズなのに音が鳴っている」という違和感は、 体験としてかなりマイナスです。


落とし穴③ アニメーションが止まらない/止まり方がおかしい

Animator や Tween 系のアニメーションは、

  • 設定次第で timeScale の影響を受ける
  • 逆に影響を受けないものもある

という、少しややこしい挙動をします。

結果として、

  • キャラだけ固まってUIは動いている
  • 一部の演出だけ止まらない

といった「チグハグなポーズ」になりがちです。


落とし穴④ Rigidbody再開時の挙動が不自然になる

物理演算を使っているゲームでは、 ポーズ解除時に

  • 急に勢いよく動き出す
  • 位置がズレる

といった現象が起きることがあります。

これは、

時間が止まっている間に「力」や「状態」が溜まる

ことが原因です。


落とし穴⑤ シーン遷移時のtimeScaleリセット忘れ

これも本当に多いミスです。

ポーズ中にシーンを切り替えた結果、

次のシーンが最初から止まっている

という事故、かなりの確率で一度は経験します…。

Time.timeScale は 自動では元に戻らない という点を、必ず覚えておきましょう。


ここまで読んで、

「じゃあ、どうすればいいの?」 「全部自分で止めるしかないの?」

と思った方、大丈夫です 😊

次の章では、

👉 これらの問題を一つずつ解決する実践テクニック を、具体例付きで解説していきます。

ポーズ実装は、 ここから一気に「プロっぽく」なっていきますよ ✨




6. 各要素を正しく止める実践テクニック

ここからは、前の章で挙げた

  • Updateが止まらない問題
  • 音が鳴り続ける問題
  • アニメーションが制御できない問題

を、ひとつずつ確実に解決していく方法を解説していきます。

「全部まとめて止める」ではなく、 役割ごとに正しく制御するのがポイントです ☝️


6-1. Update内の処理を安全に止める方法

まず最優先で対処すべきなのが、 Updateがポーズ中も動き続ける問題です。

一番シンプルで、かつ事故が少ない方法は、 Updateの冒頭で早期リターンする書き方です。


void Update()
{
    if (isPaused) return;

    // ここから下に通常時の処理を書く
}

これだけで、

  • 入力処理
  • 状態更新
  • ゲームロジック

を、ポーズ中にまとめて無効化できます。

「Updateが止まらない」というUnityの仕様を、 コード側で正しく受け止めるイメージですね。

規模が大きくなってきたら、

  • PauseManager.Instance.IsPaused を参照する
  • 共通の基底クラスで制御する

といった設計に進化させるのもおすすめです。


6-2. オーディオを正しく停止・再開する

次は、ポーズ中も鳴り続けてしまう音の問題です。

Unityでは、 Time.timeScale はオーディオに影響しないため、

音は明示的に止める必要があります。

代表的な方法は、次の2つです。

  • AudioListener.pause を使う方法
  • AudioSource を個別に Pause / UnPause する方法

一括で止めたい場合は、こちらが一番シンプルです。


AudioListener.pause = true;   // ポーズ時
AudioListener.pause = false;  // 再開時

これだけで、 シーン内のすべての音をまとめて停止できます。

一方で、

  • UIのクリック音だけ鳴らしたい
  • 環境音は止めたくない

といった場合は、 AudioSource を個別に管理する方法が向いています。

オーディオ制御の基本や考え方については、 こちらの記事もあわせて読むと理解が深まります👇


6-3. アニメーション・Tweenを正しく制御する

最後に、アニメーション周りです。

Animator を使っている場合、 ポーズ時に一番手軽なのは

animator.speed = 0

にする方法です。


animator.speed = 0f; // ポーズ
animator.speed = 1f; // 再開

これで、 キャラクターや演出用アニメーションを 確実に停止できます。

ただし問題になるのが、

  • ポーズ中も動かしたいUIアニメーション
  • フェード演出やボタンの強調表示

といったケースです。

ここで活躍するのが、 Tween系ライブラリ、特にDOTweenです。

DOTweenでは、

  • timeScaleの影響を受けるTween
  • 影響を受けないTween

を明確に分けて扱うことができます。

ポーズ中もUIアニメーションを動かしたい場合は、 UpdateTypeをUnscaledに設定するだけでOKです。

実務レベルのポーズ演出を作るなら、 DOTween Proはほぼ必須と言っていい存在です👇

DOTween Pro

✅Unityアセットストアでチェックする


ここまでで、

  • ロジック
  • アニメーション

個別に、かつ安全に止める方法が揃いました。

次は、 👉 さらに拡張性の高い「設計としてのポーズ管理」 について解説していきます。

中〜大規模開発を見据えるなら、 ここからが本当に重要です 😊




7. 一歩進んだ設計:拡張性の高いポーズ管理

ここまでの実装で、 「ちゃんと動くポーズ機能」は完成しました。

ただし、ゲームの規模が少し大きくなると、

  • スクリプトごとに isPaused を参照している
  • PauseManager に処理が集まりすぎる
  • 後から機能追加すると破綻しそう

といった設計面の不安が出てきます。

ここでは、 中〜大規模開発でも破綻しにくいポーズ設計を紹介します。


7-1. ポーズは「イベント」として扱う

まず考え方を一段階レベルアップさせましょう。

ポーズは、

「PauseManagerが全部止める」ものではなく、
「ポーズが発生したことを通知するイベント」

として扱うのが理想です。

つまり、

  • PauseManager は「今ポーズになったよ」と知らせるだけ
  • 各オブジェクトは自分で止まり方を決める

という責務分離を行います。


7-2. インターフェース(IPausable)を使う設計

よく使われる方法が、 ポーズ用インターフェースを定義するやり方です。


public interface IPausable
{
    void OnPause();
    void OnResume();
}

ポーズが必要なクラスは、 このインターフェースを実装します。


public class EnemyController : MonoBehaviour, IPausable
{
    public void OnPause()
    {
        // AI停止処理
    }

    public void OnResume()
    {
        // AI再開処理
    }
}

PauseManager 側では、

  • IPausable を実装しているオブジェクトを管理
  • ポーズ時に一括で OnPause() を呼ぶ

だけで済みます。

これにより、

  • 新しい機能を追加しても既存コードを壊しにくい
  • 止め方がオブジェクトごとに最適化できる

というメリットがあります。


7-3. イベント駆動(Observerパターン)でさらに柔軟に

もう一段階洗練された方法が、 イベント駆動でポーズを管理する設計です。

PauseManager が、

  • ポーズ開始イベント
  • ポーズ解除イベント

を発行し、 各オブジェクトがそれを購読します。

この形にすると、

  • PauseManager は存在を知らなくていい
  • 依存関係が一方向になる

という、かなり強い設計になります。

イベントやActionを使った設計については、 こちらの記事がとても参考になります👇


7-4. シングルトンPauseManagerは「使いどころ」を選ぶ

PauseManager をシングルトンにするのも、 選択肢としてはアリです。

特に、

  • 小〜中規模ゲーム
  • 個人開発

では、

PauseManager.Instance.IsPaused

を参照するだけで済むのは、とても楽です。

ただし、

  • どこからでもアクセスできてしまう
  • 責務が肥大化しやすい

というデメリットもあるので、 「便利だから」だけで選ばないのが大切です。


ここまでで、

  • 実装としてのポーズ
  • 設計としてのポーズ

の両方が見えてきたと思います。

次は、 👉 シーン遷移や外部アセット使用時の注意点 をまとめて確認していきましょう。

ここを押さえておくと、 「なぜか止まる/動かない」事故をほぼ防げますよ 😊




8. シーン遷移・外部アセット使用時の注意点

ポーズ機能が一通り完成しても、 実際のゲームでは「想定外の場面」が必ず出てきます。

特にトラブルが起きやすいのが、

  • シーン遷移を伴う場合
  • 外部アセットやライブラリを使っている場合

この章では、 実務でよく起きる事故ポイントをまとめて確認していきましょう。


8-1. シーン遷移時は必ずTime.timeScaleをリセットする

何度も触れていますが、 これは本当に重要なので改めて書きます。

Time.timeScale は、

シーンをロードしても自動では元に戻りません

そのため、

  • ポーズ中にタイトルへ戻る
  • ポーズ中にリトライする

といったケースでは、 次のシーンが最初から止まったままになります。

これを防ぐために、

  • シーン遷移前
  • シーン開始時(Awake / Start)

のどちらかで、必ず


Time.timeScale = 1f;

を実行するクセをつけましょう。

特にタイトルシーンやリトライ処理では、 「保険」として必ず書くのがおすすめです。


8-2. ポーズ中にシーンを切り替える設計に注意

ポーズメニューには、よく

  • 「タイトルへ戻る」
  • 「ステージ選択へ」

といったボタンが用意されます。

このとき注意したいのが、

ポーズ解除 → シーン遷移

の順番です。

いきなりシーンをロードするのではなく、

  1. ポーズを解除する
  2. timeScaleを1に戻す
  3. シーンをロードする

という流れを、 必ず1セットにしておきましょう。

これを関数化しておくと、 事故がかなり減ります。


8-3. 外部アセットは「timeScaleの影響」を必ず確認する

外部アセットやライブラリを使っている場合、 もうひとつ気をつけたいのが、

そのアセットが timeScale の影響を受けるかどうか

です。

特に、

  • Tween系
  • 演出用アニメーション
  • UIエフェクト

は、設定によって挙動が大きく変わります。

たとえば DOTween では、

  • 通常のTween → timeScaleの影響を受ける
  • Unscaled設定 → ポーズ中も動く

と、明確に切り分けられています。

ポーズ中に

  • UIだけ動かしたい
  • 演出は完全に止めたい

といった要件がある場合は、 どの処理がどの時間軸で動いているかを 必ず意識しましょう。


8-4. ポーズ中の入力処理にも注意する

UIが表示されている間でも、

  • ゲーム用の入力
  • ショートカットキー

が反応してしまうことがあります。

これを防ぐために、

  • ポーズ中は入力処理をスキップする
  • UI操作専用の入力だけ通す

といった制御を入れておくと安心です。

特に新Input Systemを使っている場合は、 Action Mapの切り替えを使うと、 かなりスマートに制御できます。




まとめ

ここまで、Unityで「一時停止(ポーズ)」を正しく実装する方法を、 基礎から実践・設計まで順番に解説してきました。

最後に、この記事で特に大切だったポイントを振り返っておきましょう。

  • Time.timeScale = 0 は「万能な停止スイッチ」ではない
  • Updateは止まらないため、コード側で明示的な制御が必要
  • 音・アニメーション・UIは個別に止め方を考える
  • ポーズは「時間制御」+「状態管理」の問題

Unityのポーズ実装でつまずく原因の多くは、 「全部まとめて止めようとする」発想にあります。

そうではなく、

「何を止めて、何を止めないのかを設計する」

という視点を持つことで、 バグが減り、拡張もしやすいコードになります。

私自身も、最初は Time.timeScale = 0 だけで済ませて 何度も痛い目を見てきました…😅 でも、仕組みを理解してからは、 ポーズ実装が一気に怖くなくなりました。

この記事の内容をベースにすれば、

  • 小規模な個人ゲーム
  • UIや演出にこだわった作品
  • 後から機能追加する前提のプロジェクト

どれでも安心して使えるポーズ機能が作れるはずです。

ぜひ、ご自身のプロジェクトに合わせて 「ちょうどいい設計」を選んでみてくださいね 😊


よくある質問(FAQ)

Q
Time.timeScaleを0にすればゲームは完全に止まりますか?
A

結論から言うと、完全には止まりません

Time.timeScale = 0 は、

  • 物理演算
  • FixedUpdate()
  • Time.deltaTime を使った処理

を止めるだけで、

  • Update() 自体
  • UI操作
  • Time.unscaledDeltaTime を使った処理

動き続けます

そのため、 Update内の処理を自分で止める制御や、 音・アニメーションの個別制御が必要になります。

Q
ポーズ中もUIアニメーションだけ動かしたい場合はどうすればいい?
A

このケースでは、

timeScaleの影響を受けない時間軸を使う

のが基本方針です。

  • Time.unscaledDeltaTime を使う
  • DOTweenなどで Unscaled Update を指定する

といった方法があります。

特に DOTween を使っている場合は、

  • ゲーム本体の演出 → 通常のTween
  • ポーズUIの演出 → Unscaled Tween

と分けるだけで、 自然なポーズ演出が作れます。

Q
小規模なゲームでもイベント方式やインターフェースは必要?
A

必須ではありません。

個人制作や小規模ゲームであれば、

  • PauseManager + bool管理
  • Update冒頭での早期return

だけでも、十分に安定したポーズは作れます。

ただし、

  • あとから機能追加する予定がある
  • 敵・ギミック・演出が増えそう

という場合は、 早めにイベント駆動やIPausable設計にしておくと、 後でかなり楽になります。

「今はシンプルに、将来は拡張しやすく」 このバランスを意識して選ぶのがおすすめです 😊

※当サイトはアフィリエイト広告を利用しています。リンクを経由して商品を購入された場合、当サイトに報酬が発生することがあります。

※本記事に記載しているAmazon商品情報(価格、在庫状況、割引、配送条件など)は、執筆時点のAmazon.co.jp上の情報に基づいています。
最新の価格・在庫・配送条件などの詳細は、Amazonの商品ページをご確認ください。

スポンサーリンク