カードゲームの作り方

【解説通りに作るだけ】Unityのデジタルカードゲーム作り方講座⑥ ターンフェーズ作成編

前回までの記事で、実際にデータを持ったカードを自由に出せるようになりましたね!!

前回の記事を見てない人はそちらを参考↓

【解説通りに作るだけ】デジタルカードゲームの作り方講座⑤ カードデータの反映編前回までの記事でカードを持って動かせるようになりましたね!! 見てない人は前回の記事参考↓ http://yuus01.info/g...

今回の記事では、ターン開始時のドローやターンエンドなど、ターンフェーズの実装をしていきます!

今回の記事で実装すること↓

デッキの作成
ターンエンドボタンの実装
敵のカードの召喚
ターンフェイズ管理

完成形としてはこんな感じ↓

ターンの流れが出来ると、よりゲームらしくなるよね!

前回はちょっと難しかったかも知れないけど、
今回は前回に比べると多少簡単なはず!!

ちょっとずつ理解しながら進めてこうね。

ではいくぞ!

2022/01/06 加筆修正

DrawCardが全部DrowCardになっていたので修正しました!!(これはお恥ずかしいやつ(*ノω・*)テヘ)

コメントで教えてくれた方ありがとうございますー!

全体の流れの説明

ではまず今回やる作業の全体の流れを抑えてから、実際の作業に進んで行きましょう!

今回やる事としてはこんな感じ↓

・GameManagerへ追記
・TurnEndボタンへのアタッチ

今回実装する「ボタンを押した時に処理を行うやり方」は今度めっちゃ使うので、この機会に覚えちゃおう!!

GameManagerへの追記

今回のコードは全部「GameManager」に書いていきます!!

追加する内容はザックリこんな感じ↓

デッキのリストの追加
・ゲームスタート時の手札のドロー(3枚)処理
・TurnEndボタンを押したら、相手のターンにする処理
・自分のターンになったらカードを1枚引く処理
・相手のターンにカードを一枚出してくる処理

まあとりあえず、やりながら見ていこう!!

オレンジ部分のコードに注目して、コピペしてみよう↓

ちょっと長かったけど、無事貼れたかな??

エラーが出てないことを確認したら、次に進もう!

TurnEndボタンへのアタッチ

では次に、TurnEndボタンを押した時に、ターンエンドを行う処理を紐付けていくよ!!

ボタンに処理を設定する方法

①「TurnEndButtom」をクリック
②「OnClick」って所の「+」をクリック
③④「None」って書かれてる所に向かって、GameManagerオブジェクトをドラッグ&ドロップ

①「NoFunction」をクリック
②「GameManager」を選択
③「ChangeTurn」をクリック

そしたら、こんな感じになればOK!!!↓↓

これでTurnEndボタンに「ChangeTurn」メソッドの紐づけが完成!!

では実行してみよう!!

ちゃんとターンの流れが出来てる!!

という訳でしっかり実装出来たら、コードの解説をしていきます!

コードの解説

今回は大枠で見ると、7つのメソッドを追記した。ということになるので、

メソッド毎にどんな事をしてるメソッドなのか。って言うのを理解していこう!!

ちなみに出てきたメソッドの概要はこんな感じ↓

【メソッド名】 【メソッド処理の概要】
StartGame 初期値の設定
DrawCard カードをデッキから一枚引く
SetStartHand ゲーム開始時の手札を引く(3枚)
TurnCalc ターンの管理
ChangeTurn 敵と自分のターンを逆にする
PlyerTurn プレイヤーのターンの動きを管理
EnemyTurn 敵のターンの動きを管理

ではそれぞれのメソッドの詳細を説明していくよ!!

「StartGameメソッド」解説

このメソッドは、
ゲーム実行時に最初に呼ばれるメソッドで、初期値の設定をしてるよ。

次の記事以降で、
・リーダーのHP
・ゲーム開始時のマナポイント
などの設定を、ここのメソッドに追記していくよ。

「DrawCard」メソッド解説

このメソッドは、デッキの一番上のカードをドローするメソッドだよ。

最後の行で、前回の記事で作ったメソッド「CreateCard」を使ってるけど、これは

CreateCard(出したいカードの番号, カードを出したい場所)

というメソッドだったよね。

ここではそれを使って、今回新しく作った「deck」リストの0番目(プログラミングでは1つ目を0番目という)を手札に出す。という処理をしてるよ。

上のIF文は、
「Deck」の枚数が0枚だったら引かないようにする。
という条件分岐をしてるよ。

※IF文はかなり大事なので、全く分からない人は軽く調べること推奨!!

「SetStartHand」メソッド解説

このメソッドは、手札を3枚ドローする処理。

FOR文は「指定の回数を繰り替えす」処理なので、
さっき説明した「DrawCard」メソッドを3回繰り返してるだけだね。

※FOR文もかなり大事なので、軽く調べること推奨!
まあ簡単に言うと、「指定した回数分処理を繰り返す」もの。って認識でOK

「ChangeTurn」メソッド解説

このメソッドは、ターンの管理をしているよ。

今回GameManagerの上の方で追記した内容に、

bool isPlayerTurn = true;

というのがあるんだけど、これは「今どっちのターンなのか」を管理する変数になっているよ。

これを逆(つまりTrueをFalseに、FalseをTrue)にすることで、ターンを順番に回すことが出来るよ。

「TurnCalc」メソッド解説

このメソッドは、
今どっちのターンかを判断して、
次の対象のターン処理を実行するメソッド。

「ChangeTurn」メソッドでも説明したけど、最初の状態(デフォルト)では、isPlayerTurnはTrueだったよね。

つまり最初はプレイヤーのターン。

でもターンエンドボタンが押されたりすると「ChangeTurn」メソッド動いて、isPlayerTurnが逆になる。つまりFalseになる。

Falseになると、EnemyTurn(敵のターン処理)が始まる。

で、EnemyTurnの最後の処理でまたChangeTurnメソッド動いて、isPlayerTurnが逆になる。今度はTrueになる。

そしてまたPlayerのターンになって、、、、

という様な処理を繰り返しているよ!

※IF文がいまいち分かんない人用に説明しとくと、

IF(~)は、「~だったら、この処理をやるよ。」ってことで、
ELSEは、~じゃなかったら、この処理をやるよ。」ってこと!

とりあえずこのくらいが分かれば全然OK!!

「PlayerTurn」メソッド解説

このメソッドは、自分のターンの動きを処理してるよ。

今はまだドローする処理しかないけど、
・ターンの始まりにマナポイントを増やす
・攻撃済みのカードを攻撃出来るようにする
等の処理をここに追記していくよ!

「EnemyTurn」メソッド解説

このメソッドは、敵のターンの動きを処理してるよ。

今の動きとしては、この2つだけ。
・Card1を召喚
・ターンエンドする

もっと敵にカードを出させたいなら、同じように召喚するコードを書けばOK

最終的にはターン経過とかHPに応じて、敵の行動を変えるようにしていく予定だよ。

【プラスα】カード枚数を制御したい

よし、完成したから演習に行こう!!!

って思ったけど、ターンエンドボタンを押しまくってみて??

バグじゃあああ!!!!

ってな訳で、流石にこれはカッコ悪いので修正しましょ!

修正したい点としては2点だね。

  • フィールドに何枚でも出せちゃう
  • 手札が何枚でも持てる

この2つを修正していこう!!

こんな感じにしていくよ!

  • フィールドには5体まで
  • 手札は9枚まで

なんとなくでもいいから、
「こうすれば出来そうかも!」
って考えてから進んでみてね。

手札枚数に制限を掛けるには??

まず手札枚数の制限をするには、どの処理を変更すればいいのかを考えてみよう。

方法としては色々考えられるけど、
一番簡単に出来るのは「ドローする時」の処理を変更するのが良さそう。

というわけで、
現状では何枚でもドロー出来てしまう「DrawCard」メソッドを、
「手札枚数が9枚より少ないならドローする」という処理に変えていくよ!!

ではDrawCardメソッドを修正していこう。
下のコードになるようにオレンジ部分を追記、修正してみて!!↓

では追記した部分の解説をしていくよ!

CardController[] playerHandCardList = playerHand.GetComponentsInChildren();

これは日本語で言うと、
PlayerHandにあるカードを、
playerHandCardListというリストに入れますよ。
って処理だよ。

プログラミング的に言うと、
PlayerHandの子要素を
CardController型のリストに突っ込みますよ。
ってことだね。

その下のIF文は、

if (playerHandCardList.Length < 9){省略}

日本語で言うと、
playerHandCardListの個数が9個無ければ、
その次の処理をやりますよ。
ってこと!!

こんな感じの処理を追加することで、
「手札が9枚の時にはドローはしない」
というコードにすることが出来るよ!!

フィールドの枚数に制限を掛けるには??

今度は敵フィールドに出てくるカードの枚数を制限してみよう!!

自分で考えてやってみるとめっちゃ力になるから、一旦考えてみて!!

さっきのとほぼ一緒だからできるはず!

では答え合わせ↓

こんな感じにすればOK!!

一応解説すると、
今度はenemyFieldのカードリストを取得して、
その個数が5個無いならカードを出す。
ってことだね。

ではゲーム実行して、バグ修正出来たのかを確認してみて!!

出来てたら次に進んでいこう!

【演習】リストとIF文の使い方

では最後に演習やっていきましょう!

今回の課題はこれ↓

【課題】
次の画像の1~5ターン目の動きを再現してみよう!!!

【1ターン目】

【2ターン目】

【3ターン目】

【4ターン目】

【5ターン目】

これをコードで実装してみて!!

ヒントとしては、

・デッキのリストを変更する
・2体目まではCard3を召喚する
・3体目からはCard2を召喚する

ここら辺に注意してやってみよう!!

【演習】答え合わせ

では出来たかな??

答えの解説にいくぞ!!

今回演習で修正が必要なのは、以下の2つだけだね。

  • deckリスト
  • EnemyTurnスクリプト

それぞれの修正後はこんな感じ!!

【deckリスト】

毎ターンCard1とCard2を交互に引いてるので、デッキとしてはこんな感じ↓

9枚目以降は見えてないので、数字の羅列が9個分あれば正解だよ。

【EnemyTurnスクリプト】

敵フィールドのカードの数が2より小さいなら、Card3を出す。
そうでないなら、Card2を出す。

ということなので、こんな感じかな↓

今回の演習は出来たかな??
これが出来てたら、かなり理解しながら進めてると思うよ!!

みんなの出来具合を知りたいので、

コメントに「演習できーた!」とか
「演習難しいです。お陰で悲しみです。」
とか書いてくれると今後の記事に活かしやすいのでお願いします!

※普通に書いてくれればいいよ。笑

【まとめ】ターンフェイズの実装

今回でターンフェイズの実装が出来ましたね!!

ターンフェイズを作るにあたって、

  • IF文の使い方
  • FOR文について
  • ボタンにメソッドを付ける方法
  • 要素数を取得する方法

ここら辺も理解出来ると、今後ゲームを作るうえで便利なので少しずつでも覚えていこうね!!

では今回はここで終わり!!

演習が出来たかどうかのコメントよろしくね!

ちなみに次回はマナポイントの実装 攻撃の実装をしていくよ!

ではおわりっ!!

次の記事↓

【解説通りに作るだけ】Unityのデジタルカードゲーム作り方⑦ カードバトル編前回までの記事で、ドローやターンエンドボタンなど ターンフェーズについての実装が完了しましたね! 前回の記事を見てない人はそちらを参考...

前の記事↓

【解説通りに作るだけ】デジタルカードゲームの作り方講座⑤ カードデータの反映編前回までの記事でカードを持って動かせるようになりましたね!! 見てない人は前回の記事参考↓ http://yuus01.info/g...

参考にさせて頂いた動画
[Unityゲーム開発講座] シャドバ風!?カードゲームの作り方 #1 UIの実装

ABOUT ME
みじんこ
【名前】みじんこ(ここのブログ書いてるひと) ・大学2年の時に「ゲームが作りたいー!!」って思ったのに、ゲームの作り方を解説してるサイトがことごとく何言ってんのか分かんなくて挫折した。 ・数年な時を経て「だったら俺が完全初心者にも超わかりやすいサイトを作ってやんよ!」って事で、初めてゲームを作ろうとしてる方向けに解説記事を書いてるよ。

POSTED COMMENT

  1. もっけ より:

    演習はできましたが
    答えとは違いました
    deckをプレイヤー側、deck_enemyを敵側として
    デッキを2つ作成して演習クリアしました
    DrowCardメソッドには、第二引数にnumを追加して、0がプレイヤー、1が敵にして、処理を分けるようにしました
    でも、そもそもデッキを分けるのはよくないですね(失敗

    2
    • みじんこ より:

      >もっけさん
      なるほど!確かにその方法でも実装出来ますね

      確かに今回のゲームの仕様では敵のデッキは存在しないのでデッキを分ける必要は無いですが、敵もデッキを持ってバトルするカードゲームを作る場合は、もっけさんの作った通りの仕様になると思います!

      もし別にカードゲームを作る場合には、そっちの仕様で作ってみても面白いと思いますよ!!

  2. じゃがすけ より:

    敵も自分もカードをランダムに召喚することってできますかね?

    1
  3. muto より:

    わかりやすかったです。
    謎のコンパイラエラーはきまくってソースコピペしたら動いたのでたぶん{}の位置ミスかも…

    1
    • みじんこ より:

      あるあるミスですね(笑)
      カッコを使うときは書き終わってから閉じるんじゃなくて、
      最初から{}をセットで書いておくとミスりづらくなりますよ!(って誰かが言ってた。)

  4. 匿名 より:

    毎度演習問題の制作ありがとうございます!!
    良い復習になります。

    1
    • みじんこ より:

      コメントありがとうございます!
      演習問題は今後も付けていきますね!!

      1
  5. Yuka より:

    沢山の動画や記事を読んできたけどここの記事が一番わかりやすかったです!
    さっそく質問したいのですが…

    カードの動かし方編のDropPlaceについて、カード1をカード2の↑に重ねると、カード1がカード2の中入ってに消えなくなってしまう現象が起こります。

    カードデータの反映編のViewについて、私の場合はimageだけ表示すれば良くて、Show()の中に表示しない行を//つけたけど、結果的になぜかImageの横に「New」というテキストが表示されます。

    カードデータの反映編のフィールドの枚数に制限について、Drawの時の制限は出来たが、Dragする時にFieldによって最大枚数を制限したくて、いろいろDropPlaceで試してみたができませんでした。

    なにかいい方法を教えていただけないでしょうか。

    1
    • みじんこ より:

      Yukaさん、コメントありがとうございます!

      んー、カードが消える現象謎ですね、、
      消えるって言うのは、カード自体はあるけど見えなくなってるんですかね??
      もしくはカード自体が無くなっちゃうんですかね??
      分かりそうならまたコメントで教えて下さい!

      ちょっと今色々忙しくて他のところに答えられませんが、日曜には改めてコメント返せると思うので、また日曜辺りに覗いてみてください〜

      1
      • Yuka より:

        ご返信ありがとうございます!
        その後色々調べて問題解決できました。
        Unity本当に面白いですね!
        みじんこさんはカードを裏面切り替えとか、mirrorなどを使ってonline対戦についてもしよろしければ是非教えていただきたいです!

        1
        • みじんこ より:

          Yukaさん、日曜に返信できなくてすみません!
          解決できたのであれば良かったです!
          (自己解決出来るとは、さてはYukaさん結構出来る人ですね、、?)

          カードの裏面切り替えは、カードの一番前面に裏面の画像を貼り付けて、それをIFで表示、非表示させるのが一番簡単かと思います。
          オンライン対戦は私も作ったことないんですよね〜
          私も全くプロではなく、あくまで独学でゲームを作っているだけのひとなので、一緒に勉強していきましょう(`・ω・´)ゞ

  6. 匿名 より:

    DrawCard()のスペルが全部DrowCard()になっているので修正お願いします!

    3
    • みじんこ より:

      コメントありがとうございます!
      これは英語力がないのがバレたやつですね、、(お恥ずかしい)
      またミス等あれば教えて下さいー!

  7. からすま より:

    最近、趣味でカードゲームを作りたく、Unityをはじめました。大変参考にさせていただいております。

    実装したい処理があるのですが、どの様にコードを書けばいいか分からず…質問したいことがあります。
    既に解説頂いている内容であればご容赦ください。

    【実装した内容】
    ・ドローフェイズ、マナフェイズ、メインフェイズ、アタックフェイズと4つのフェイズを実装。
    ・ドローフェイズに入るとデッキからカードを一枚ドローして、マナフェイズに移行する。

    【実装したい内容】
    ・マナフェイズ時は手札からマナゾーンに手札を一枚置くことが出来る。(この時フィールドや墓地などにカードが置くことが出来ないようにしたい。)
    ・手札からマナゾーンに一枚置いた場合、メインフェイズに移行する。

    以上、二つの処理を実装したいのですが、どの様なコードを書けば実装出来ますでしょうか。
    お手数ですが、ご教示の程よろしくお願いいたします。

    1
    • みじんこ より:

      >からすまさん
      なるほど、デュエルマスターズ的な感じですね?

      んー、他にも効率的な実装方法があるとは思いますが、パッと思いつく方法だと、
      例えばですが、ターンフェイズを管理するフラグを作って、そのフラグによって処理を変えるようにするとかどうでしょう??

      現時点ではフィールドにカードをドロップすると、召喚処理(コストを消費して、フィールドに置かれる)が行われますが、
      その処理をIFで「ターンフェーズがメインフェーズならカード召喚処理を実行する」という風に分岐させて、
      更に「マナフェーズならマナチャージ処理を実行する」のようにフェーズ毎の分岐を追記して、
      その処理内でメインフェーズへ移行させれば、からすまさんの実装したい内容はどちらも実装出来るかと思います!

      というざっくりとした説明でしたが、どうですかね??

  8. グリグリ より:

    難しくなってきてるけど、なんとかついていけてる!

    1
  9. グミ より:

    敵フィールドを5体までに制限するコードを書き換えて、味方フィールドも5体までに制限するコードへの書き換えは現段階でおこなって大丈夫ですか?

    1
  10. クルル より:

    質問です。
    フィールに手札からモンスターを出すときに、一つ一つのマスごとに区切って場所を決めて召喚したいのですが(遊戯王の様に)同じマスに何体も出てきてしまうのは、どのように解決すればいいですかね?

    もしよろしければ返信お願いいたします。
    (わかりづらい質問でしたらすいません)

COMMENT

メールアドレスが公開されることはありません。