ビンゴカードがランダムに抽選されるようになったので、いよいよ抽選を行っていきます。どの番号が選ばれたかとその反映をしたいと思います。
今回できること
Nextボタンを押して、なんの番号が抽選されたかを表示させていきましょう。
出来上がり
いよいよ画面に大きな変化がやってきましたね。ようやくビンゴらしい。
プログラムなどの設計方針・使うものなど
ゲームではしばしばプログラムのイベントを活用してUIの表示反映を行います。ボタンが押されてから抽選された数字をUIに反映するのはイベントで接続したいと思います。
- BingoManager
- ビンゴカードの最大値を元に、抽選で利用する変数を用意
- まだ未選択のビンゴカードの番号を取得する
- Nextメソッド作成
- 選択された番号をイベントとして発信する
- nextButtonゲームオブジェクト
- Button.OnClickイベント
- BingoManager.Nextメソッド
- Button.OnClickイベント
- 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メソッドをセット
- OnClickイベントの+ボタン
動作確認
うまいことできていれば、ゲームを動かして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の番号が抽選され、ここ処理の内容が実行されます。
仕上げの確認
ど真ん中の数字が変化したら成功!
コメント