Android
Unity
アプリ内課金
ゲーム制作

Unity でブロック崩しを作る際のステージ選択機能の仕組み

この記事では、Unity でブロック崩しを作る際のステージ選択機能の仕組みについて紹介します。

itemstore BLOG で連載している
【いますぐ始めるアプリ内課金】第5回:ブロック崩しを完成させる(アプリ内課金なし)
の補足になりますので、併せてお読みください。

なお、このブロック崩しは、 Android 4.2 以降のスマホで実際にプレイできます。

GooglePlay

QRコード

ステージ選択ボタンの使い方と簡単な仕組みについて

前述のブログで公開している教材プロジェクトを改造して、ステージを増やすための手順を説明します。
大きな流れは、

  • 新たなステージとなるシーンを追加
  • 前ステージのシーンに新たなステージを関連付ける
  • ステージ選択ボタンの追加

となります。

その後、どのようにしてステージ選択ボタンがステージの状態(「選択不可」「選択可能」「クリア済み」)に応じて、状態を変化させているのかを説明します。

ステージの増やし方

まずはステージ自体を増やすことから説明しましょう。
教材ではすでにSTAGE1~3が用意されているので、STAGE4を作ってみます。

ステージ固有シーン(STAGE4)の作成

シーンを作成して、新しいステージを作ります。

新しいシーンはメニューの [File]→[New Scene] で作成できます。

19-3-メニューの File - New Scene

今回は Stage4 というシーン名で保存しました。

作られたシーンをゲーム内でロードするには Build Settings の Scenes in Build のリスト内に追加しておく必要があります。
メニュー[File]→[Build Settings] で Build Settings ダイアログを開き、 Add Open Scene ボタンを押すと現在開いているシーンが追加できます。

20-3-ScenesInBuildのリストにロードするシーンを追加

新しく作成したシーン Stage4 をブロック崩しのステージ固有シーンとして扱うにはプレハブの StageCommonConfig をシーンに配置し設定する必要があります。
StageCommonConfig にはブロック崩しを進行させるために必要なデータをステージ共通シーンに伝える役割があります。

Prefab フォルダにある StageCommonConfig をシーンにドラッグアンドドロップで追加して、データを設定しましょう。

21-3-StageCommonConfigプレハブを配置

NextStageName には次のステージを設定しますが、最終ステージの場合は何も設定しません。
Blocks には、ブロックだけを格納しているゲームオブジェクトを設定します。
この設定のため、ブロックは空のゲームオブジェクトの下位に配置してください。

空のゲームオブジェクトはメニュー[GameObject]→[Create Empty]で作成できます。
名前は変えなくても構いませんが、わかりやすいように Blocks に変更しました。
新しく作成した空のゲームオブジェクト Blocks を StageCommonConfig の Blocks プロパティに設定します。

22-3-Blocksの設定

あとはブロックを Prefabs の BlockLv1~3 から適宜選択してドラッグ&ドロップでシーンに配置します。
画面外に出てしまうとボールが届かなくなりクリアできなくなるので、カメラ枠の範囲内に置くようにしましょう。
すべてのブロックは先ほど作成した空のゲームオブジェクト Blocks の下に配置されるように Hierarchy タブで位置関係を確認・調整してください。

23-3-ブロックを配置してステージを作成

きれいに整列させたい場合は Unity の Snap Settings を利用すると良いでしょう。
Snap Settings はメニュー[Edit]→[Snap Settings]で表示されます。
これに、整列させたい間隔を設定すると選択したゲームオブジェクトを一定間隔できれいに配置することができます。

24-3-ブロックをSnap Settingsで整列

また、Scene タブで1個以上のブロックを選択して Ctrl を押しながらドラッグ操作をすると指定された間隔で移動できます。
ブロックを選択して Ctrl + D を押すと同じ場所にブロックを複製できるので、位置調整の手間が省けます。

最後に、ステージ固有シーンとステージ共通シーンのカメラが競合しないように Stage4 の Main Camera を無効にしてシーンを保存してください。

25-3-ステージ固有シーンのカメラを無効化

ステージ選択ボタンの追加

ブロックを配置した新たなステージを作っても、タイトルで選択できなくてはプレイできません。
そこで、作成した Stage4 に対応する新たなステージ選択ボタンをタイトル画面に追加します。

ステージ選択ボタンはプレハブ(Prefab/ButtonStage)で用意されています。
Hierarchy タブの Canvas/PanelStageSelect の下位にドラッグアンドドロップすると新しいステージ選択ボタンを簡単に追加できます。
最初は既存のステージ選択ボタンと重なっていますので移動させて配置してください。

26-3-ステージボタンの追加

ステージの名前は、他のボタンと同じく、ボタンの下位にある Text を編集しましょう。

ステージ選択ボタンの独自プロパティの設定

ボタンが押されたら作成したシーン Stage4 を読み込んだり、 前のステージをクリアするまで「選択不可」とするための設定を行います。
プロパティについては、「Unity でブロック崩しを作る際に使用する独自コンポーネント」の StageButton.cs の項も参考にしてください。

27-3-追加したステージボタンの設定

NameStage

追加したステージ選択ボタンに、割り当てたいステージのシーン名(今回は「Stage4」)を設定します。
これによりボタンが押されると、先ほど作成したシーン「Stage4」が読み込まれ、その後ボールやバーなどのステージ共通シーンが読み込まれステージ画面が表示されます。

FlgFirstStage

最初のステージに対応するボタンの場合はチェックします。
これがチェックされていると、初期状態から「選択可能」な状態になります。
最初のステージではなくても、いつでも「選択可能」にしたければチェックをいれましょう。
サンプルの STAGE2, STAGE3 のように前のステージをクリアしていなければ「選択不可」にしたい場合はチェックをはずしてください。

前のステージ(Stage3)の StageCommonConfig の設定

教材では、前のステージをクリアすると次のステージが選択できるようになります。
そのためには、前のステージが次のステージのシーン名を知っている必要があります。

今回は STAGE3 が STAGE4 の前のステージなので、シーン Stage3 を開き、 StageCommonConfig の設定を変更しましょう。

28-3-追加したステージのシーン名を前のステージに設定

Stage1,2,3 などのステージ固有シーンには必ず StageCommonScene プレハブが配置されています。
そのコンポーネントのプロパティ NameNextStage に「Stage4」を設定します。
これで、STAGE3 をクリアすると STAGE4 が「選択可能」に変更されます。
また、クリア時のダイアログの NEXT ボタンが有効になり押すと STAGE4 に移動できるようになります。

動作の確認

Title シーンを開いてから実行ボタンを押して動作を確認します。
(アプリ内課金を含む教材では Awake シーンを開いて実行ボタンを押して動作を確認してください)

29-3-ステージ追加の動作確認

初回起動時は Stage2, 3 と同じく選択不可になっていて、 Stage3 をクリアした直後から Stage4 が選択可能になることが確認できました。
Stage4 も正常にプレイでき、コンティニュー処理や各種ダイアログの表示も正常に行われています。

ステージの状態のリセット

Unity エディタ上で動作確認をした際もステージの状態は保存されます。
もしも、初回起動時からの動作を確認したくなった場合は、 PlayerPrefs の機能をコードから呼び出して初期化できます。

教材には、 PlayerPrefsClear というボタンがタイトル画面に隠されています。
Unity 上での実行時に、 Hierarchy タブでそのボタンを選択し、Inspector タブの左上のチェックを有効にするとボタンが Game タブの画面に表示されます。
表示された PlayerPrefsClear ボタンをクリックすることで全てのステージの状態が消去されます。
あとは、一度実行を停止して、再び実行すれば初回起動時と同じ状態になります。

30-3-Unity上での実行中にステージの状態をリセット

この PlayerPrefsClear ボタンでは、次のように Unity 標準の関数を呼び出すことで PlayerPrefs のデータを削除しています。

TitleScene.cs
    public void OnDebugButtonPlayerPrefsClear()
    {
        // 効果音を再生
        Util.PlayAudioClip(this.seButton, Camera.main.transform.position, 1.0f);
        // このアプリの PlayerPrefs の設定を全て消去します。
        PlayerPrefs.DeleteAll();
    }

ステージの状態に応じてボタンが変化する仕組み

ボタンは Awake イベント関数の中で対応する各ステージの状態に応じて、見た目や機能を変化させます。
Awake イベントはゲームオブジェクトが作成された直後に1度だけ呼び出される関数で、ボタンの初期化に使用しています。

StageButton.cs
    void Awake()
    {
        // ステージの状態を管理する PlayerPrefs のキーを作成します。
        // 接頭辞にステージのシーン名を足した文字列がキーになります。
        string keyStageStatus = prefixKeyStageStatus + nameStage;

        // ボタンのコンポーネントを取得します。
        UnityEngine.UI.Button coButton = GetComponent<UnityEngine.UI.Button>();

        // ステージの状態の記録がない場合は新規で設定します。
        // インストール直後のゲームの起動の際に行われます。
        if (PlayerPrefs.HasKey(keyStageStatus) == false)
        {
            // 最初のステージだけを「選択可能」にして、他は「選択不可」にします。
            if (flgFirstStage == true)
            {
                PlayerPrefs.SetInt(keyStageStatus, (int)StageStatus.Unlocked);
            }
            else
            {
                PlayerPrefs.SetInt(keyStageStatus, (int)StageStatus.Locked);
            }
        }

        // ステージの状態を取得します
        int stageStatus = PlayerPrefs.GetInt(keyStageStatus);

        // ステージの状態がクリア済みの場合
        if (stageStatus == (int)StageStatus.Cleared)
        {
            // すでにクリアしている場合は色をクリア済みのものに変えます
            UnityEngine.UI.ColorBlock colorBlock = coButton.colors;
            colorBlock.normalColor = colorOnClear;
            colorBlock.highlightedColor = colorOnClear;
            coButton.colors = colorBlock;
        }

        // ステージの状態が選択不可の場合
        if (stageStatus == (int)StageStatus.Locked)
        {
            // ロック解除されていない
            if (flgFirstStage == true)
            {
                // ただし、最初のステージのボタンは、強制的にロックを解除する
            }
            else
            {
                // ボタンコンポーネントを押せないように無効にする
                coButton.enabled = false;
                // ロック状態を表す画像のゲームオブジェクトを有効にする
                imageLocked.SetActive(true);
            }
        }
    }

ステージ選択ボタンでは PlayerPrefs からステージの状態を取得しています。
PlayerPrefs は Unity の標準機能で、任意の名前のデータをアプリごとに複数設定することができます。

31-3-ステージの状態の変化

初回のアプリ起動時は PlayerPrefs にはステージの状態は記録されていないので、 FlgFirstStage がチェックされていないステージは全て「選択不可」で初期化しています。

ステージをクリアした際は StageCommonScene により、次のステージが「選択不可」の場合は「選択可能」に PlayerPrefs を変更します。
これにより、前ステージをクリアすると次のステージが「選択可能」になります。

参考リンク