ランダムな数字を抽選しよう!真ん中に表示!![Unity] #4

ビンゴカードがランダムに抽選されるようになったので、いよいよ抽選を行っていきます。どの番号が選ばれたかとその反映をしたいと思います。

目次

今回できること

Nextボタンを押して、なんの番号が抽選されたかを表示させていきましょう。

出来上がり

いよいよ画面に大きな変化がやってきましたね。ようやくビンゴらしい。

プログラムなどの設計方針・使うものなど

ゲームではしばしばプログラムのイベントを活用してUIの表示反映を行います。ボタンが押されてから抽選された数字をUIに反映するのはイベントで接続したいと思います。

  • BingoManager
    • ビンゴカードの最大値を元に、抽選で利用する変数を用意
    • まだ未選択のビンゴカードの番号を取得する
    • Nextメソッド作成
    • 選択された番号をイベントとして発信する
  • nextButtonゲームオブジェクト
    • Button.OnClickイベント
      • BingoManager.Nextメソッド
  • AreaInfoView
    • 抽選された数字を表示する

BingoManager修正

メインとなる実装はランダムな数字を抽選するまで!あとはイベントを発信する処理ですね。イベントは慣れないと使いづらく感じますが強力なツールなので、しっかりと使いこなせるようにしましょう。

ビンゴカードの最大値を元に、抽選する変数を用意

今回のビンゴゲームでは、数字の最大値は25~99までの数字を選択できるようにしています。ビンゴの数字を抽選する事前準備として、最大値がいくつかを覚えておく必要があります。また、すでに出した数字が再登場しないようにする工夫も必要です。

public class BingoManager : MonoBehaviour
{
    // メンバー変数を追加
    private List<int> bingoNumberBuffer = new List<int>();

    private void GenerateBingoCard(int maxNumber)
    {
        bingoSquareList.Clear();
        // -- ここから ----------------------------
        bingoNumberBuffer.Clear();
        // -- ここまで ------------------------------
        maxNumber = Mathf.Min(Mathf.Max(maxNumber, SQUARE_COUNT), 99);
        List<BingoSquare> tempList = new List<BingoSquare>();
        for (int i = 1; i <= maxNumber; i++)
        {
            BingoSquare bingoSquare = new BingoSquare();
            bingoSquare.number = i;
            bingoSquare.isOpen = false;
            tempList.Add(bingoSquare);
            // -- ここから ----------------------------
            bingoNumberBuffer.Add(i);
            // -- ここまで ------------------------------
        }
        for (int i = 0; i < SQUARE_COUNT; i++)
        {
            int randomIndex = Random.Range(0, tempList.Count);
            bingoSquareList.Add(tempList[randomIndex]);
            tempList.RemoveAt(randomIndex);
        }
    }
    // 他の処理は省略
}

未選択の数字を取得するメソッドを追加

bingoNumberBufferには、抽選で利用できる数字が入っています。この中からランダムに一つ抽選することで、未選択の数字を取得することが可能です。数字を取得しつつ、リストの中から再抽選されないように除外する処理も忘れずに!

public class BingoManager : MonoBehaviour
{
    // ほかは省略
    private int GetRandomNumber()
    {
        if (bingoNumberBuffer.Count == 0)
        {
            return -1;
        }
        int randomIndex = Random.Range(0, bingoNumberBuffer.Count);
        int bingoNumber = bingoNumberBuffer[randomIndex];
        bingoNumberBuffer.RemoveAt(randomIndex);
        return bingoNumber;
    }
}

イベント発信とNextメソッド

ここは一緒にしちゃいましょう。Nextボタンが押された時に呼ばれるメソッドの作成を行います。中ではなんの番号が抽選されたかのイベント発信も行います。

public class BingoManager : MonoBehaviour
{
    // イベント発信用のアクションを追加
    public static System.Action<int> OnBingoNumber;

    public void Next()
    {
        // まだ空いていないSquareを探す
        int number = GetRandomNumber();
        if (number == -1)
        {
            return;
        }

        // イベント発信
        OnBingoNumber?.Invoke(number);

        // 数字から何番目のSquareのIndexかを探す
        int squareIndex = bingoSquareList.FindIndex(x => x.number == number);

        // 要素内に存在しない場合はエラー
        if (squareIndex == -1)
        {
            Debug.Log($"number:{number} squareIndex:{squareIndex}");
            return;
        }
        // 表示更新(ここもイベント化しても良さそう)
        cardAreaView.SetCardOpen(squareIndex);
        // 変数の更新
        bingoSquareList[squareIndex].isOpen = true;
    }
    // 他の処理は省略
}
スライム

今回はNextメソッド内で選択されたカードの更新処理も行いました。こちらもイベントで変更できるようにしてもいいですね。

Nextボタン

作ったメソッドをボタンと連携させましょう。この時点で一度表示の確認が行なえます!うまくいきますかねー。

インスペクターのセット

基本的にはNewGameボタンと同じです。nextButtonゲームオブジェクトのインスペクターを変更しましょう。

  • nextButtonゲームオブジェクトのButtonコンポーネント
    • OnClickイベントの+ボタン
      • BingoManagerゲームオブジェクトセット
      • BingoManager.Nextメソッドをセット

動作確認

うまいことできていれば、ゲームを動かしてNextボタンを連打するとぽんぽん穴が空いていきます。うまく行かない場合は次の項目をチェックしてみてください。

  • 反応しない場合
    • nextButton関係の設定
  • 色がへん
    • cardAreaViewの色設定
  • NewGameボタンを押した後にNextボタン押したらおかしくなる
    • GenerateBingoCardメソッドでbingoNumberBufferのクリア処理忘れ

AreaInfoViewに数字を出す

今回の仕上げ。イベントを受け取って数字を反映する処理。しかと見よ。

スクリプト更新

AreaInfoViewのスクリプト変更。全体そこまで大きくないので、全文載せておきます。イベントを受け取る処理は流派がいくつかあります。今回は使い捨てな方法になっているので、他の場面では適してないことがありますのでパターンの一つと思って利用してください。

using UnityEngine;
using TMPro;

public class AreaInfoView : MonoBehaviour
{
    [SerializeField] private TextMeshProUGUI currentNumberText;
    [SerializeField] private TextMeshProUGUI subInfoText;

    public TextMeshProUGUI CurrentNumberText => currentNumberText;
    public TextMeshProUGUI SubInfoText => subInfoText;

    private void Awake()
    {
        BingoManager.OnBingoNumber += (number) =>
        {
            currentNumberText.text = number.ToString();
        };
    }
}
フェアリー

OnBingoNumberはstaticなイベントです。そのためクラス名の後ろにイベントがやってきます。

スライム

+= (number) => {ここ処理}はイベントが呼ばれたら、numberの番号が抽選され、ここ処理の内容が実行されます。

仕上げの確認

ど真ん中の数字が変化したら成功!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

目次