LessonEX ポーズ画面
EX-1 ポーズ画面の実装
ポーズ画面と言うと実装が困難なイメージがあるかもしれませんが、Unityでは比較的簡単に実装することができます。
UnityにはTimeScaleという「現実時間と比較したUnity内の時間の尺度」を表すパラメータがあります(言葉にするとわかりにくいかもしれないですね…)
TimeScaleが1.0の時は現実と同じ速度でUnity内の時間が流れます。ですが、TimeScaleを2.0にするとゲーム内の時間は現実の2倍の速度で流れるようになります。そして、TimeScaleを0.0にするとUnity内の時間の流れは停止します。このTimeScaleを用いることでゲームの一時停止や倍速、スロー演出などを簡単に実装することができるのです。
それでは簡単なポーズ機能を実装してみましょう。ここでは3Dアクションゲーム編の完成版に実装していきます。
新しいスクリプトGamePauseを追加して、以下のように入力してください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GamePause : MonoBehaviour
{
bool m_isPause = false; // ポーズ中かどうか
void Update()
{
// キーボードのPキーが押されたら…
if (Input.GetKeyDown(KeyCode.P))
{
if (m_isPause)
{
// ポーズ解除
Time.timeScale = 1.0f;
}
else
{
// ポーズする
Time.timeScale = 0.0f;
}
// フラグを切り替える
m_isPause = !m_isPause;
}
}
}
コードが書けたら保存して、適当な空オブジェクトにアタッチしてみてください。
空中でPキーを押して、落下が一時停止することを確認してみてください。ポーズ中にPキーを押すと再び動き出します。
TimeScaleを0.5にして減速したり、2.0にして倍速にしたりできます。試してみてください。

ただしTimeScaleで止まるものと止まらないものがあります。
まず、画像のようにRigidBodyなどの物理演算は止まります。重力やAdd Forceなど、全ての処理が停止します。停止中にAdd Forceが実行された場合、停止が解除された瞬間に移動が始まります。
アニメーションの処理も停止します。TimeScaleに影響を受けてほしくない場合、AnimatorのUpdate ModeをUnscaled Timeに変更すると停止しなくなります。

逆に止まらないのはUpdate関数です。Update関数まで止まってしまうと、ポーズ画面を解除することができなくなってしまいます。ポーズ画面を解除する処理や、ポーズ中に実行したい処理はUpdate関数に書くようにしましょう。
(同じようにLateUpdate関数も止まりません)
FixedUpdate関数は止まります。FixedUpdate関数内にポーズ中に実行したいプログラムを書いても動作しないので注意してください。

もしポーズ中にUpdate関数を止めたい場合は、シンプルにフラグで管理しましょう。
GamePauseスクリプトに赤い部分のコードを追加してください。
~前略~
public class GamePause : MonoBehaviour
{
static public bool m_isPause = false; // ポーズ中かどうか
void Update()
{
~後略~
あとはポーズ中に処理を止めたいUpdate関数内に「ポーズ中なら処理を中断する」if文を書くだけで、ポーズ中でもUpdateを止めることができます。
~前略~
void Update()
{
// ポーズ中ならこの先の処理をしない
if (GamePause.m_isPause)
{
return;
}
// ここで移動の処理などを行う
~後略~
これでポーズ中にUpdate関数が実行されようとしてもすぐ中断されるようになりました。
staticに設定した変数はシーンが切り替わってもゲームが終了するまで残り続けます。その性質上、ゲーム内に同じ名前の変数は複数存在できないので注意してください。
せっかくなので、ポーズ中だとわかりやすいように装飾しましょう。
新しいCanvasを追加してください。

既存のUI用Canvasと区別できるように名前をつけてください。
CanvasのSort Orderを既存のUI用Canvasの値より大きくしてください。Sort Orderは描画の優先度で、値が大きい方が後(前面)に描画されることになります。
UI Scale Modeは既存のUI用Canvasと同じようにしておきましょう。

PauseCanvas下にポーズ中に表示するUIを追加しましょう。
今回は適当に半透明の黒い背景と「Pause」のテキストを追加しています。

ポーズ用Canvasを非アクティブにしましょう。名前の横のチェックを外すとオブジェクトが非アクティブになり、表示されなくなります。
非アクティブにしたオブジェクトは描画や更新は行われませんがシーン内には存在しており、アクティブにすることですぐに有効化することができます。

後はポーズの状況でポーズ用Canvasのアクティブと非アクティブを切り替えるだけです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GamePause : MonoBehaviour
{
static public bool m_isPause = false; // ポーズ中かどうか
public GameObject PauseCanvasObject; // ポーズ用Canvas
void Update()
{
// キーボードのPキーが押されたら…
if (Input.GetKeyDown(KeyCode.P))
{
if (m_isPause)
{
// ポーズ解除
Time.timeScale = 1.0f;
PauseCanvasObject.SetActive(false);
}
else
{
// ポーズする
Time.timeScale = 0.0f;
PauseCanvasObject.SetActive(true);
}
// フラグを切り替える
m_isPause = !m_isPause;
}
}
}
PauseCanvasObjectをpublicにしているので、先ほど作成したPauseCanvasをインスペクターに設定するのを忘れないようにしてください。

これでポーズ中だけポーズ用Canvasが表示されるようになりました。
アニメーションを追加したり、ステージを抜けるボタンを追加したりなど色々活用できると思います。ぜひゲームに実装してみてください。
タイマーの実装や移動処理で活躍するTime.deltaTimeですが、TimeScaleの値を変更するとTime.deltaTimeも影響を受けてしまいます。
TimeScaleの影響を受けずに1フレームごとの間隔を取得したい場合 Time.unscaledDeltaTimeというパラメータを使用してください。
Unity Tips!

