自作ゲームに一時停止機能を導入する方法と注意点

ゲームをプレイ中に何か用事で招集されたりした場合は、一般的にはゲームを中断すると思います

対戦ゲームなどリアルに対戦相手がいるゲームの場合は、相手に待ってもらうか勝ちを譲る

必要がありますが

しかし、ソロプレイの場合はゲームの進行を待ってほしいものです

それがアクション性の強いゲームの場合はなおさらのことです

その場合に備えて今回は、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の一時停止、再開を行うことができるようになります

まとめ

一時停止はアクション性の高いゲームではほとんど必須といってもいいものです

ただし、ゲームの時間を止めるの意外と苦労のいる作業です

特に一時停止を念頭に置いていないゲームに一時停止機能を入れる場合は更に難易度が上がります

ですので、ゲームの自作する場合はこのことも念頭に入れて開発していきましょう


コメントを残す

メールアドレスが公開されることはありません。

ABOUT US
vuniformity誰でもない人
トレンドの行く末を見守っている
仮名を名乗るエンジニア

ゲーム開発は仕事であり趣味である
プログラムだけでなく多種多様なスキルを数多く持つ

ゲーム開発は
ソーシャルゲームを開発運用の経験アリ
ゲーム以外にも経験アリ
Webサービス保守開発等に携わる

ゲームプレイの主な戦場は
FGO
FEH
MTGA
マビノギ
ここでは主にunityroomで公開しているゲーム作り直しの軌跡を綴っていきます