こんにちは、みじんこと申します。
本記事では前記事から引き続き、Unityでのガチャ(パック)機能の実装方法を説明します。
そちらをまだ見ていない方は、実施後にこの記事に進んで頂けると良きかと思います!
本記事では⑤のガチャ機能における「カードの移動アニメーションの実装」を解説していきます。
- 前準備とカードの作成
- カードとパックの生成実装
- カードの種類の実装
- カードのランダム生成機能の実装
- カードの移動アニメーションの実装
- カード詳細パネルの実装
- ショップの実装
本記事の完成形としてはこんな感じですね。
こんな感じで、パック開封時にカードが展開されるようにしていきます!!
それでは今回も頑張っていきましょう!!
Contents
【実装概要】本記事で実装する内容について
今回はカードの移動アニメーションを実装していきますが、この流れにて実装していきます。
- DOTween(アニメーション用のアセット)のインポート
- カードを移動させる処理を実装
「DOTween」って言うアニメーションを簡単に実装できるアセットを使って、
カードの動きを実装していく流れです。
それでは早速やっていきましょう!
手順①:DOTweenのインストール
それではまずは「DOTween」というアセットをインストールしていきましょう。
※DOTween:「Unityで動きをつけたいならこれを使え!」と言われるくらいに有名なアセット!
まずはUnityの画面にて、上部メニューのWindow→AssetStoreをクリック
そしたらUnity Asset Storeにアクセスされると思うので、検索バーにdotweenと入力して検索。
DOTweenって名前のアセットがあると思うのでクリック。(Proじゃない方ね)
DOTweenのページに飛ぶので、
青いボタン(マイアセットに追加する or Unityで開く)をクリックしてUnity画面を開く。
下記のウィンドウが表示されるので、「Import」をクリック。
下記のウィンドウが表示されるので、また「Import」をクリック。
下記のウィンドウが出てくるので、「Open DOTween Utility Panel」をクリック。
「Setup DOTween」をクリック。
ちょっと待ってるとApplyが押せるようになるので、クリックする。
ウィンドウが閉じたら、もう設定は終わってるはずなので、閉じてOK!!
手順②:カード移動アニメーションの実装
ではアセットのインポートが完了したので、実装に進んでいきましょう。
この流れで進めていきます!
- Unity上で、カードの移動先を作成
- 実際にカードが動く処理をスクリプトに記載
- Unity上の設定(スクリプトのアタッチとか)
- ゲームの実行
ではやっていこう!!
カードの移動先を作る
ではまずはカードが展開される場所を作っていきましょう!
- 新しくPanelを作って、名前をExpandCardTransに変更
- パラメータを設定
- AddComponentして、Grid Layout Groupを追加
- パラメータを設定!
ちなみに「Grid Layout Group」っていうのは、
子要素を指定の大きさで均等に並べてくれる便利なコンポーネントのこと!!
④で設定した値に沿って子要素のセルの大きさや並び方が変わるよ。
今作ったExpandCardTransの中に更にパネルを作っていくよ。
- ExpandCardTransの子要素として、新しくPanelを8個作成。
名前をExpandCardTrans1〜ExpandCardTrans8にしてね。 - こんな感じになればOK!!
この8枚のパネルにカードが広がって移動していくイメージです!
スクリプトの作成と記載
そしたら次にスクリプトを作っていこう!!
まずは「CardMovement」スクリプトを作成。
このスクリプトにカードが移動する処理を書いていくよ。
CardMovementコードの記載と解説
ハイライト箇所に注目して追記、変更。(丸ごとコピペでもOK)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; // DOTweenの機能を使うために記載が必要 public class CardMovement : MonoBehaviour { // パック開封時にカードが移動する処理 public IEnumerator ExpandThisCard(Transform moveTarget) { transform.SetParent(moveTarget); // 親要素を変更する transform.DOMove(moveTarget.position, 0.5f); // 0.5秒かけて指定の場所に移動 yield return new WaitForSeconds(0.5f); // 0.5秒間処理を止める } } |
上からざっと説明すると、
4行目の「using ~」の記載は、DOTweenの機能を使うときに記載するもの!って認識でOK。
そして8〜14行目の「ExpandThisCard」メソッドですが、これが今回の移動処理の肝になります!
ただやってることは単純で、
- カードの親要素(※)を変更
- 指定の場所にカードを移動
- 動いてる間、処理を止めておく(コルーチン処理)
これだけですね。
ただこのコルーチンってのがかなり大事なので、後ほど説明します。
※親要素:Unity上で言うと、対象オブジェクトの上位の要素のこと。図解するとこれ↓
■コルーチンについての説明
【補足】コルーチンって何よ!!
プログラムの処理を一旦止めることが出来る関数のことをコルーチンって言います。
(正確な説明ではないかも)
※正確に知りたい人はこちらをチェック→ コルーチン – Unity マニュアル
コルーチンを使いたい時はまず、
「この関数はコルーチンだよ!」って宣言してあげる必要があります。
その宣言が「IEnumerator」です。(ExpandThisCardメソッドの前に書いてあるやつ)
IEnumerator メソッド名って書いてあげることで、
「このメソッドはコルーチンなんだなあ」って思ってもらえる感じです。
それでそのコルーチンの中で、
yield return new WaitForSeconds(1.0f);
って書くと1秒間処理を止められます。
で、そのコルーチンを実行したいときに
「StartCoroutine メソッド名」って書くことで、
コルーチンを実行できる!っていうこと!!
コルーチンを使う時の3つのポイント!!
- コルーチンだよって宣言する:IEnumerator メソッド名
- ここで止まってねって書く(1秒止めたい時):yield return new WaitForSeconds(1.0f);
- コルーチンを実行してくれーって書く:StartCoroutine(メソッド名)
これを踏まえた上で、さっき記載したコードを見てもらえると理解が深まるかと思います!
CardControllerコードの記載と解説
さて、今しがたCardMovementスクリプトを作りましたが、
CardViewと同じようにCardControllerスクリプトから管理出来たほうが便利なので、
CardControllerスクリプトも修正していきましょう。
CardControllerスクリプトにハイライト箇所を追記。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CardController : MonoBehaviour { public CardView view; // カードの見た目の処理 public CardModel model; // カードのデータを処理 public CardMovement movement; // カードの動きを処理 private void Awake() { view = GetComponent<CardView>(); movement = GetComponent<CardMovement>(); } public void Init(int cardID) // カードを生成した時に呼ばれる関数 { model = new CardModel(cardID); // カードデータを生成 view.Show(model); // 表示 } public void DestroyCard(CardController card) { Destroy(card.gameObject); } } |
これは説明するまでもなく、
CardControllerからCardMovementを扱えるようにしただけですね。
OpenPackManagerコードの記載と解説
さて、カードが動く処理は書けましたが、
カードが動く処理を動かす処理がないと何の意味もないので、
次はカードが動く処理を実行させる処理を書いていきましょう。
カードが動いて欲しいタイミングは、
パックが開いて、カードが生成されたタイミングなので
OpenPackメソッドにカードを動かす処理を書いていきましょう!
というわけで「OpenPackManager」スクリプトに下記のハイライト部分を追記。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
(省略) public class OpenPackManager : MonoBehaviour { [SerializeField] GameObject cardPackPrefab; // カードパックプレハブ [SerializeField] Transform openedCardTrans; // 開封したカードの生成場所 [SerializeField] Transform cardPackTrans; // カードパックの生成場所 // カードの展開先の場所 [SerializeField] Transform expandCardTrans1; [SerializeField] Transform expandCardTrans2; [SerializeField] Transform expandCardTrans3; [SerializeField] Transform expandCardTrans4; [SerializeField] Transform expandCardTrans5; [SerializeField] Transform expandCardTrans6; [SerializeField] Transform expandCardTrans7; [SerializeField] Transform expandCardTrans8; (省略) // パックを開封するメソッド public void OpenPack() { // 8枚カードを生成する for (int i = 0; i < 8; i++) { int cardId = decisionCardId(); GameManager.instance.CreateCard(cardId, openedCardTrans); } // カードを展開させる ExpandPackCards(); } (省略) // パックのカードを展開するメソッド void ExpandPackCards() { int cardNum = 0; Transform moveTarget = null; CardController[] cardList = openedCardTrans.GetComponentsInChildren<CardController>(); foreach (CardController card in cardList) { cardNum += 1; switch (cardNum) { case 1: moveTarget = expandCardTrans1; break; case 2: moveTarget = expandCardTrans2; break; case 3: moveTarget = expandCardTrans3; break; case 4: moveTarget = expandCardTrans4; break; case 5: moveTarget = expandCardTrans5; break; case 6: moveTarget = expandCardTrans6; break; case 7: moveTarget = expandCardTrans7; break; case 8: moveTarget = expandCardTrans8; break; } StartCoroutine(card.movement.ExpandThisCard(moveTarget)); } } } |
こちらもざっと説明していきますが、量が多いので分割して考えましょう。
ざっくり分けると、記載したコードの内容は下記の3つですね。
- カードの展開先の設定
- ExpandPackCardsメソッド(カードを展開させるメソッド)の記載
- ExpandPackCardsメソッドを実行させる処理の記載
それぞれざっくりと解説していくと、、
■①カードの展開先の設定
まずはカードを展開する場所の設定をする必要があるので、
カード8枚分の移動先の場所の設定を入れるコードを記入。
1 2 3 4 5 6 7 8 9 |
// カードの展開先の場所 [SerializeField] Transform expandCardTrans1; [SerializeField] Transform expandCardTrans2; [SerializeField] Transform expandCardTrans3; [SerializeField] Transform expandCardTrans4; [SerializeField] Transform expandCardTrans5; [SerializeField] Transform expandCardTrans6; [SerializeField] Transform expandCardTrans7; [SerializeField] Transform expandCardTrans8; |
■②ExpandPackCardsメソッドの記載
これが今回の肝ですね。
見た目長いですけど、大したことしてないので安心してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
// パックのカードを展開するメソッド void ExpandPackCards() { int cardNum = 0; Transform moveTarget = null; CardController[] cardList = openedCardTrans.GetComponentsInChildren<CardController>(); foreach (CardController card in cardList) { cardNum += 1; switch (cardNum) { case 1: moveTarget = expandCardTrans1; break; case 2: moveTarget = expandCardTrans2; break; case 3: moveTarget = expandCardTrans3; break; case 4: moveTarget = expandCardTrans4; break; case 5: moveTarget = expandCardTrans5; break; case 6: moveTarget = expandCardTrans6; break; case 7: moveTarget = expandCardTrans7; break; case 8: moveTarget = expandCardTrans8; break; } StartCoroutine(card.movement.ExpandThisCard(moveTarget)); } } |
注目すべき処理は3つです。
- 移動するカードのリストを取得
- それぞれのカードの展開先の設定
- カードの移動
■①cardListの取得
1 |
CardController[] cardList = openedCardTrans.GetComponentsInChildren<CardController>(); |
まずはこのコードを実行して、対象のカードを取得してリスト化します。
「openedCardTrans」の子要素のカードを全部cardListって名前のリストにぶち込むよ!って理解でOK
■②各カードの展開先の設定
次に、さっき作ったカードリストを使って1枚づつ順番に移動先を設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
foreach (CardController card in cardList) { cardNum += 1; switch (cardNum) { case 1: moveTarget = expandCardTrans1; break; case 2: moveTarget = expandCardTrans2; break; case 3: moveTarget = expandCardTrans3; break; case 4: moveTarget = expandCardTrans4; break; case 5: moveTarget = expandCardTrans5; break; case 6: moveTarget = expandCardTrans6; break; case 7: moveTarget = expandCardTrans7; break; case 8: moveTarget = expandCardTrans8; break; } } |
foreachっていうのは、
リストに入ってるものを対象に1つづつ処理を実行させるよ!ってもの。
switchっていうのは、
()内の値によって処理内容を変更させる!ってもの。
なので、やってることとしては、
1枚目のカードの設定をしてる時は、expandCardTrans1を移動先に設定して。
2枚目のカードの設定をしてる時は、expandCardTrans2を移動先に設定して、、、
みたいな感じで、カードによって移動先を変えて設定してる!!ってことですな。
Foreach文について
リストに書かれてるものに1つづつ処理をさせたい時に使うよ。
foreach (型名 変数名 in リスト名)
{
処理
}
(すごく適当な使用例)
foreach (食べ物型 A in 美味しいものリスト)
{
Aを食べる
}
→【実行結果】美味しいものリストのものを全部食べる!みたいな。
Swich文について
値によって処理を変えたい時に使うよ。
swich (変数名)
{
case 値:
処理
break;
case 値:
処理
break;
(以降、書きたい分だけ続く、、)
}
(すごく適当な使用例)
foreach (食べ物型 A in 美味しいものリスト)
{
switch (A)
{
case 寿司:
醤油を付ける
break;
case カレー:
自家製スパイスをかける
break;
}
Aを食べる
}
→【実行結果】食べ物によって食べ方を変えて、更に美味しく食べれる!みたいな。
■③OpenPackメソッドの修正
1 2 3 4 5 6 7 8 9 10 11 12 |
// パックを開封するメソッド public void OpenPack() { // 8枚カードを生成する for (int i = 0; i < 8; i++) { int cardId = decisionCardId(); GameManager.instance.CreateCard(cardId, openedCardTrans); } // カードを展開させる ExpandPackCards(); } |
これは単にカードを生成した後に、
ExpandPackCardsメソッドを動かしてカードを展開するよーってだけ!
Unity側の設定
それでは最後にUnity側の設定をしていきましょう。
- OpenPackManagerを選択
- ExpandCardTrans1~8をアタッチする
CardプレハブにもCardMovementをアタッチしましょう。
- Cardプレハブをクリックして、OpenPrefabして開く
- AddComponentでCardMovementをアタッチ
これで設定は完了です!!
ゲームの実行
それではゲームを実行しましょう。
パックが出てきて、、
クリックしたら、カードが動いた!!
ってなればOKです!!
【演習】コルーチンを使えるようになろう!
さてさて皆さん、お待ちかねの演習のお時間です!
今回は処理を止めるコードとしてコルーチンってのが出てきましたね。
ゲームを作る時にはめちゃめちゃ使うものなので、演習を通して使えるようになりましょう。
今回やってもらいたい演習はこちらです。
今作ったゲームはパックを開くとすぐにカードが展開されてしまうので、
この動画のように、クリック後少し待って、
カードが1枚づつ移動し始めるような処理にしてみましょう!
コルーチンの内容が分かってないと出来ないので、
コルーチンってなんだっけ。
って人は、コルーチンについての説明をもう一回読んでからやってみよう!
【答え合わせ】コルーチンを使えるようになろう!
では演習の答え合わせしていきましょう。
コルーチンを使う時の3つのポイントを使えていれば出来たはず!
コルーチンを使う時の3つのポイント!!
- コルーチンだよって宣言する:IEnumerator メソッド名
- ここで止まってねって書く(1秒止めたい時):yield return new WaitForSeconds(1.0f);
- コルーチンを実行してくれーって書く:StartCoroutine(メソッド名)
まずは、この3点を実装する必要があるのでこのコードを書いていきましょう。
- 関数をコルーチン宣言する
- カードを展開する前に、ちょっと待ち時間を作ってあげる
- それぞれのカードを動かす間にちょっとだけ待ち時間を挟む
では実際のコードで解説していきます。
OpenPackManagerスクリプトのExpandPackCardsメソッドに
ハイライト箇所を変更、追記しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
// パックのカードを展開するメソッド IEnumerator ExpandPackCards() // IEnumeratorに変更 { int cardNum = 0; Transform moveTarget = null; CardController[] cardList = openedCardTrans.GetComponentsInChildren<CardController>(); yield return new WaitForSeconds(1.25f); foreach (CardController card in cardList) { cardNum += 1; switch (cardNum) { case 1: moveTarget = expandCardTrans1; break; case 2: moveTarget = expandCardTrans2; break; case 3: moveTarget = expandCardTrans3; break; case 4: moveTarget = expandCardTrans4; break; case 5: moveTarget = expandCardTrans5; break; case 6: moveTarget = expandCardTrans6; break; case 7: moveTarget = expandCardTrans7; break; case 8: moveTarget = expandCardTrans8; break; } StartCoroutine(card.movement.ExpandThisCard(moveTarget)); yield return new WaitForSeconds(0.1f); } } |
これによって、これらの処理が実装される感じですね。
- カードが展開される前に1.25秒待って、
- その後1枚カードが動いたら0.1秒待ってから次のカードを動かす
そして最後にExpandPackCardsメソッドをコルーチン化したので、
このメソッドを実行するときのコードをStartCoroutineに変更しましょう。
OpenPackメソッドに書いてある下記のハイライト部分を変更。
1 2 3 4 5 6 7 8 9 10 11 12 |
// パックを開封するメソッド public void OpenPack() { // 8枚カードを生成する for (int i = 0; i < 8; i++) { int cardId = decisionCardId(); GameManager.instance.CreateCard(cardId, openedCardTrans); } StartCoroutine(ExpandPackCards()); // StartCoroutineに変更 } |
では最後にゲームを実行!!!
演習通りの動きになった!!!
と言うわけで、今回の解説はこれで終わりです!!
お疲れ様でした!
【まとめ】カードの移動編
今回も最後まで読んでいただき、ありがとうございました!!
ガチャ機能としては大体、実装出来たかと思うので、
一旦、ガチャ機能の解説記事はここまでとなります。
この記事がカードゲーム制作の一助になったでしょうか。
もし少しでも助けになったのであれば嬉しいです。
次回からはデッキ編成の作り方解説に入っていきますので、
引き続きこちらも読んでいただけると良きかと思います!!
2024/2/2 追記
この記事のガチャ機能の続きの実装について解説した記事をリリースしました!!
この記事の解説通りに作っていけば、下記のようなガチャ機能やショップ機能、デッキ編成機能を実装できるようになっていますので、是非とも見てみてくださいな!
ここまで!!
ではでは今回は以上です!
また別の記事でお会いしましょう!!
ではまた!!!