気ままなUnityエンジニアブログ

新米Unityエンジニアが送る解説アウトプットブログです。Twitter : @UjinUnity

MENU

【Unity ゲーム制作】神経衰弱ゲームを作ろう!〜その4 ( カードの複数生成 )

スポンサーリンク

今回は以下の動画の様にランダムに複数のカードオブジェクトを生成する処理を実装しましょう!


f:id:Wojtek:20190924011205g:plain

CardData.class に関する記述が抜けていたため、修正いたします。

まずは、Cardクラスで表示する画像情報などをまとめたクラスを作りましょう。

Card.csに「CardData」クラスを作成しよう!

/// <summary>
/// カードの情報クラス
/// </summary>
public class CardData {

    // カードID
    public int Id { get; private set; }

    // 画像
    public Sprite ImgSprite { get; private set; }

    public CardData (int _id, Sprite _sprite) {
        this.Id = _id;
        this.ImgSprite = _sprite;
    }
}


上記のスクリプトを「Card.cs」の内部に作成してください。


作成し終わったら、内容について説明していきます。

このクラスの役割はズバリ 「Cardクラスで使用する情報用のクラス」です。

どういう意味かと言いますと、「public Sprite ImgSprite { get; private set; }」という変数を定義しています。


こちらは 「Cardに表示させる画像情報」を保管する変数です。

 public CardData (int _id, Sprite _sprite) {
        this.Id = _id;
        this.ImgSprite = _sprite;
    }

上のコードを見てください。
コンストラクタ ( クラスを new するときに発生する関数 ) でid と 画像データを設定しています。

つまり、Cardクラスを使って何かを表示したいときに、直接 Cardクラスに画像データを送るのではなく、
CardData クラスを作成して「表示する画像情報」などを設定し終わったあと、その内容をCardクラスに反映する仕組みになります。


CardDataクラスが作成し終わった、「CardCreateManager.cs」のStart関数に以下の処理を書き込みましょう。

usign System.Linq; == このusing を新規に記入しておいてください。

void Start () {

        // カード情報リスト
        List<CardData> cardDataList = new List<CardData> ();

        // 表示するカード画像情報のリスト
        List<Sprite> imgList = new List<Sprite> ();

        // Resources/Imageフォルダ内にある画像を取得する
        imgList.Add (Resources.Load<Sprite> ("Image/card_image_000"));
        imgList.Add (Resources.Load<Sprite> ("Image/card_image_001"));
        imgList.Add (Resources.Load<Sprite> ("Image/card_image_002"));

ここではまずは生成するカード画像情報を取得しています。
List は前回作成したCard.csのデータクラスに当たります。
このcardDataList にカードオブジェクトの情報を設定します。

次に List imgList を生成しています。
そして次の行から、Sprite型の情報をimgListに追加しています。

今回は、Resources.Load() を使って前回導入したカード情報を取得しています。

Resources.Load() はUnityに設定されている関数で、Assets配下の「Resources」フォルダに格納されているファイルを参照して取得できる関数です。
今回は Load()と宣言し、Sprite型のオブジェクト情報として取得しております。
注意点としては、Resources配下に設定した画像などが存在しない場合、Null値を出力するので、使用する際はnullチェックを忘れないでください。


次は取得したカード用の画像の分だけ、CardDataを作成しましょう。

     // forを回す回数を取得する
        int loopCnt = imgList.Count;

        for (int i = 0; i < loopCnt; i++) {

            // カード情報を生成する
            CardData cardata = new CardData (i, imgList[i]);
            cardDataList.Add (cardata);
        }

ここではfor文をしようしています。

int loopCnt = imgList.Count;

この部分ですが、List.Count() をfor文など使用する場合、List.Count()が呼ばれる度にCount()関数内部の処理が実行されます。
今回は数枚規模なので処理に大きな差は出ませんが、何百単位でのループ処理が必要な場合などは、list.Count()を使用する場合は変数に代入してから
使用することをお勧めします。

Listについては以下の記事も参考にしてください!
wojtek.hatenablog.com


CardDataの生成が完了しました。
神経衰弱で大事なのは、同じカードが2枚存在していることですよね
なのでもう一つのList を作成し、そのListに先ほど作ったcardDataListの値を2回読み込ませましょう。

   // 生成したカードリスト2つ分のリストを生成する
        List<CardData> SumCardDataList = new List<CardData> ();
        SumCardDataList.AddRange (cardDataList);
        SumCardDataList.AddRange (cardDataList);

これで同じカードが2枚ずつ存在する状態になりました。

次は表示するカードの順番をランダムにする処理です。

 // リストの中身をランダムに再配置する
        List<CardData> randomCardDataList = SumCardDataList.OrderBy (a => Guid.NewGuid ()).ToList ();

List randomCardDataList に先ほど設定したListの順番をランダムにして格納しています。

OrderBy() はLingの機能で要素を昇順に並べ替えています。
今回はその要素にGuidを使用しました。
Guidは値がめったに重複しない様に生成される識別子です。
今回はこの値を元にListの中身をランダムに入れ替えています。

これで表示するCardData情報は完成しました。
あとはこの情報を実体オブジェクトに格納しましょう。


// オブジェクト生成

// カードオブジェクトを生成する
        foreach (var _cardData in randomCardDataList) {

            // Instantiate で Cardオブジェクトを生成
            Card card = Instantiate<Card> (this.CardPrefab, this.CardCreateParent);
            // データを設定する
            card.Set (_cardData);
        }

ここではforeachを使っています。
これで格納された数のCardオブジェクトを生成することができます。


上記スクリプトで書かれている 「card.Set (_cardData);」について解説します。

Card.csに以下の関数を作成してください。

public class Card : MonoBehaviour {

    // カードのID
    public int Id;

    // 表示するカードの画像
    public Image CardImage;

    // 選択されているか判定
    private bool mIsSelected = false;

    // カードの設定
    public void Set (CardData data) {

        // IDを設定する
        this.Id = data.Id;

        // 表示する画像を設定する
        this.CardImage.sprite = data.ImgSprite;

        // 選択判定フラグを初期化する
        this.mIsSelected = false;

    }

これは先ほど作成したCardDataの情報を「Cardクラス」に反映してしています。
画像情報やID番号を反映することができるようになりました。


この後Gameを起動してみて、最初のGifの様な動作になれば成功です!。