前回までの記事で、敵の攻撃の実装まで出来たね!
やってない人は前回の記事参照↓
今回の記事では、簡単なアニメーションを実装していくよ!!
完成形はこんな感じ↓
カードゲームの基本としてはこれで完成になります。
なので第11回まで続いたカードゲーム作成講座も、今回の記事で一旦終わりとなります!!
ここまで一緒に作ってきてくれた皆さま、本当にありがとうございました!
ではでは早速、最後の実装もやっていきましょう!!!
Contents
【全体概要】全体の流れの説明
ではまず、今回やっていく作業全体の説明をしていくよ!
今回実装する処理は下記の2つ↓
- ターン切り替え時の処理の実装
- 敵の攻撃モーションの実装
それぞれの実装はこんな感じの流れでやっていくよ↓
- ChangeTurnパネルの作成
- パネルを表示、非表示させる処理の実装
- パネルの文字列を変更する処理の実装
- DoTweeenのインポート
- DOTweenのセットアップ
- 敵のカードの攻撃時のモーションの実装
今回実装する概要が分かったら、実際に実装していこう!!
【実装&コードの解説①】ターン切り替えの処理実装
ではまずはターンが切り替わる時の処理を作成していこう!!
完成形としてはこんな感じ↓
それぞれのターンが始まるときに
「Your(もしくはEnemy) Turn」って文字の入ったパネルが表示されて、ちょっとしたら消える。
って処理を実装していくよ!
①ターン切り替え時に表示するパネルの作成
それではまずはパネルを作っていこう!
1.ChangeTurnPanelの作成
①「Canvas」を右クリックして、「UI」→「Panel」を選択して、Panelを作成する。
②作ったPanelは「ChangeTurnPanel」という名前に変更しよう!
2.Panelのパラメータ変更
さっき作ったPanelのパラメータを、右の赤で囲った数値を参考にしてサイズと色を修正しよう。
(見た目の問題なので自分の好きな値でもいいよ!)
3.ChangeTurnTextの作成とパラメータ変更
①「ChangeTurnPanel」の中に「Text」を作って、その名前を「ChangeTurnText」にしよう
②③④サイズ、文字列、パラメータを変更しよう。(正直、見た目の好みの問題なので何でも良し!)
説明通りにパネルが作れたかな?
出来たら次に進んで行こう!
②ChangeTurnPanelを表示、非表示にする
次は先ほど作った「ChangeTurnPanel」をコードで表示、非表示させていくよ!
ではまずは新しくUIを管理するクラス「UIManager」を作ろう。
1.UIManagerクラスとUIManagerオブジェクトの作成
①新しく「UIManager」クラスを作ろう
②「+」→「CreateEmpty」で新しくオブジェクトを作っておこう。名前は「UIManager」にしてね。
2.UIManagerオブジェクトへアタッチする
①今さっき作った「UIManagerオブジェクト」を選択して、
②UIManagerクラスをドラッグしてアタッチしよう。
③こんな感じになればOK!!
3.UIManagerクラスへコードの追記
UIManagerクラスの準備が出来たら早速コードを書いていこう!!
UIManagerクラスに下記のコードを全てコピペしよう↓
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class UIManager : MonoBehaviour { [SerializeField] GameObject changeTurnPanel; public IEnumerator ShowChangeTurnPanel() { changeTurnPanel.SetActive(true); yield return new WaitForSeconds(2); changeTurnPanel.SetActive(false); } } |
4.UIManagerクラスのコード解説
今回のコードのポイントは2つ!
- [SerializeField] GameObject changeTurnPanel
- SetActive()
それではそれぞれの解説をしていくよ!!
①[SerializeField] GameObject changeTurnPanel
Unity上でオブジェクトを紐付けするためのコード。
②SetActive()
SetActive()にTrueまたはFalseを入れることで、そのオブジェクトを表示または非表示に出来るよ。
つまり、これで↓
changeTurnPanel.SetActive(true)
ChangeTurnPanelを表示する。ってことになるよ!
5.Unity側でChangeTurnPanelをアタッチする
それではUnity側で「ChangeTurnPanel」オブジェクトを紐付けよう
①UIManagerをクリック
②ChangeTurnPanelを右のChangeTurnPanelのところにドラッグする
これでUIManagerクラスに「ChangeTurnPanel」を紐付けられたので、表示/非表示が出来るようになったよ!!
6.ターンの切替時にChangeTurnPanelを出すようにする
パネルを表示させるメソッドは出来たので、それをターンの切り替え時に実行する様にしていくよ!
まずはGameManagerクラスの方からUIManagerクラスのメソッドを呼び出せるように設定をしていこう!
下記コードのオレンジの部分を追記しよう↓
1 2 3 4 5 6 7 8 9 10 11 12 |
public class GameManager : MonoBehaviour { [SerializeField] UIManager uIManager; [SerializeField] CardController cardPrefab; [SerializeField] Transform playerHand, playerField, enemyField; [SerializeField] Text playerLeaderHPText; [SerializeField] Text enemyLeaderHPText; [SerializeField] Text playerManaPointText; [SerializeField] Text playerDefaultManaPointText; (省略) } |
このあとアタッチ!!
①GameManagerを選択
②UIManagerをドラッグして、右のところにアタッチしよう!!
それでは無事GameManagerクラスからUIManagerクラスのメソッドを使えるようになったなら、実際に呼び出すコードを書いていこう!!
ターン切り替えの表示を出したいタイミングはターンが切り替わる時なので、ターンを管理している「TurnCalc」メソッドに追記していこう!
下記コードのオレンジの部分を追記しよう↓
1 2 3 4 5 6 7 8 9 10 11 12 13 |
void TurnCalc() // ターンを管理する { StartCoroutine(uIManager.ShowChangeTurnPanel()); if (isPlayerTurn) { PlayerTurn(); } else { // EnemyTurn(); StartCoroutine(EnemyTurn()); // StartCoroutineで呼び出す } } |
今のままではChangeTurnPanelがずっと出ていて分かりづらいので、普段は非表示にしておこう
「ChangeTurnPanel」を選択して、右のチェックを外して非表示にしてね
ではエラーが出てないことを確認して、実際にゲームを実行してみよう!
ターンの切り替え時にChangeTurnパネルが出るようになった!!
ちゃんと表示されたら次に進もう!!
③ChangeTurnPanelのテキストをコードから変更する
ターン変更のパネルは出るようになったけど、
相手のターンにも「Your Turn」だと分かりずらい!!
ってことで、コードから文字列を変えていこう!
- 自分のターンなら「YourTurn」
- 敵のターンなら「EnemyTurn」
と表示されるようにしていくよ!!
【コードの追記】コードからテキストを変更する
それでは実際にコードを追記していこう!
UIManagerクラスにオレンジの部分を追記しよう。(全部コピペでもOK)
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 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class UIManager : MonoBehaviour { [SerializeField] GameObject changeTurnPanel; [SerializeField] Text changeTurnText; public IEnumerator ShowChangeTurnPanel() { changeTurnPanel.SetActive(true); if (GameManager.instance.isPlayerTurn == true) { changeTurnText.text = "Your Turn"; } else { changeTurnText.text = "Enemy Turn"; } yield return new WaitForSeconds(2); changeTurnPanel.SetActive(false); } } |
※ 〜isPlayerTurnの部分でエラーが出るけど、とりあえず気にしないで!!
今回追記したのは、下記の3点だね↓
- using UnityEngine.UI
- [SerializeField] Text changeTurnText
- IFの分岐文
①②はそんなに重要ではないので、③をざっくり説明するよ!!
※一応、①と②をめっちゃ軽く説明すると、
①はテキストとかUIをいじる時に必要なコード
②は「changeTurnText」のテキストをUIManagerクラスに紐付けるコード
って認識でOK。
【コード解説】IFの分岐文について
そんなに難しくはないと思うけど、③の分岐文だけ抜き出して解説するよ!
if (GameManager.instance.isPlayerTurn == true)
{
changeTurnText.text = “Your Turn”;
}
else
{
changeTurnText.text = “Enemy Turn”;
}
ここでやってる処理を日本語で言うと、
「もし自分のターンだったら、changeTurnテキストをYour Turnにするけど、
もし相手のターンだったら、changeTurnテキストをEnemy Turnにするよ」
ってことだよね。
ちなみにさっきコードを追記した時にエラーが出てる理由としては、
GameManagerクラスが持ってる変数「isPlayerTurn」がPublic(他のクラスからも使える状態)になってないからだよ。
なので次はエラーを解消していこう!!
【コード修正】isPlayerTurnをPublicにしよう
では下記コードのように、GameManagerの「isPlayerTurn」をPublicに変更しよう↓
1 2 3 4 5 6 7 8 9 |
public class GameManager : MonoBehaviour { (中略) public int playerManaPoint; // 使用すると減るマナポイント public int playerDefaultManaPoint; // 毎ターン増えていくベースのマナポイント public bool isPlayerTurn = true; // Publicへ変更 List<int> deck = new List<int>() { 1, 2, 3, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 }; (省略) |
そしたらエラーが消えたことを確認して、最後にUnity側の設定をしていこう!
①UIManagerを選択
②ChangeTurnTextを右の赤枠のところにドラッグしてアタッチ!!
それではゲームを実行してみよう!!
表示される文字が変わった!!!
自分のターンには「Your Turn」、
敵のターンには「Enemy Turn」と表示されるようになったかな??!
うまく出来たら次へ行こう!!
【実装&コードの解説②】攻撃モーションの実装
ではでは最後の実装をしていくよ!
攻撃モーションを実装できればこんな感じにかなりゲームらしくなるので、頑張ってやっていこう!!
やっていく順番としてはこんな感じ↓
- アセットストアから「DOTween」をインストールする
- DOTweenのセットアップ実施
- 敵のカードの攻撃時にモーションを付ける
DOTweenを使えるようになればかなり色々なことが出来るようになるので、
自分でも色々試しながら実装してみてね。
ではやっていこう!!!
①アセットストアから「DOTween」をインストールする
まずは最強アセットのひとつ、「DOTween」をインストールしていこう
※ ちなみに無料です。一応ね(笑)
下記のURLにダウンロードページがあるので、
「マイアセットに追加する」→「インポート」って押して行けばOKだよ!!
(微妙に文言が違う可能性あり)
https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676
そしたらUnityのバージョンによって変わるけど、
①②「Window」→「PackageManager」をクリック
③みたいな感じで別のウィンドウが出てくる
④DOTweenを選択して、
⑤「Import」をクリックするとまた別のウィンドウが出てくるから更に「Import」をクリック!!!(必要ないものはチェックを外してもいいよ!今回はそのままやっていきます)
そしたらDOTweenのインストールは一段回は完了!
次はセットアップしていくよ!
※ 表示してるのはMacの画面になります。
(Windowsを使ってる人で「アセットストアのインポートよくわからないんですが、、(´;ω;`)」って悲しみに暮れてる人はコメントで教えて下さい。追記するので!!(調べた方が早いんだが、、?って説もあり。))
②DOTweenのセットアップ
インポートが終わると勝手に下のウィンドウが出てくるので、「Open DOTween Utility Panel」をクリックしよう↓
そしたら次に「Setup DOTween」をクリック↓
そしたらこんな感じの画面↓が出てくるからちょっと待とう
上の画面の「Waiting〜」ってのが消えたら「Apply」を押そう
そしたらセットアップも完了したので、バツを押して消してOK!
③敵のカードの攻撃時にモーションを付ける
それではDOTweenのセットアップも終わったので、
次から実際にコードを書いて敵の攻撃モーションを作って、攻撃時に動くようにしていくよ!!
1.【コードの追記】CardMovementクラスへ攻撃モーションの追記
CardMovementクラスのメソッドの一番下あたりに下記のオレンジの部分のメソッドを丸ごと追記しよう↓
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using DG.Tweening; public class CardMovement : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler { (省略) public IEnumerator AttackMotion(Transform target) { Vector3 currentPosition = transform.position; cardParent = transform.parent; transform.SetParent(cardParent.parent); // cardの親を一時的にCanvasにする transform.DOMove(target.position, 0.25f); yield return new WaitForSeconds(0.25f); transform.DOMove(currentPosition, 0.25f); yield return new WaitForSeconds(0.25f); transform.SetParent(cardParent); // cardの親を元に戻す } } |
2.【コードの解説】さっき追記した攻撃モーションのコードについて
今回追記した内容は大きく分けてこの3つ
- 現在の位置の取得
- 対象のゲームオブジェクトを動かす&戻す
- Cardの親要素を一旦Canvasに変更する&戻す
それぞれについてざっくりと説明していくよ!!
ざっくりコード解説
ざっくり解説すると、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public IEnumerator AttackMotion(Transform target) { Vector3 currentPosition = transform.position; // ① cardParent = transform.parent; // ① transform.SetParent(cardParent.parent); // ② transform.DOMove(target.position, 0.25f); // ③ yield return new WaitForSeconds(0.25f); transform.DOMove(currentPosition, 0.25f); // ④ yield return new WaitForSeconds(0.25f); transform.SetParent(cardParent); // ⑤ } |
- 現在のcardの位置と親要素の取得
- cardの親要素をcardParent.parent(=Canvas)に変更
- cardをtarget.position(=攻撃対象の場所)へ移動する
- target.positionにいるcardをcurrentPosition(=cardの元の場所)に戻す
- cardの親要素をcardParent(=EnemyField)に戻す
こんな感じだね!!!
コードと上の解説を読んで、
「ははん、なるほどな」って分かった人は読み飛ばしてOKだけど、
「よくわからんちんです。(๑ ´•.̫ •`๑)」
ってひとはコードの詳細も書いたので読むこと推奨↓
※DOTweenの使い方も解説してるので、DOTweenを初めて使う人は読むべし!!!
コード解説① 現在位置の取得
ではまず現在位置の取得の説明をしていくよ!
該当部分だけ抜き出すとこの部分だね↓
Vector3 currentPosition = transform.position;
cardParent = transform.parent;
1行目のVector3ってのは位置情報を保持できる型って認識でOK
要はここでは「currentPositionって変数に、cardのポジション情報を入れておくよ!!」ってこと。
2行目は前にも出てきたけど、「cardParentって変数にcardの親要素を入れといて!」って感じ。
今回の場合で言うと、cardの親要素はEnemyFieldなのでcardParentはEnemyFieldが入るよ!
、、、いや、そもそもなんでそんな事やってんの??(´・ω・`)
って思った人はちゃんと考えながら進めてて偉い!
でもこのあと説明するので、一旦「何か知らんけど、今の位置情報を保持してるのね。」って認識でOKだよ
コード解説② 対象のゲームオブジェクトを動かす
では次に実際にカードを動かすコードの説明をしていくよ!!
ちなみにここが、
今回のコードの一番大事なところ!!
だよ。
ゲーム作りで今後絶対に使うことになるであろうDOTweenの基本的な使い方をよく覚えておこう!
では該当部分を抜き出すとこの部分↓
transform.DOMove(target.position, 0.25f);
yield return new WaitForSeconds(0.25f);
transform.DOMove(currentPosition, 0.25f);
yield return new WaitForSeconds(0.25f);
(途中に挟まってるWaitForSecondsは、単に0.25秒処理を止めてるだけなのであんまり気にしないで良いよ。)
大事なのは、transform.DOMove(場所, 0.25f)のところ!!!
これはcardの位置を0.25秒で指定の場所に動かすよ!!ってコードになるよ。
なので
このコードの場所と時間を変えるだけで、
動かす場所と速度を変えられるのだ!
それを踏まえて今回追記したコードを見てみると、
transform.DOMove(target.position, 0.25f);
これは、target.position(攻撃先のカードの場所)に0.25秒で動かすよ!ってこと。
でもこれだけだと攻撃先に動いたまま元の場所に戻ってこれないので、
transform.DOMove(currentPosition, 0.25f);
この処理を書いて、0.25秒でcurrentPosition(さっき説明した、移動前に取得した元のカードの場所)に戻る!!ってことをしているよ。
ちなみに「DOMove」が動かしますよ〜。ってコードなだけで、他にも色々出来るよ。
例えば「DOMove」を「DORotate(回転させるコード)」に書き換えるとCardが回転するし、
「DOScale(大きさを変えるコード)」を使えば大きさの変更も出来るよ!!
そんな感じに色んな事が出来るDOTweenは超便利なので色々試してみてね!!
ちなみにDOTweenを使う時には、使用するクラスのネームスペースに
using DG.Tweening
の記載が必要だから忘れないようにね!!
コード解説③ 親要素の変更
最後に親要素の変更処理の説明!
これは単純に見た目の問題で追記した処理になるよ。
transform.SetParent(cardParent.parent); // cardの親を一時的にCanvasにする
(省略)
transform.SetParent(cardParent); // cardの親を元に戻す
1行目は、cardの親要素をcardParent.parentにしているよ。
(この場合で言うと、cardParentはEnemyField、その親要素はCanvasなのでcardの親要素をCanvasにしてるってこと)
2行目は、cardの親要素をcardParet、つまりEnemyFieldにしているって事!
それだけ!!
【コードの追記】敵の攻撃時に攻撃モーションを実行させる
さて、敵の攻撃時のモーションを作ることは出来たけど、
まだそれを実行するコードを書いてないので次にそれを書いていこう!!!
GameManagerクラスのEnemyTurnメソッドの中の、敵カードが攻撃する処理にオレンジ行を追記をしよう↓
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
IEnumerator EnemyTurn() { (中略) while (Array.Exists(enemyFieldCardListSecond, card => card.model.canAttack)) { (中略) if (playerFieldCardList.Length > 0) // プレイヤーの場にカードがある場合 { int defenceCardNumber = UnityEngine.Random.Range(0, playerFieldCardList.Length); CardController defenceCard = playerFieldCardList[defenceCardNumber]; yield return StartCoroutine (attackCard.movement.AttackMotion(defenceCard.transform)); CardBattle(attackCard, defenceCard); } else // プレイヤーの場にカードがない場合 { AttackToLeader(attackCard, false); } (省略) } |
追記した内容はこれだけ↓
yield return StartCoroutine (attackCard.movement.AttackMotion(defenceCard.transform));
さっき作った攻撃時のモーション(AttackMotionメソッド)を攻撃する前に仕込んだだけ。
ちなみにStartCoroutineの前にyield returnを付けているのは、
「この処理が終わるまで次の処理は進めないでね!!」って意味だよ。
それでは実際にゲームを実行してみよう!!
敵のカードが動き出した!!!
と、まあこんな感じに動くと一気にゲームっぽくなるよね。
他にも色々出来ることはあるので、色々試してみてね!!
【演習】バグ修正
ではでは最後に復習を兼ねて演習やっていきましょう!!
今回やっていただきたいのはこの2つ!!
- リーダーに攻撃した時にも攻撃モーションを付ける
- ChangeTurnPanelを出すタイミングを調整する
完成形としてはこんな感じ↓
①の場合
こんな感じにプレイヤーに対して攻撃する時にも、攻撃モーションが出るように修正してみよう!!
②の場合
ちょっと変化が分かりづらいかもしれないけど、
今のままでは、ChangeTurnPanelが出てる最中に敵のカードに攻撃可能の緑の枠が付いてしまっているので、
上の動画のように、ChangeTurnPanelが出終わってから、ターンの処理が始まるように修正してみよう。
修正する方法の見当も付かないなあ、、
困った…
ってひと向けにヒントを書いておくと、
- プレイヤーに攻撃しているコードを探そう
- 攻撃モーションを付けるコードを追記しよう
- 攻撃先(ターゲット)の場所をUnity側でアタッチしよう
- ChangeTurnPanelが出終わるまで処理を止めるように修正しよう
- それに伴って修正箇所が出てくるので、修正しよう
こんな感じかな!!
ではでは次から実際にバグ修正の解説をしていくので、自分なりにやってみてから進もう!!
【演習】バグ修正解説
さあ皆さん最後の演習は出来たかな??
それでは修正方法の解説をしていくよ!!
①プレイヤーへの攻撃時にも攻撃モーションを付ける方法
実際にやることは3つだけ!
- リーダーの場所(Transform)の変数を作る
- リーダーへ攻撃する前に攻撃モーションを実行する
- リーダーの場所をUnity側で紐付ける
それでは順番にやっていこう!!
①リーダーの場所についての変数を作る
まずはリーダーの場所についての変数がないので追記していこう!!
GameManagerクラスの上の部分にオレンジ行を追記しよう↓
1 2 3 4 5 6 7 8 9 10 11 |
public class GameManager : MonoBehaviour { [SerializeField] UIManager uIManager; [SerializeField] CardController cardPrefab; [SerializeField] Transform playerHand, playerField, enemyField; [SerializeField] Text playerLeaderHPText; [SerializeField] Text enemyLeaderHPText; [SerializeField] Text playerManaPointText; [SerializeField] Text playerDefaultManaPointText; [SerializeField] Transform playerLeaderTransform; |
これでリーダーの場所についてコードから指定出来るようになったよ!
②攻撃モーションの追記
次はリーダーへの攻撃を処理しているコードの前に、攻撃モーションの実行コードを追記しよう。
GameManagerクラスのEnemyTurnの該当箇所に、オレンジの部分を追記しよう↓
1 2 3 4 5 6 7 8 9 10 11 12 |
if (playerFieldCardList.Length > 0) // プレイヤーの場にカードがある場合 { int defenceCardNumber = UnityEngine.Random.Range(0, playerFieldCardList.Length); CardController defenceCard = playerFieldCardList[defenceCardNumber]; yield return StartCoroutine (attackCard.movement.AttackMotion(defenceCard.transform)); CardBattle(attackCard, defenceCard); } else // プレイヤーの場にカードがない場合 { yield return StartCoroutine(attackCard.movement.AttackMotion(playerLeaderTransform)); AttackToLeader(attackCard, false); } |
追記した内容について一応説明しておくと、
ほぼカードへの攻撃時に追記した攻撃モーション実行コードと同じものだよね。
ただ、移動先はカードではなくプレイヤーなので、引数には「playerLeaderTransform」(=プレイヤーのリーダーの場所)を入れているよ。
③Unity側でアタッチする
それでは最後にUnity側で「playerLeaderTransform」をアタッチ!!
①GameManagerをクリック
②PlayerLeaderをドラッグして、アタッチ!!!
それではゲームを実行してみよう!!
こんな感じにリーダーへの攻撃時にもモーションが付いたらOK!!
②ChangeTurnPanelを出すタイミングを調整する
これも実際にやることは3つだけ!
- ShowChangeTurnPanelメソッドをyield return StartCoroutineに変更
- yield returnにしたので、TurnCalcメソッドをIEnumeratorにする
- TurnCalcメソッドの実行をStartCoroutineに変更する(2箇所)
それでは順番にやっていこう!
①②yield return StartCoroutineに変更する & それに伴う変更
ChangeTurnPanelの表示/非表示のタイミングが変になってしまっているのは、
ShowChangeTurnPanelメソッドが終わり切る前に次の処理に進んでしまっているのが原因だよね。
なのでStartCoroutineの前に、yield returnを追記しよう!
yield returnにするとそのメソッドの定義をIEnumeratorにする必要があるので、そこも合わせて修正しよう。
GameManagerクラスのTurnCalcメソッドの該当箇所を修正しよう。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
IEnumerator TurnCalc() // ターンを管理する { yield return StartCoroutine(uIManager.ShowChangeTurnPanel()); if (isPlayerTurn) { PlayerTurn(); } else { //EnemyTurn(); // コメントアウトする StartCoroutine(EnemyTurn()); // StartCoroutineで呼び出す } } |
修正できたら、エラーが出ていないことを確認して次に進もう!!
③TurnCalcメソッドの実行をStartCoroutineに変更する(2箇所)
さっきTurnCalcメソッドの定義をvoidからIEnumeratorに変更したことで、
今のままだとメソッドが動かなくなっちゃってる!!
そんな訳なので、TurnCalcメソッド実行時のコードも修正しよう。
修正箇所は2つ!!
下記コードの部分と、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
void StartGame() // 初期値の設定 { enemyLeaderHP = 5000; playerLeaderHP = 50000; ShowLeaderHP(); /// マナの初期値設定 /// playerManaPoint = 1; playerDefaultManaPoint = 1; ShowManaPoint(); // 初期手札を配る SetStartHand(); // ターンの決定 StartCoroutine (TurnCalc()); } |
下記コードの部分!!
1 2 3 4 5 |
public void ChangeTurn() // ターンエンドボタンにつける処理 { isPlayerTurn = !isPlayerTurn; // ターンを逆にする StartCoroutine(TurnCalc()); // ターンを相手に回す } |
ではでは修正できたかな??
それではゲームを実行してみよう!
こんな感じにChangeTruePanelが消え終わってから、ターンの処理が始まっていればOK!!
今回の記事も長くなってしまったけど、上手くゲームを作ることが出来たかな??
皆さま大変お疲れ様でした!!!
【最後に】まとめと今後の記事について
それでは最後に今回の記事で大事だったことをまとめていくよ!!
・SetActiveでオブジェクトを表示/非表示にする
・Coroutineの使い方
・DOTweenのインストール方法&使い方
このあたりは他にゲームを作るときにも参考になるところなので覚えておいて損はないよ!
特にDOTweenなんて色んな事が出来るので、バチバチ色んなことを試しながら習得しちゃって下さい!!
感謝とか感謝とか、、
そして最後に大事なお話。
本記事をもって、カードゲーム作成解説記事シリーズは完結とさせて頂きます、、!!
更新頻度がものすごく遅く、書き終えるまで2年近く掛かってしまいましたが、
何とか予定していたところまでは書き切ることが出来ました。
これは本当にコメントを書いてくれた皆様のお陰としか言いようがないです。
改めてお礼を言わせて下さい。本当にありがとうございました。
何度も記事の更新を放置しました。
何度も寄り道してました。
散々待たせているのに、それでも読んでくれてる皆さんが
「参考なりました!」とか、
「わかりやすかったです」とか、
「更新待ってます!!」とかとか
いつも温かいコメントを書いてくれてたので、
その度「よし、続き書くか!」って戻ることが出来ました。
この解説記事のコメントについては、ほんとに純度100%で嬉しいコメントしかなかったので、いつもコメントを見るのが嬉しかったです。(みんな民度高いよね。どうした??笑)
アンチ的なコメントが一切なかったのも個人的には誇りです。
正直、私自身ゲームを作るプロではないですし、誰かに直接教えてもらった訳でもないので、
ゲーム作成方法については専門の方から見たら杜撰な部分は多いと思います。
でもだからこそ、完全初心者のひとが「分かりやすい!!」って言ってくれるような記事が書けたんだと思ってます。
この解説記事は、
「ゲーム作りたいな!!」って思ったけど、
ゲームの作り方解説サイトの解説の意味が分からなくて3秒で挫折した、
当時、PCすら持っていなかった大学2年の私を救うために書いた記事です。
これで当時の私も救われたことでしょう。成仏してください。
個人的な趣味で書き始めたものでしたが、
同じように困っているひとの手助けも出来たみたいでよかったです!
これからもお互いゲーム作りを楽しんでやっていきましょう!!
今後について!
さっきから書いているように、カード解説記事は一旦これで終わりとなります。
ただ正直、
「まだまだカードゲームとしては甘々だぜ!!!」
って思うので、続きの解説記事もどんどん書いていくよ!!!!
なのでカードゲーム作成解説記事【基礎編】が終わり、
次はカードゲーム作成解説記事【発展編】を始めていくよ!!
※ 発展と言っても、難しくなるわけじゃないのでご安心を!
実装内容としては、
- 効果持ちカードの実装
- 速攻(スピードアタッカー)
- カードのドロー
- トークンカードを手札に加える
- トークンカードの召喚
- リーダーのライフ回復、ライフダメージ
- スペル(呪文)カードの実装
- カードのドロー
- トークンカードを手札に加える
- トークンカードの召喚
- リーダーのライフ回復、ライフダメージ
- マナポイント(PP)ブースト
- 効果音の実装
- ドローの音
- 攻撃時の音
- カードの見栄え向上
この辺りを解説する予定だよ!!(あくまで現時点の予定なので悪しからず)
★ 2022/8/5 追記 ★
実際作るゲームとしてはこんな感じ!!
でも最後に注意点!
【発展編】の記事については有料での公開とさせて頂きます。
ブログ書くのってめちゃめちゃ時間かかるんですよ、、
普通に会社員しながらブログ書いているので、正直このペースじゃ
【発展編】を書き終わるのは3年後だな、、
では3年間お待ち下さい!!
ってなりかねないというか、そんな未来しか見えないです。
なのでモチベーション維持のため、有料での公開とさせてもらう事となりました。
そんな訳なので、わたくしみじんこの事を「応援してもいいかな!」って方のみご検討下さい!
そして気になる価格ですが、一般のゲーム作成の本一冊よりも安い値段にする予定です。
(というか本より高いと「本買うわ!!」ってなるよね。笑)
ちなみに【発展編】の公開時期としては、来月の2月 8月中(だいぶ伸びてしまって申し訳なし。。)を予定しております。
※これについては、進捗状況をこのブログで逐一ご報告する予定なので、検討頂ける方はたまにブログを覗きに来てくださいな!!
ただ、まだまだ未定な部分が多いので、こちらについてもご意見頂けるとありがたいです!
★ 2022/9/4 追記 ★
ついに記事リリースいたしました!!!
「買う前にどんな内容なのかを知りたい!!」って方はこちらに記事内容を紹介した記事を書きましたので、ご参照ください!
重ね重ねですが、本講座を最後まで読んでいただきありがとうございました。
今までコメントを書いて応援してくれたあなたには勿論、
コメントは書いてないけど本講座を最後まで付き合ってくれたあなたにも、
よきゲーム制作ライフが送れることを祈っております。
また機会があれば、どこかでお会いしましょう!
ではでは今回の記事はこれでおわりっ!!
・参考にさせて頂いた動画
[Unityゲーム開発講座] シャドバ風!?カードゲームの作り方 #1 UIの実装
全11回の投稿ありがとうございました!
全くの初心者でコピペばかりでしたが、初心者なりにゲームの作り方を勉強できてとても面白かったです。
今後もC#を勉強していって自分でゲームを作れるように頑張りたいと思います。
今後も投稿頑張ってください。
>メイソンさん
こちらこそ、コメントを書いていただきありがとうございます。
初心者の方がいきなりカードゲームを作るのは難しかったとは思いますが、楽しんで勉強して貰えたなら良かったです!!(∩´∀`)∩
ここまで来れたなら、もう自分の作りたいゲームも作れるかと思いますので、今後とも楽しみながら是非ゲームを作っていってください!
そして作ってる途中で基本に立ち戻りたくなったら、またこの記事を見ながらゲームを作ってみて下さい!新たな気づきもあると思うので!
ではではメイソンさんのゲーム作成ライフを応援しておりますー!!
基礎編の投稿ありがとうございました。お疲れ様です。
このブログのおかげでUnity初心者でもカードゲームっぽいものが作れました。
発展編を気長に待ちつつも自分でも機能追加していこうと思います。
>ふぇっとち~ねさん
基礎編お疲れ様でしたー!
最後までやっていただきありがとうございます!!
発展編は出来るだけ2月中に完成させる予定なので、もう少々お待ち下さい_(._.)_
はい、今回作ったものを自分の好きな様に機能追加、変更するだけでもかなり力が付くと思うので、ガシガシいじってみてください!
投稿ありがとうございました。楽しすぎて4日間でここまで来ちゃいました。発展編楽しみにしています。
効果持ちカードがどこを弄ればいいのか早く知りたいです!
>ドラクさん
コメントありがとうございます!!
4日で終わらせてしまうとは凄まじいですね笑
でも楽しんで貰えたなら良かったです!
発展編は3月中にはお見せ出来るかと思うので、
お暇な時に
進捗日記でも見つつ、生暖かい目でもう少々お待ち下さい!
とてもとても参考になる記事でした。まだまだ自分での理解が甘い部分もあって、解説がないと自力のゲームが作れるかは不安しかないですが…この調子で頑張っていきたいです!みじんこさんのこともこれからも応援させてもらいます!
>じゃすてぃそさん
最後の記事まで来るの早いですね!笑 お疲れ様でした( ´ ▽ ` )ノ
正直、初心者の方が一度で記事の内容を全て理解し切るのは難しいと思うので、
今回作ったものをベースにして、じゃすてぃそさんの作りたいゲームに作り変えていったりしてみて下さい!
それだけでかなり力になるかと思うので!!
ではではお互い、引き続きゲーム制作を楽しみながらやっていきましょう!
全11回の基礎編の投稿ありがとうございました。とてもわかりやすい記事で参考になりました。この記事のおかげで、初心者から一歩進めた気がします。中学生なもんで発展編を読むことは出来ないけど、今までお世話になりました。
>イルカさん
コメントありがとうございます!!
お力になれたみたいで良かったです( ´∀`)
中学生でここまで来るとは将来有望ですね、、笑
今後もゲーム制作楽しみながら続けてくださいね!
>中学生なもんで発展編を読むことは出来ないけど、今までお世話になりました。
そうですよね、、クレジットカードとかないですもんね、、m(_ _)m スマヌ…
高校生になって、バイトして、それでもまだ興味があったらまた来てくださいな!
(もし「どうしても!」ってことであれば方法は考えるので言ってください!)
返信ありがとうございます。これからもゲーム作りを楽しんでいこうと思います。そして、お気遣いありがとうございます。僕が目指している高校はバイト禁止と聞いているので高校にいっても記事を読めないかもしれません。なので、もしいい方法があるならお願いしたいです。よろしくお願いします。
>イルカさん
返信遅くなってすみません、、!
んー、銀行振り込みとかなら対応出来るかと思いますので、それでも良ければ、、?
考えてくださりありがとうございます。申し訳ないですが今回は一旦見送ることにしようと思います。記事の完成に向けて頑張ってください!
了解しました!!
また機会があったらお願いします( ´∀`)
こんにちは、吉田智久さん
おかげさまで11編まで、基礎編すべて終えることができました。 ほんとうに、ありがとうございます。
もうすぐ発展編も買って読むようです。
ところが、一つ疑問点が生じました。
11編すべて終えて、テストを始めるとplayerHandでplayerFieldにはドラッグモーションができますが、
その後、攻撃をするときはドラッグモーションが生じません。
ただ、敵カードやリーダーに対する攻撃はきちんと入ることから、他のものはきちんと作動するようですが、
私が何を逃したのでしょうか。
*翻訳機を使いました。
すみません。質問が間違っています。
9編のマナコスト実装編で3回エラーを修正するコード(CardMovementのクラスコード修正)を行います。
コスト不足で使えないカードが敵リーダーのパネルにピタッと貼ってしまいます。
修正する前です。
CardController card = GetComponent();
canDrag = true;
if (card.model.canUse == false) // マナコストより少ないカードは動かせない
{
canDrag = false;
}
if (canDrag == false)
{
return;
}
このコードはこのようなエラーは発生していませんが、なぜでしょうか?
+ そして掲示板が間違っているようですね。 すいません.
>sinamonさん
んー、こちらの回答は難しいですね。。
敵リーダーのパネルに張り付くような処理はしてないはずなので、、
ちなみに張り付くと言うのは、カードが敵リーダーのパネルの子要素になっていると言うことですか??
はい、もし必要でしたら映像を撮ってリンクを差し上げます。
敵リーダPanelの子要素になるような処理は書いてないので何かしらミスがありそうですね、、
もし可能であればその事象が起きている映像を送ってもらえますか??
何か分かるかも知れないです。
https://drive.google.com/file/d/1cAFPsANb-Vdaii3wYQlw1npJV7RUd3H7/view?usp=sharing
はい、こちらです。
何卒、よろしくお願いします.
んー、なるほど。。
CardがCanvasの子要素になったままreturnされてるのが原因のように見えますね。
OnBeginDragメソッドの中で 「if (canDrag == false)」の分岐文があると思うのですが、その部分のコードは正しく書かれてないかもですね。
第9回の最終的にはOnBeginDragメソッドは以下のコードになるはずなのですが、そうなってるか確認してみてください↓
public void OnBeginDrag(PointerEventData eventData) // ドラッグを始めるときに行う処理
{
CardController card = GetComponent<CardController>();
canDrag = true;
if (card.model.FieldCard == false) // 手札のカードなら
{
if (card.model.canUse == false) // マナコストより少ないカードは動かせない
{
canDrag = false;
}
}
else
{
if (card.model.canAttack == false) // 攻撃不可能なカードは動かせない
{
canDrag = false;
}
}
if (canDrag == false)
{
return;
}
cardParent = transform.parent;
transform.SetParent(cardParent.parent, false);
GetComponent<CanvasGroup>().blocksRaycasts = false; // blocksRaycastsをオフにする
}
アップしていただいた通りに修正してみると、これ以上敵リーダーについてしまう現象は現れません。 ありがとうございました!
あと1つ気になることが、応用編だと1枚から9枚までアップされたのですか? それともまだ未完成ですか?
お、解決出来たみたいでよかったです!( ´∀`)
応用編はもう完成してますので、ご興味あればご検討ください!
>sinamonさん
最後までお疲れ様です、早いですね!笑
こちらこそお役立ち出来てよかったです。
質問の回答ですが、
敵の攻撃には攻撃モーションを実装していますが、
Player側のカードには攻撃モーションを実装していないので、
その動きで想定通りになります。
と言う回答で大丈夫ですか??
みじんこさん ありがとうございます カードを他のものに変えたりしてオリジナルっぽさを出して遊んだりしてます まだまだ理解が及ばないところが多いですが、復習して応用編にもチャレンジしてみたいと思います。
>もりのくまさん
基礎編の最後まで来たんですね!お疲れ様でした( ´∀`)
どんどんいじくってみて、自分の好きなようなゲームにしてみてください、どんどん理解も進むと思います!
はい、応用編ではもっと色んなことが出来るように解説しているので、ご興味あればチャレンジしてみてください〜
市販の入門書を一通り読んでから「で、結局何すればゲーム作れるの?」と途方に暮れていたところにこの講座に出会いました。
今日、無事に基礎編を終えることが出来ました。
本当に分かりやすく適度に難しく適度に簡単で、ものすごく勉強になりました。
この講座を書いていただいてありがとうございました。