こんにちは、みじんこと申します。
本記事では前記事から引き続き、Unityでのオンライン対戦機能の実装方法を説明します。
そちらをまだ見ていない方は、実施後にこの記事に進んで頂けると良きかと思います!
本記事では下記の流れにて、カードゲームにおけるオンライン対戦機能の実装方法を解説していきます。
※本記事では⑤の「カードの攻撃処理の実装」のみ解説していきます。
- 前準備とカードの作成
- UIの作成、カードの生成実装
- カードの種類の実装
- カードの移動とドロップ処理の実装
- カードの攻撃処理
- カードバトル処理の実装
- リーダーへの攻撃処理の実装
- オンライン機能の導入と実装
本記事の完成形としてはこんな感じですね。
カード同士でバトルし合って、バトルで負けた方は破壊されるようにしていきます!
あとはリーダーへ攻撃したら、
ログにその内容が出力される!
というような処理を実装していきます。
それでは今回もやっていきましょう!!
攻撃処理の実装じゃ!!
Contents
【実装概要】本記事で実装する内容について
さて今回のカードバトル処理の実装は、こんな流れにて実装していきます!
- 攻撃された時にバトルが始まる処理の実装
- カードバトル関数の作成
- 【演習】リーダーが攻撃されたことを検知する処理の実装
まずは攻撃された時にバトル処理が実行されるようにして、
そのあとに今回の肝になる「カードバトル関数」を記載してカードバトルの処理を実装!!
という流れで進めていくよ!!
最後に「リーダーが攻撃された処理」については、
演習として皆さまにやってもらうので、カードバトルの処理を理解しながら進めていってね。
では始めていこう!
手順①:攻撃された処理の実装
それではまず、攻撃されたことを検知するスクリプトを作っていこう!!
「AttackedCard」スクリプトを新規で作成して、
作れたら下記のコードを丸ごとコピペしちゃいましょう!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; // 攻撃される側のコード public class AttackedCard : MonoBehaviour, IDropHandler { public void OnDrop(PointerEventData eventData) { // attackerを選択 マウスポインターに重なったカードをアタッカーにする CardController attackCard = eventData.pointerDrag.GetComponent<CardController>(); // defenderを選択 CardController defenceCard = GetComponent<CardController>(); // バトルする(一旦、ログで出力) Debug.Log(attackCard.model.name + "が攻撃してきた"); Debug.Log(defenceCard.model.name + "が攻撃された"); } } |
1-1.コードの説明
先に進む前に、ざっくりコードの内容の説明をするよ!
ここで重要になるのは「OnDrop」メソッド。
あれ?「OnDrop」ってなんか聞いたことあるぞ??
って人は素晴らしい!
前回解説した「DropField」スクリプトでも使ったメソッドですな!!
「DropField」は、
カードを“フィールドにドロップした時”に
処理が動くようにしたけど、
今回の「AttackedCard」は、
カードを“カードの上にドロップした時“に
処理を動かすようにしていくよ!
では実際のコードを踏まえて説明をしていくと、
カードの上に別のカードがドロップされると、OnDrop関数が起動して、
1 2 |
// attackerを選択 マウスポインターに重なったカードをアタッカーにする CardController attackCard = eventData.pointerDrag.GetComponent<CardController>(); |
↑これでマウスの下にあるカードを攻撃する側のカード(attackCard)に設定。
1 2 |
// defenderを選択 CardController defenceCard = GetComponent<CardController>(); |
↑これでドロップされた方のカードを攻撃される側のカード(defendCard)に設定。
という処理をしているよ!!
1-2.スクリプトのアタッチ
それでは攻撃されたことを検知するスクリプトが作れたので、
こいつをカードプレハブにアタッチしちゃいましょう!!
- CardプレハブをOpenPrefabする
- AddComponentで「AttackedCard」を追加!!
これでアタッチは完了。
1-3.ゲームの実行
それはゲームを実行して、攻撃されたことを検知できるか確かめてみましょう!
2枚をフィールドに出して、、
「Slashing」を「FireSpell」にドロップ!!!
ログを見ると、「攻撃してきたカード」と「攻撃されたカード」が出力されてる!!
ってなればOKです!!
手順②:カードバトル関数の記載
それでは次に、今回のメイン「カードバトル処理」を実装していきます!
やることとしては、
GameManagerに「CardBattleメソッド」を書いて、
攻撃された時に、そのメソッドをAttackedCardから実行させる!!
という感じですね。
早速やっていこう!
2-1.コードの記載(GameManager)
ではまず「GameManager」スクリプトにカードバトルの処理を書きたいので、
下記コードのハイライト箇所を追記しちゃってください!!
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 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class GameManager : MonoBehaviour { // CardController型に変更 [SerializeField] CardController cardPrefab; // カードプレハブ // カードの生成場所 [SerializeField] Transform playerHand; [SerializeField] Transform playerField; [SerializeField] Transform enemyHand; [SerializeField] Transform enemyField; // シングルトン化 public static GameManager instance; private void Awake() { if (instance == null) { instance = this; } } (省略) public void CardBattle(CardController attackCard, CardController defenceCard) { // 攻撃側のパワーが高かった場合、攻撃されたカードを破壊する if (attackCard.model.power > defenceCard.model.power) { Destroy(defenceCard.gameObject); } // 攻撃された側のパワーが高かった場合、攻撃側のカードを破壊する if (attackCard.model.power < defenceCard.model.power) { Destroy(attackCard.gameObject); } // パワーが同じだった場合、両方のカードを破壊する if (attackCard.model.power == defenceCard.model.power) { Destroy(attackCard.gameObject); Destroy(defenceCard.gameObject); } } } |
パっと見、追記箇所が長いですが注目するべきは下記の2ヶ所だけ!!
- GameManagerのシングルトン化
- CardBattleメソッドの追記
それぞれざっくりと説明していきます!
【コード解説①】シングルトン化って??
めちゃくちゃざっくり一言でいうと、
シングルトン化とは、「このインスタンスはこれ1つだけだよ!!」ってすることです。
「GameManagerはこの1つだけだよ!!」とすることで、
簡単に他のスクリプトから参照出来るようにしているのです!
今回で言うと、
これでAttackedCardスクリプトから、
簡単にGameManagerのメソッドが使えるようになった!ってこと。
要はシングルトン化しておけば、
[SerializeField] GameManager gameManagerってコードに書いて、Unity側で「GameManager」をアタッチして〜〜〜〜とかやらなくても、
どこからでも使えるようになるよ!!便利だね!!ってイメージでOKです。
【コード解説②】CardBattleメソッドについて
さてこちらが今回の肝。
カード同士のバトル処理です!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public void CardBattle(CardController attackCard, CardController defenceCard) { // 攻撃側のパワーが高かった場合、攻撃されたカードを破壊する if (attackCard.model.power > defenceCard.model.power) { Destroy(defenceCard.gameObject); } // 攻撃された側のパワーが高かった場合、攻撃側のカードを破壊する if (attackCard.model.power < defenceCard.model.power) { Destroy(attackCard.gameObject); } // パワーが同じだった場合、両方のカードを破壊する if (attackCard.model.power == defenceCard.model.power) { Destroy(attackCard.gameObject); Destroy(defenceCard.gameObject); } } |
とは言っても大した処理ではなくて、
単純に引数(CardBattleの後ろに書いてあるattackCardとかのこと)で、
攻撃側のカードと攻撃される側のカードの情報を取得して、
その情報を元にパワーを比べて、パワーが低い方のカードを破壊するのじゃあ!!!
ってだけの処理ですね。
※説明が足りなかったらコメントくださいな!
2-2.コードの記載(AttackedCard)
さて、カードバトルの処理は書けましたが、
バトル処理を実行するコードがないぞ!!!
ってことで、「AttackedCard」のコードを
下記のハイライト行に注目して書き換えましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; // 攻撃される側のコード public class AttackedCard : MonoBehaviour, IDropHandler { public void OnDrop(PointerEventData eventData) { // attackerを選択 マウスポインターに重なったカードをアタッカーにする CardController attackCard = eventData.pointerDrag.GetComponent<CardController>(); // defenderを選択 CardController defenceCard = GetComponent<CardController>(); // バトルする GameManager.instance.CardBattle(attackCard, defenceCard); } } |
さっきまでログ出力だったところを、CardBattleメソッドの実行にしただけですね。
※ちなみにGameManagerをシングルトン化したことで、
GameManager.instance.〜と書けば、GameManagerメソッドが実行できるようになったよ。
2-3.ゲームの実行
それではゲームを実行していきましょう!
こんな感じに正しくバトル処理が行われていればOKです!!!
※ そもそも味方同士で戦ってるのが正しくないとか、実は手札でもバトルしてしまう!とかは、一旦気にしない方向性で。笑
手順③:リーダーが攻撃されたことを検知する処理の実装
それでは最後に、リーダーが攻撃されたことを検知するスクリプトを作っていこう!!
演習はこのあとにやってもらうので、ひとまず一緒に新規のスクリプトを作成しましょう。
カードバトルの時と同じように実装していくので、
「AttackedLeader」スクリプトを新規で作成してください!
【演習】リーダーが攻撃されたことを検知してみる
さて、ここからは演習としてやってみましょう!!
皆さんにやってもらう課題としてはこんな感じ!!
さっき作った「AttackedLeader」にコードを書いてもらって、
「FireSpell」で敵のリーダーに攻撃したら、、、
ログにパワー分のダメージが出た内容が出力される!!
って処理を実装してもらいます!
基本的にはさっきやった内容が理解出来てれば実装できるはず!!
自分で考えて実装することで力になるので、
すぐに答えは見ないで、一旦は自力で挑戦してみてみましょう(`・ω・´)
【答え合わせ】リーダーの攻撃検知
さて、みなさま演習は出来ましたかね??
ではでは答え合わせをしていきましょう。
やりたいことは、
リーダーにカードがドロップされたら、
それを検知して、ドロップしてきたカードの情報をログに出す。
ってことだよね??
なのでやることは、
「AttackedLeader」スクリプトにOnDropメソッドを書いて、
それをリーダーにアタッチすればOK!!という感じ。
ということで、「AttackedCard」へ、下記のハイライト部分に注目してを追記しちゃいましょう!
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 UnityEngine.EventSystems; public class AttackedLeader : MonoBehaviour, IDropHandler { public void OnDrop(PointerEventData eventData) { // attackerを選択 マウスポインターに重なったカードをアタッカーにする CardController attackCard = eventData.pointerDrag.GetComponent<CardController>(); Debug.Log("リーダーに" + attackCard.model.power + "のダメージ"); } } |
追記した内容はほぼさっきと一緒で、
OnDropメソッドを使う為に、
「UnityEngine.EventSystems」と「IDropHandler」を記載して、
OnDropメソッド内で、
ドロップしてきたカードの情報を取得して、その情報をログに出す。
ってだけですな!!
そしたらコードはこれでいいので、こいつをアタッチしましょう。
- EnemyLeaderを選択して、
- AddComponentにて、「AttckedLeader」をアタッチ!
これでゲームを実行!!
「FireSpell」で敵のリーダーに攻撃!
ログにパワー分のダメージが出た内容が出力された!
ってなってればOKです。
この演習が出来た人はしっかり内容を理解しながら進めてますね! ( ´∀`)スバラシイ!
出来なかった人も大丈夫。
ちょっとずつでも理解しながら進んでいきましょう!
それではこの攻撃処理をログではなく、ゲーム画面に反映していく必要があるのですが、
今、実装してしまうと後でちょっとやり直す手間が増えてしまうので、そこは後でやりましょう!
というわけで今回の実装はここまでです!
最後までお疲れ様でした( ´∀`)
【終わりに】カードの攻撃処理の実装
今回も最後までお疲れ様でした!!!
だんだんとカードゲームっぽい感じになってきましたね。
次回はついに「オンライン実装」に入っていきます。
とは言ってもまだ導入とちょっとした設定くらいなので、肩の力は抜いてやっていきましょう!
ではまた次の記事にて!!
【次の記事】