ゲームをプレイ中に何か用事で招集されたりした場合は、一般的にはゲームを中断すると思います
対戦ゲームなどリアルに対戦相手がいるゲームの場合は、相手に待ってもらうか勝ちを譲る
必要がありますが
しかし、ソロプレイの場合はゲームの進行を待ってほしいものです
それがアクション性の強いゲームの場合はなおさらのことです
その場合に備えて今回は、Unityで一時停止機能の導入と注意点を見ていきたいと思います
コンテンツ
導入方法

実装方法はいくつかありますが、
簡単な方法としてUnityのタイムスケールを0にする方法があります
Time.timeScale = 0.0f;
こうすることでゲームの時間が止まります
今回は0にしてますが、0.5などにするとスローモーションするなどの芸当も可能です
ただし、基本的なものはこれでゲームが止まりますがいくつか弊害があるので、
そのあたりの対応の必要となってきます
対応する必要があるものは
- Updateは毎フレーム呼ばれる
- アニメーションが停止する
- サウンドは停止しない
これらの対応が必要があります
Updateが呼ばれる問題を対応する

Updateが呼ばれる問題の対応を見ていきたいと思います
初めにUpdateが呼ばれたら問題になる点としては、
- 当たり判定の処理をしている場合
一時停止してても当たり判定を続けるため、
プレイヤーなどのキャラクターがいつの間にか死んでいる可能性がある
- 移動処理がTransform.postionに直に入れている場合
一時停止中にも移動する
- オブジェクト生成している場合
一時停止中にもかかわらず生成し続ける
等々いろいろ問題があります。
これを解決する方法としては、Updateの直前で処理を止める方法がシンプルです。
public static bool isPause = false;
void Update()
{
if(isPause)
{
return;
}
// 何かの処理
}
// 一時停止
public void Pause()
{
Time.timeScale = 0.0f;
isPause = true;
}
// 再開
public void Resume()
{
Time.timeScale = 1.0f;
isPause = false;
}
こうすることでUpdateを止めることができますが、Updateが複数ある場合は必要な個所すべてに
この処理を入れる必要が出てきますので、
一時停止機能を入れる予定であればUpdateは極力使用しないようにしましょう
また、アセットストアなどを使用している場合はUpdateを使用していないか確認は必須です
どうしてもUpdateを使いたい場合はこうしましょう
↓オブジェクト
public class MonoBehaviorEX : MonoBehavior
{
// 更新処理
public void DoUpdate()
{
// 何かの処理
}
}
↓Updateを処理するコントローラ
こうすることでUpdateを疑似的に呼ぶことが可能で一時停止の対応が可能となります
public void List<MonoBehaviorEX> m_objects = new List<MonoBehaviorEX>();
void Update()
{
if(isPause)
{
return;
}
foreach(var tmp in m_objects)
{
tmp.DoUpdate();
}
}
アニメーションが停止する問題を解決する

引き続きアニメーションが停止する問題を見ていきたいと思います
アニメーションが停止するのは一見問題ないように見えますが、
一時停止画面に表示するUIのアニメーションも停止します
ですので、一時停止中にも動いてほしいアニメーションすら停止することになるので、
その対処が必要になります
対応方法はいたってシンプル
AnimatorのUpdateModeをNormalから

UnScaledTimeに変更します。

こうすることで一時停止中にもアニメーションが機能するようになりますが
こうするとタイムスケールが効かなくなる欠点もあるので必要最低限にしましょう
サウンドが停止しない問題を解決する

最後にサウンドが停止しない問題を見ていきたいと思います
サウンドが停止しない問題点としてSEが再生途中で一時停止が行われた場合に問題が起きます
具体的には
- 一時停止中にSEが再生される
- 再開したときにSEの再生タイミングがずれる
- 再開したときにSEの再生が終わっている場合、無音の発射エフェクト等などの違和感が発生する
対応方法は以前作成したボリューム制御のスクリプトに
新しく一時停止の処理の追加を行います
使うのはこちら、オーディをの再生を一時停止する機能を用います
Audio.Pause();
↓再開する
Audio.UnPause();
実際に使用する
/// <summary>
/// SEの一時停止
/// </summary>
/// <param name="isPause">true: 一時停止 false: 再開</param>
public void PauseSE(bool isPause)
{
foreach(var tmp in m_changers.Where((a) => a.Value.VolumeType != VolumeType.Bgm))
{
if(isPause)
{
tmp.Value.Audio.Pause();
}
else
{
tmp.Value.Audio.UnPause();
}
}
}
これを一時停止のタイミンや再開のタイミングで呼び出すことでSEのタイミングを担保しつつ
SEの一時停止、再開を行うことができるようになります
まとめ
一時停止はアクション性の高いゲームではほとんど必須といってもいいものです
ただし、ゲームの時間を止めるの意外と苦労のいる作業です
特に一時停止を念頭に置いていないゲームに一時停止機能を入れる場合は更に難易度が上がります
ですので、ゲームの自作する場合はこのことも念頭に入れて開発していきましょう
コメントを残す