【Unity/2D】スイカゲーム風の落ち物ゲームを作ってみる話 #9 次に出る果物を表示する

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

前回は、スコアの機能を実装しました。

今回は次に出てくる果物を表示させたいと思います。

次に出る果物の表示

次に出てくる果物を表示させたいのですが、画像でもあれば簡単に表示できますが、今回のゲームでは画像がありません。

さて困った…。どうにか次に出てくる果物を知らせるには…?

幾つかの方法が考えられますが、果物の色で次に出てくる果物を表示すればいいんです。

ということで果物の色で次に出てくる果物を表示します。

次に出てくる果物を表示するUIの作成

まずは次に出てくる果物を表示するためのUIを作成します。
ゲーム画面の右上に配置します。

メニュー > UI > Panelでパネルを作成し「UI_NextFruis」という名前で、AlwaysOnDisplayの子オブジェクトにします。

メニュー > UI > Panelでパネルを作成

「UI_NextFruis」という名前でAlwaysOnDisplayの子オブジェクトにする

そしてUI_NextFruitsのImageコンポーネントを削除します。

Imageコンポーネントを削除

次に、メニュー > UI > Imageでイメージを作成し「ImageFrame」としてUI_NextFruitsの子オブジェクトにします。

メニュー > UI > Imageでイメージを作成

「ImageFrame」としてUI_NextFruitsの子オブジェクトにする

そしてImageFrameを右上に配置します。

ImageFrameを右上に配置

Gameビュー

ImageFrameも表示だけになるので、ImageコンポーネントのRaycast Targetのチェックを外します。

ImageコンポーネントのRaycast Targetのチェックを外す

次に「Next」と表示させたいので、「Text_Next」というUIのテキストオブジェクトを作成し、UI_NextFruitsの子オブジェクトにして右上に配置します。

「Text_Next」というUIのテキストオブジェクトを作成しUI_NextFruitsの子オブジェクトにする

表示テキストを編集

右上に配置

Gameビュー

次にImageFrameを複製し「NextFruitsColor」とします。

ImageFrameを複製し「NextFruitsColor」とする

そしてImageコンポーネントのSource Imageのオブジェクト選択画面で、Knobを選択して色を黒にします。

Imageコンポーネントのオブジェクト選択画面を出す

オブジェクト選択画面でKnobを選択

Source ImageにKnobが選択された状態

色を黒にする

Gameビュー

このKnobの色を次の果物の色に変更して表示していきます。

もしKnobが無いという場合は、白い丸の画像を用意してください。

では下準備が整ったので、スクリプトを編集します。

スクリプトを編集

スクリプトの新規作成

今回はNextFruitsDisplayという新たなスクリプトを作成します。

NextFruitsDisplayスクリプトを新規作成

そしてNextFruitsColorに作成したスクリプトをアタッチします。

NextFruitsColorに作成したスクリプトをアタッチ

では準備ができたのでスクリプトを編集します。

Variables.cs

using UnityEngine;

public class Variables : MonoBehaviour
{
    #region Var-Number
    public const float zero = 0f;                               // floatの0
    public const float half = 2f;                               // floatの2
    public const float colorMax = 255f;                         // 色の最大値
    #endregion

    #region Var-String
    public const string tag_Fruits = "Fruits",                  // タグ:果物
                        tag_Bottom = "Bottom",                  // タグ:容器の底              
                        tag_GameManager = "GameManager",        // タグ:ゲームマネージャー
                        tag_NextFruits = "NextFruits";          // タグ:次の果物
    #endregion
}

今回新たに追加したのは、色の最大値となるcolorMaxと、NextFruitsColorに付けるタグの文字列となるNextFruitsの定数です。

次にNextFruitsDisplayを編集します。

NextFruitsDisplay.cs

using UnityEngine;
using UnityEngine.UI;

public class NextFruitsDisplay : MonoBehaviour
{
    #region NextDisplay
    // 次の果物の色の表示
    public void NextDisplay(Color color)
    {
        // 表示色を引数で渡された色にする
        gameObject.GetComponent<Image>().color = color;
    }
    #endregion
}

NextFruitsDisplayにはメンバ変数はありませんので処理を見ていきます。

NextDisplay関数

NextDisplay関数では、外部のスクリプトからアクセスされるためアクセス範囲をpublicにしています。

自身の表示色を引数で渡された色にします。

Colorを使うためusingにUnityEngine.UIを追加する必要があります。                        

次にFruitsGeneratorを見ていきます。

FruitsGenerator.cs

using UnityEngine;

public class FruitsGenerator : MonoBehaviour
{
    #region Var-Fruits
    [Header("果物")]
    [SerializeField] Fruits[] fruits;
    #endregion

    #region Var-FruitsDrop
    [Header("果物を生成する待機時間")]
    [SerializeField] float generatedTime = 1f;
    [Header("果物を落下させる待機時間")]
    [SerializeField] float droppedTime = 1f;
    #endregion

    #region Var-NextFruits
    [Header("次の果物の色")]
    [SerializeField] Color[] nextFruitsColor;
    #endregion

    #region Var-Internal
    Fruits currentFruits;                                               // 現在の果物
    NextFruitsDisplay nextFruitsDisplay;                                // NextFruitsDisplay
    bool isGenerated = false,                                           // 果物を生成したかのフラグ
         isDropped = false,                                             // 果物を落下させたかのフラグ
         isNextFruits = false;                                          // 次の果物ができたかのフラグ
    float timer = 0f;                                                   // 内部カウント用
    Color nextColor;                                                    // 次の果物の色
    public static int nextFruitsNumber = 0;                             // 次の果物の番号
    #endregion

    #region Start
    void Start()
    {
        // NextFruitsDisplayを取得
        nextFruitsDisplay = GameObject.FindWithTag(Variables.tag_NextFruits).GetComponent<NextFruitsDisplay>();
        // 果物を生成
        FruitsGenerate();
    }
    #endregion

    #region Update
    void Update()
    {
        // ゲームマネージャーのゲームオーバーのフラグがtrueの場合
        if (GameManager.isGameOver)
        {
            // 処理を中断
            return;
        }

        // 内部カウントを加算
        timer += Time.deltaTime;

        // --- 果物の生成 ---
        // 内部カウントが生成待機時間を超えている場合
        if (timer > generatedTime)
        {
            // 生成フラグがfalseの場合
            if (!isGenerated)
            {
                // 果物を生成
                FruitsGenerate();
                // 内部カウントを0にする
                timer = Variables.zero;
            }
        }

        // --- 果物の落下 ---
        // 内部カウントが落下待機時間を超えている場合
        if (timer > droppedTime)
        {
            // 落下フラグがfalseの場合
            if (!isDropped)
            {
                // スペースキーが押された場合
                if (Input.GetKeyDown(KeyCode.Space))
                {
                    // 果物を落下
                    FruitsDrop();
                    // 内部カウントを0にする
                    timer = Variables.zero;
                }
            }
        }
    }
    #endregion

    #region FruitsGenerate
    // 果物の生成
    void FruitsGenerate()
    {
        // 落下フラグをfalse
        isDropped = false;
        // 次の果物が生成されている場合
        if (isNextFruits)
        {
            // 果物のコピーを生成 生成物:次の果物
            currentFruits = Instantiate(fruits[nextFruitsNumber],
                                        // 位置:ポインターの位置 回転無し
                                        transform.position, Quaternion.identity);
        }
        // それ以外の場合
        else
        {
            // 果物のコピーを生成 生成物:登録された果物からランダムに生成
            currentFruits = Instantiate(fruits[Random.Range((int)Variables.zero, fruits.Length)],
                            // 位置:ポインターの位置 回転無し
                            transform.position, Quaternion.identity);
        }
        // 現在の果物の物理シミュレーションをfalse
        currentFruits.GetComponent<Rigidbody2D>().simulated = false;
        // 現在の果物の親オブジェクトをポインターにする
        currentFruits.transform.SetParent(gameObject.transform);
        // 生成フラグをtrue
        isGenerated = true;
        // 次の果物の番号を生成
        NextFruitsGenerate();
    }
    #endregion

    #region FruitsDrop
    // 果物の落下
    void FruitsDrop()
    {
        // 生成フラグをfalse
        isGenerated = false;
        // 現在の果物の物理シミュレーションをtrue
        currentFruits.GetComponent<Rigidbody2D>().simulated = true;
        // 現在の果物の親オブジェクトをnull
        currentFruits.transform.SetParent(null);
        // 落下フラグをtrue
        isDropped = true;
    }
    #endregion

    #region NextFruitsGenerate
    // 次の果物の番号を生成
    void NextFruitsGenerate()
    {
        // 次の果物の番号を生成
        nextFruitsNumber = Random.Range((int)Variables.zero, fruits.Length);
        // 次の果物の色を代入
        nextColor = nextFruitsColor[nextFruitsNumber];
        // 次の果物の色のアルファ値(透明度)を最大にする
        nextColor.a = Variables.colorMax;
        // 次の果物が出来たかのフラグをtrue
        isNextFruits = true;
        // 次の果物の色を表示
        nextFruitsDisplay.NextDisplay(nextColor);
    }
    #endregion
}

では追加したメンバ変数から見ていきます。

メンバ変数

メンバ変数で追加したのは、次の果物の色の配列となるColor[]のnextFruitsColorです。

あとは内部処理用として、NextFruitsDisplayを取得するためのnextFruitsDisplayです。

そして次の果物が準備出来たかのフラグとなるboolのisNextFruitsです。

そして次の果物の番号となるintのnextFruitsNumberです。
次の果物が準備できたことが分かるようにpublic staticにしています。

では処理を見ていきます。

Start関数

Start関数ではnextFruitsDisplayでNextFruitsDisplayを取得しています。

FruitsGenerate関数

FruitsGenerate関数では、次の果物が準備できたフラグのisNextFruitsがtrueの場合、currentFruitsを次の果物にしています。

それ以外の場合、つまりisNextFruitsがfalseの場合、currentFruitsはランダムに選ばれた果物になります。

そしてNextFruitsGenerate関数を呼んで、次の果物の番号を生成します。

NextFruitsGenerate関数

NextFruitsGenerate関数では、次の果物の番号をランダムに生成します。

そしてnextColorに次の果物の色を代入します。

nextColorは赤(R)・緑(G)・青(B)の色の情報しか持っていないため、アルファ値(透明度)のaが0になります。
そのためアルファ値を最大のcolorMaxにします。

そして次の果物が準備できたのでisNextFruitsをtrueにして、取得したnextFruitsDisplayのnextDisplay関数を呼び、引数にnextColorを渡しています。

ではスクリプトが編集できたので、Unityでの作業になります。

Unityでの作業

まずNextFruitsColorに「NextFruits」というタグを作成し設定します。

NextFruitsColorに「NextFruits」というタグを作成し設定します。

次にポインターのInspectorビューに次の果物の色という項目が追加されているので、落下する果物と同じ01_Cherry~05_Persimmonまでの色を、Variantsフォルダの果物の色からコピーして設定します。

落下する果物と同じ01_Cherry~05_Persimmonまでの色を設定

色をコピーする時は、一つの果物につきRGBの三回コピペするのは面倒ですので、アルファ値の下のHexaDecimalの値をコピーすると一回で済みます。
所謂16進数のカラーコードになります。

HexaDecimalをコピーすると楽ができる

では準備ができたので動作確認します。

動作確認

今回の確認事項は
  • 次の果物の色が表示されるか
  • 次の果物の色と同じ果物が生成されるか
になります。

それでは確認しましょう。

次の果物の色はみかん

次の果物の色の表示が変わりました。
どうやら次はみかんのようです。

次はみかんが生成された

これで想定通りの機能が実装できました。

まとめ

今回は
  • 次の果物の色を表示するUIを作成した
  • 次の果物の色を表示する機能を実装した
という事をやりました。

次回はゲームオーバーになったらリトライできる機能を作りたいと思います。

では、また次回!

コメント