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

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

MENU

【Unity ゲーム制作】神経衰弱ゲームを作ろう!〜その8 (カードを配るアニメーション実装)

スポンサーリンク

f:id:Wojtek:20191006192625g:plain

今回は動画のような「カードを配るアニメーション処理」を作成したいと思います!

CardField 及び Card オブジェクトの調整しよう!


f:id:Wojtek:20191006192835p:plain

まずは「CardField」の設定を変更しましょう。

・Grid Layout Group のCellSize を X 100 : Y 200 に変更
・Grid Layout Group のChild Alignment を Upper Left に変更
ContentSizeFitter の Horizontal Fit を 「Unconstrained」に変更

カードの生成枚数を増やすため、1枚のサイズを小さくしました。

次は Card.オブジェクトの設定を変更します


f:id:Wojtek:20191006193353p:plain


Cardオブジェクトの pivot の Y値を 1 に変更します。

CardCreateManager に GridLayoutGroup のプロパティを追加する

public class CardCreateManager : MonoBehaviour {

    // 生成するCardオブジェクト
    public Card CardPrefab;

    // 「カード」を生成する親オブジェクト
    public RectTransform CardCreateParent;

    // 生成したカードオブジェクトを保存する
    public List<Card> CardList = new List<Card> ();

    // カード情報の順位をランダムに変更したリスト
    private List<CardData> mRandomCardDataList = new List<CardData> ();

    // GridLayoutGroup
    public GridLayoutGroup GridLayout;

GridLayout を設定したら、CardFieldのGridLayoutGroupをアタッチしましょう!。

こちらの準備ができたら、ソースコードの変更に入ります。


Card.csのmRt変数をpublic に変更する

public class Card : MonoBehaviour {

    // カードのID
    public int Id;

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

    // 透過処理用
    public CanvasGroup CanGroup;

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

    public bool IsSelected => this.mIsSelected;

    // カード情報
    private CardData mData;

    // 座標情報
    public RectTransform mRt;


Cardオブジェクトの座標変更の準備が整いました。

CardCreateManagerに処理を追加

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;

public class CardCreateManager : MonoBehaviour {

    // 生成するCardオブジェクト
    public Card CardPrefab;

    // 「カード」を生成する親オブジェクト
    public RectTransform CardCreateParent;

    // 生成したカードオブジェクトを保存する
    public List<Card> CardList = new List<Card> ();

    // カード情報の順位をランダムに変更したリスト
    private List<CardData> mRandomCardDataList = new List<CardData> ();

    // GridLayoutGroup
    public GridLayoutGroup GridLayout;

    // カード配列のインデックス
    private int mIndex;

    // カードを生成する時の高さインデックス
    private int mHelgthIdx;
    // カードを生成する時の幅インデックス
    private int mWidthIdx;

    // カードの生成アニメーションのアニメーション時間
    private readonly float DEAL_CAED_TIME = 1f;


・DOTweenを使用するため、 using DG.Tweening を追加
・カードの生成処理を実装するためのインデックス変数を追加


変数制限の次はいよいよ内部の処理に進みます。

        this.mIndex = 0;
        this.mHelgthIdx = 0;
        this.mWidthIdx = 0;

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

        // ランダムリストの初期化
        this.mRandomCardDataList.Clear ();

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

        // GridLayoutを無効
        this.GridLayout.enabled = false;

        // カードを配るアニメーション処理
        this.mSetDealCardAnime ();

前回と違う部分は「mRandomCardDataList」をメンバー変数にしたことです。
また、カードを生成するタイミングで GridLayoutGorup の変数を無効化しています。
アニメーション処理をやる場合、GridLayoutGroupが発動中だと邪魔になるため、生成が終わるまでは無効化しておきます。

それでは、カードの生成アニメーション処理を見ていきましょう。

/// <summary>
    /// カードを配るアニメーション処理
    /// </summary>
    private void mSetDealCardAnime () {

        var _cardData = this.mRandomCardDataList[this.mIndex];

        // Instantiate で Cardオブジェクトを生成
        Card card = Instantiate<Card> (this.CardPrefab, this.CardCreateParent);
        // データを設定する
        card.Set (_cardData);
        // カードの初期値を設定 (画面外にする)
        card.mRt.anchoredPosition = new Vector2 (1900, 0f);
        // サイズをGridLayoutのCellSizeに設定
        card.mRt.sizeDelta = this.GridLayout.cellSize;

        // カードの移動先を設定
        float posX = (this.GridLayout.cellSize.x * this.mWidthIdx) + (this.GridLayout.spacing.x * (this.mWidthIdx + 1));
        float posY = ((this.GridLayout.cellSize.y * this.mHelgthIdx) + (this.GridLayout.spacing.y * this.mHelgthIdx)) * -1f;

        // DOAnchorPosでアニメーションを行う
        card.mRt.DOAnchorPos (new Vector2 (posX, posY), this.DEAL_CAED_TIME)
            // アニメーションが終了したら
            .OnComplete (() => {
                // 生成したカードオブジェクトを保存する
                this.CardList.Add (card);

                // 生成するカードデータリストのインデックスを更新
                this.mIndex++;
                this.mWidthIdx++;

                // 生成インデックスがリストの最大値を迎えたら
                if (this.mIndex >= this.mRandomCardDataList.Count) {
                    // GridLayoutを有効にし、生成処理を終了する
                    this.GridLayout.enabled = true;
                } else {
                    // GridLayoutの折り返し地点に来たら
                    if (this.mIndex % this.GridLayout.constraintCount == 0) {
                        // 高さの生成箇所を更新
                        this.mHelgthIdx++;
                        this.mWidthIdx = 0;
                    }
                    // アニメーション処理を再帰処理する
                    this.mSetDealCardAnime ();
                }
            });
    }

まずは生成したCard.オブジェクトの座標を好きな位置に設定してください。
今回は画面外からカードが配られるイメージなので、画面外に設定しています。

前回と違うのは foreach ではなく、 インデックス変数から手動でカードの生成処理を行なっています。

ここまで処理が完成したらGameを起動してみましょう!

最初の動画の通りの動きになったら成功です!