【Unity】2Dシューティングを作ってみる話 #17

記事をご覧いただき、誠にありがとうございます。
投稿主の無能です。

前回は、BGMとSEを現状で付けられるものを設定しました。

今回はゲームの中断とコンティニューを実装したいと思います。

ゲームの中断

ゲームの中断は、所謂ポーズ機能になります。

ゲームの最中に離れる事があった場合、ポーズ機能が無いとアクションやシューティングだとゲームオーバー必至なので、今回のゲームにポーズ機能はほぼ必須と言っても良いでしょう。

ではゲームの中断を実装していきます。

ゲームの中断を知らせるUIを作成する

一口に中断と言っても、中断していることが分かるようにしないといけないので、UIを作成してユーザーにゲームが中断していることを知らせるようにします。

ではCanvasを作成し「GameStatus」という名前にします。

「GameStatus」という名前のCanvasを新規作成する

Canvasは既に存在していますが、先に作成したCanvasはAndroidデバイスでのコントロール関連をまとめたものなので、区別出来るように新規作成しています。

そしてこのCanvasに子オブジェクトで空のオブジェクトを作成し、名前を「Pause」にします。

Canvasに「Pause」という名前の子オブジェクトを作成する

これはフォルダ整理に近いもので、GameStatusにはコンティニューの際のUIも入るので、このようにしてあります。

では中断の画面表示部分を作っていきます。

フォントアセットを作成する

今回はUI用にフォントアセットを作成していきますので、フォントを探します。

少しシャープ印象にしたいと思うので、無能はこちらのフォントにしました。
※二次配布に抵触する可能性があるため、リンク先を参照してください。

Rajdhani - Google Fonts

Assetsフォルダ内に「Fonts」フォルダを作成し、フォントをインポートします。

Assetsフォルダ内に「Fonts」フォルダを作成しフォントをインポートする

今回は日本語は使わないので、英数字のみでフォントアセットを作成します。

Window > TextMeshPro > Font Asset Creator でフォントアセット作成画面を表示します。

Window > TextMeshPro > Font Asset Creator でフォントアセット作成画面を表示

フォントアセット作成画面

先程インポートしたフォントをSource Font Fileに設定します。

インポートしたフォントをSource Font Fileに設定する

次にPacking MethodをOptimumに、Atlas Resolutionをどちらも8192にします。

Packing MethodをOptimumに、Atlas Resolutionをどちらも8192にする

そしてCharacter SetをASCIIにするとGenerate Font Atlasが有効になるので押します。

Character SetをASCIIにしてGenerate Font Atlasを押す

するとフォントアトラスの作成結果が表示されます。

フォントアトラスの作成結果が表示される

テキストで結果が表示されて、作成時に失敗した文字が1文字あったようです。

空白を表す記号化か代替文字かと思いますが、特に必要ありませんので大丈夫です。

フォントアトラスの作成結果では、このように作成に失敗した文字が出るので、要・不要を確認するようにしてください。

ではSaveボタンを押してこのフォントアトラスを保存します。

Saveボタンを押して作成したフォントアトラスを保存

すると保存先を指定しますが、インポートしたFontsフォルダにします。

インポートしたFontsフォルダを保存先に指定

無事作成できました。

フォントアセット作成画面はもう不要なので閉じます。

フォントアセットが作成できた

ではこのフォントアセットを使ってUIを作成します。

ゲームの中断(ポーズ)のUIを作成する

では準備が出来たので中断のUIを作成します。

どのようなUIにするかは皆さん次第ですが、ポーズを表示するのとあわせて、ゲームを続けるかどうかの確認が出来れば良さそうです。

ではそのようにUIを作りましょう。

まずはPauseを表示するテキストを作成します。

GameObject > UI > Text - TextMeshPro からテキストを作成し、名前を「Text_pause」にしたら、Pauseの子オブジェクトにします。

作成したUIから見ると孫オブジェクトになります。

GameObject > UI > Text - TextMeshPro で「Text_pause」を作成し、Pauseの子オブジェクトにする

そしてText Inputで表示するテキストをPauseにします。

Text Inputで表示するテキストをPauseにする

このままだと見辛いので、位置とサイズを変更して視認出来るようにします。

サイズ・位置を調整

Scene・Gameビュー

辛うじて見えましたね。

後はフォントサイズとフォントの配置を調整します。

無能はこのように設定しました。

Text_Pauseの設定全体

まる、フォントアセットを先程作成したものにして、Alignmentで中央揃えにしました。

そしてFont Sizeを200にして視認出来るようにした上でRect Transformを変更して、この状態にしました。

UIの設定は類似の作業が続くので、この辺りの作業については簡略化させてください。

Gameビューの位置を見てみてると中々良いポジションなので、このPauseの下に「Continue?」と表示させます。

要は中断した時にゲームを続けるかを尋ねるようにします。

同じ様に「Text_Continue」を作成してPauseの子オブジェクトにします。

「Text_Continue」を作成してPauseの子オブジェクトにする

Text_Continueの設定

Text_Continueの設置

そして続行するか答えるボタンとして、Continueの下にボタンを配置します。

GameObject > UI > Button - TextMeshPro からボタンを作成し、名前を「Button_Yes」とします。

GameObject > UI > Button - TextMeshProから「Button_Yes」という名前のボタンを作成

そしてContinueの左下に配置して、ボタンの文言を「Yes」にします。

Button_Yesの設定

Button_Yesの配置

何か文字が見にくくなっていますが、UIを作り終わってから原因を調べましょう。

Button_Yesを複製して「Button_No」にしてYesの右側に配置します。

Button_Noの設定

Button_Noの配置

これで中断のUIが一通りできました。

それにしても文字全体が霞んでいるようになっています。

これは文字の太さの拡縮の値のDilate値を0に、文字をくっきりさせるSharpnessを1にするとはっきりと文字が表示されます。

どちらの項目もシェーダーマテリアルの項目になります。

シェーダーマテリアルの項目のDilate値を0に、Sharpnessを1にする

大分霞みが取れた

まだボタンの文字を見ると霞んでいます。

Gameビューの方を見ると問題無く見えるのですが、気になる場合はGradient Scaleをいじってみてください。

今回は大体9くらいにすると霞みが取れると思います。

Gradient Scaleを9にする

霞みが取れた

ただGradient Scaleは、最後の手段にしておくことをお勧めします。

この値が大幅に変わると、文字の表示がおかしくなる場合があるので、今回のような場合はDilateとSharpnessのみで対応した方が良いみたいです。

では処理を実装します。

スクリプトを追記する

中断の処理はゲーム全体の処理なので、GameManagerスクリプトに追記します。

こうなります。

GameManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    [SerializeField] GameObject ShotButton;     // 画面上の発射ボタン
    [SerializeField] GameObject UI_Pause;       // ゲーム中断のUI

    int pause = 0, pauseRelease = 1;            // ゲーム中断時のタイムスケール

    void Start()
    {
#if PLATFORM_STANDALONE_WIN
        ShotButton.SetActive(false);
#endif
    }

    void Update()
    {
        // Escキーが押された場合
        if (Input.GetKey(KeyCode.Escape))
        {
            // ゲーム中断のUIをアクティブ
            UI_Pause.SetActive(true);
            // ゲーム中断処理
            GamePause();
        }
    }

    // ゲーム中断
    void GamePause()
    {
        // タイムスケールを0にする
        Time.timeScale = pause;
    }

    // ゲーム中断解除
    public void GamePauseRelease()
    {
        // タイムスケールを1にする
        Time.timeScale = pauseRelease;
        // ゲーム中断のUIを非アクティブ
        UI_Pause.SetActive(false);
    }

    // ゲーム終了
    public void GameExit()
    {
        // アプリケーションを終了する
        Application.Quit();
    }
}
では見ていきましょう。

メンバ変数にUI_Pauseという、先程作成した中断画面の親オブジェクトを追加しています。

そしてタイムスケールの管理用にpauseとpauseReleaseを用意しています。

Update関数内にEscキーが押されたらというif文からUI_Pauseをアクティブにします。

UI_Pauseは非アクティブにしておいて、このタイミングでアクティブになります。

そしてGamePause関数を呼んでいます。

GamePause関数はタイムスケールを0にします。

デフォルトは1で、これが普段のゲーム速度になります。

ここでタイムスケールと言うのは、ゲーム内時間の流れの速さを表すもので、タイムスケールが0になることでゲームが中断される、という事になります。

Time.timeScale - Unity Documentation

ただ万能と言うわけではなく、タイムスケールを0にしても止まらないものもあるので注意してください。

UIを表示した後の操作はYes・Noボタンでの操作になります。

GamePauseRelease関数ではタイムスケールを通常の1に戻した後に、UIが出しっぱなしになるのでUI_Pauseを非アクティブにしています。

こちらがYesボタンの処理になります。

GameExit関数ではアプリケーションを終了します。

こちらがNoボタンの処理になります。

ではGameManagerオブジェクトで設定しましょう。

GameManagerオブジェクトの設定

先程のスクリプトでGameManagerオブジェクトに追加された項目を設定します。

まずはPauseを非アクティブにします。

すると子オブジェクト達も非アクティブになります。

Pauseを非アクティブにする

子オブジェクト達も非アクティブになる

次にGameManagerオブジェクトで、非アクティブにしたPauseをUI_Pauseに設定します。

GameManagerオブジェクトでPauseをUI_Pauseに設定する

次はYesボタンです。

OnClickに項目を追加し、オブジェクト選択画面でSceneからGameManagerを選択します。

そして呼び出す関数をGamePauseReleaseにします。

YesボタンのOnClick設定

同様にNoボタンも設定します。

呼び出す関数はGameExitです。

NoボタンのOnClick設定

ではゲームを実行して確認します。

Noボタンのアプリケーションを終了する処理は、アプリをビルドしないと確認出来ないので、アプリをビルドしたら各デバイスで確認します。

Yesボタンを押したら通常のゲームの流れに戻るかを確認します。

Escキーでゲームが中断された

Yesボタンを押すとUIが消えてゲームが再開された

ゲームの中断がこれで実装出来ました。

コンティニューの実装は、長くなってしまったので次回に回します。

まとめ

今回は
  • ゲームの中断を実装した
という事をやりました。

次回はコンティニューの実装になります。

では、また次回!

コメント