こんにちは、みじんこと申します。
本記事では前記事から引き続き、Unityでのオンライン対戦機能の実装方法を説明します。
そちらをまだ見ていない方は、実施後にこの記事に進んで頂けると良きかと思います!
本記事では下記の流れにて、カードゲームにおけるオンライン対戦機能の実装方法を解説していきます。
※本記事では④の「カードの移動とドロップ処理の実装」のみ解説していきます。
- 前準備とカードの作成
- UIの作成、カードの生成実装
- カードの種類の実装
- カードの移動とドロップ処理の実装
- カードバトル処理の実装
- リーダーへの攻撃処理の実装
- オンライン機能の導入と実装
本記事の完成形としてはこんな感じですね。
カードをドラッグで動かせるようにして、フィールドに出せるようにしていきます!!
それでは早速やっていきましょう。
今回も張り切っていこう!!
Contents
【実装概要】本記事で実装する内容について
さて今回はカードの移動処理を実装していきますが、こんな流れにて実装していきます!
- カード移動処理の実装
- ドロップ処理の実装
まずカードを動かすためのコードを書いて、動かす処理を実装します。
最後に、フィールドにドロップしたらフィールドにカードが生成される処理を実装。
という流れで進めていくよ!!
手順①:カードの移動処理を実装する
ではいきなりですが今回のメイン「カードの移動処理」を実装していきます!
でもやることは、
カードを動かすための処理のスクリプトを新規で作成して、
それをカードプレハブにアタッチすればOK!!ってだけ。
早速やっていきましょう!
スクリプトの作成と記載
まずはスクリプトを作っていこう!!
「CardMovement」スクリプトを新規で作成。
このスクリプトにカードが移動する処理を書いていくよ。
CardMovementコードの記載と解説
次はコードの記載をしましょう。
丸ごと「CardMovement」にコピペで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 29 30 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class CardMovement : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler { // カードの親要素 public Transform cardParent; public void OnBeginDrag(PointerEventData eventData) // ドラッグを始めるときに行う処理 { // 元のカードの親要素を取得 cardParent = transform.parent; Transform canvas = GameObject.Find("Canvas").GetComponent<Transform>(); transform.SetParent(canvas, false); } public void OnDrag(PointerEventData eventData) // ドラッグした時に起こす処理 { transform.position = eventData.position; } public void OnEndDrag(PointerEventData eventData) // カードを離したときに行う処理 { // 親要素を変更 transform.SetParent(cardParent, false); } } |
CardMovementコードの解説
今記載した内容をざっと解説していきます。
ざっくり言うと大事なのは下記の3つです。
- OnBeginDragメソッド(カードをドラッグし始めた時の処理)
- OnDragメソッド(ドラッグ中の処理)
- OnEndDragメソッド(ドラッグし終わった時の処理)
それぞれメソッドの処理を見ていきましょう。
■OnBeginDragメソッドの解説
1 2 3 4 5 6 7 8 |
public void OnBeginDrag(PointerEventData eventData) // ドラッグを始めるときに行う処理 { // 元のカードの親要素を取得 cardParent = transform.parent; Transform canvas = GameObject.Find("Canvas").GetComponent<Transform>(); transform.SetParent(canvas, false); } |
カードをドラッグし始めた時に実行されるメソッドです。
そのまま動かすだけだと、
こんな感じ↓に動かしてるカードが別のカードの後ろに表示されたりするので、
カードの親要素をCanvasにして、一番上に表示されるようにしてる!!ってだけ(SetParent(canvas, false))
ただし、そのまま親要素を「Canvas」にしてしまうと、
カードを離した時に「元の親要素ってなんだっけ???」ってなっちゃうので、
親要素を変更する前に、現時点の親要素をゲットしてる(cardParent = transform.parent)
ということ!!
■OnDragメソッド
1 2 3 4 |
public void OnDrag(PointerEventData eventData) // ドラッグした時に起こす処理 { transform.position = eventData.position; } |
今回一番重要なのが、こちらの「OnDrag」メソッド。
ドラッグ中に実行されるメソッドですね。
ドラッグしてる間は、
transform.position(カードの場所)を
eventData.position(マウスポインターの場所)にする。
っていう処理をしてるから、カードが動かせる。ってことですな。
■OnEndDragメソッド
1 2 3 4 5 |
public void OnEndDrag(PointerEventData eventData) // カードを離したときに行う処理 { // 親要素を変更 transform.SetParent(cardParent, false); } |
最後はドラッグし終わった時のメソッドですね。
やってることは、SetParent(=親要素のセット)なので、
ドラッグし終わったら、このカードの親要素をセットし直してね。って処理ですな。
「cardParent」はカードを動かす前の親要素なので、元の場所に戻してるだけ!
■〜Handlerについて
次はクラス名の後ろに書いてあるIDragHandlerとかについての説明。
ここね↓
1 |
public class CardMovement : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler |
さっき説明した「OnDrag」メソッド等を使う時は、この「〜Handler」書かないと使えないよ。
って認識でOK。
それぞれ以下に対応してるよ↓
【クラス名】 | 【メソッド名】 |
---|---|
IDragHandler | OnDragメソッド |
IBeginDragHandler | OnBeginDragメソッド |
IEndDragHandler | OnEndDragメソッド |
表の右のメソッドを使うには、対応したクラスを書く必要があるって理解でOK!!
unityengine.eventsystemsについて
最後にこれ↓
1 |
using UnityEngine.EventSystems; |
これは単に、〜Handlerとかを使う為に書く必要があるもの。
って認識でOK
これを書かないと使えないので書きましょう。ってだけです!
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 |
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); // 表示 } } |
これは説明するまでもなく、
CardControllerからCardMovementを扱えるようにしただけですね。
Unity側の設定
CardプレハブにもCardMovementをアタッチしましょう。
(若干画像が違うけど、問題ないのでお気になさらず!)
- Cardプレハブをクリックして、OpenPrefabして開く
- AddComponentでCardMovementをアタッチ
これで設定は完了!!
ゲームの実行
それではゲームを実行していきましょう!
まずカードが出てきて、、
カードをドラッグしたら動いた!!
そんで、離したら手札に戻った!!(順番が変わるのはお気になさらず)
ってなればOKです!!
手順②:ドロップ処理の実装
さて、カードの移動は出来るようになったけど、
このままじゃカードをフィールドに出せないじゃん。。
って悲しい気持ちになってしまうので、
フィールドにドロップしたらフィールドにカードが生成されるような処理
を実装していきましょう!
完成系はこんな感じですね。
ゲームを実行したら、カードが出てきて、、
カードをドラッグ!!
フィールドにドロップしたら、カードがフィールドに生成された!!
何枚でもドロップし放題!!!
みたいな感じ。
それではこれを実装していきましょう!!
2-1.スクリプトの作成
まずはドロップする場所用のスクリプトを作ります。
名前を「DropField」で新規に作成して、ダブルクリックして開いておきましょう!
2-2.Unityの設定
お次はUnity側の設定。
画像通りに進めてね。
- PlayerFieldを選択
- さっき作った「DropField」スクリプトをAdd Componentで追加!
Cardプレハブもちょっと設定変更しましょう。(画像が若干違うのは気にしないで!)
- CardプレハブをOpenPrefabして開く
- 「Canvas Group」をAdd Componentで追加!
今カードにアタッチした「Canvas Group」は、
BlocksRaycastsの設定をいじれるようする為にアタッチしてるよ。
BlocksRaycastsについて
Blocks Raycastsってなんだ??!
レイキャストをブロックするかどうかのパラメータのこと!
もっと砕けて言うと、
ポインターから出てるビームが当たってる判定するか、
当たってない判定とするかっていうパラメータのこと!!
これはドロップ判定のために必要な機能なのですが、
いきなりドロップ判定の説明をするとややこしいので、
一旦、カードが動く処理についてちょいと説明しますね。
カードに向かってボタンを押すと、マウスポインターからカードに向かってビームが出ます。
そのビームが当たって、そのまま動き出すと、
カードが「なんか動き出した(`・ω・´)」ってなるのがドラッグの判定です。
逆に言うと、カードに
カードにビームの当たり判定(Blocks Raycasts)なんて、いらんぞい!
ってことで、ビームの当たり判定をオフ(Blocks Raycasts=off)してしまうと、
カード自体にポインターが当たっても、
「そんなの知りません(・Д・)」って顔されて、ドラッグの判定をされないって訳です。
さて本題に戻ると、
ドロップ処理もドラッグ判定と同じように、ポインターのビームでドラッグ判定を行ってます。
でも今のままだと、カードを動かせはしますが、
カードがずっとポインターのビームを「ブロックじゃ٩( ‘ω’ )و」って邪魔して、
カードより下にあるドロップした場所までビームが届きません。
なので、カードをドロップしても、
ドロップをした場所的には「ビームなんて届いてません(・Д・)」って顔される訳です。
実装したい人
じゃあどうすればいいのよ!!
となるので、
カードをドラッグし始めたらBlocks Raycastsの値をオフにして、
カードがビームを邪魔しないようにして、
ドロップした時に「フィールド」にビームを届ける!!
ってな処理をコードで実装していくよ!!
2-3.コードの記入
まずは「CardMovement」スクリプト。
やりたいことは、
カードをドラッグし始めたらBlocks Raycastsの値をオフにすることなので、
ハイライト部分を追記!!
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 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class CardMovement : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler { // カードの親要素 public Transform cardParent; public void OnBeginDrag(PointerEventData eventData) // ドラッグを始めるときに行う処理 { // 元のカードの親要素を取得 cardParent = transform.parent; Transform canvas = GameObject.Find("Canvas").GetComponent<Transform>(); transform.SetParent(canvas, false); // blocksRaycastsをオフにする GetComponent<CanvasGroup>().blocksRaycasts = false; } public void OnDrag(PointerEventData eventData) // ドラッグした時に起こす処理 { transform.position = eventData.position; } public void OnEndDrag(PointerEventData eventData) // カードを離したときに行う処理 { // 親要素を変更 transform.SetParent(cardParent, false); // blocksRaycastsをオンにする GetComponent<CanvasGroup>().blocksRaycasts = true; } } |
次に「DropField」スクリプトにドロップされた時の処理を書いていく!!
下記のコードを全部コピペしましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class DropField : MonoBehaviour, IDropHandler { [SerializeField] GameManager gameManager; public void OnDrop(PointerEventData eventData) // ドロップされた時に行う処理 { CardController card = eventData.pointerDrag.GetComponent<CardController>(); // ドラッグしてきた情報からCardControllerを取得 if (card.movement != null) // もしカードがあれば、 { // カードを生成 gameManager.CreateCard(card.model.cardId, this.transform); // カードオブジェクトを破壊する Destroy(card.gameObject); } } } |
※今時点で「CreateCardメソッド」の箇所でエラーが出てるのは気にしないで!!
やってることは、
もしカードがドロップされてきたら、CreateCardメソッドを使って、
ドロップしたカードのID(card.model.cardId)のカードをフィールドに生成するよ!!
そんで生成したら、元のカードは破壊するよ!!
ってな処理ですな。
【補足】なんでわざわざ新しくカードを生成してるのよ??について
何で移動してきたカードを破壊してんの??
カードの親要素をフィールドにして、
カードの場所を変更すればいいだけじゃないの??
と思った方、、、、鋭いですね。
カードを移動したいだけなら、それで合ってます。
ただここでは、
「カードをフィールドに移動したい」というより、
「カードがフィールドに召喚された」という意図でこの処理にしてます。
要は「召喚処理っぽく」する為に、
単に移動してきただけじゃなくて、新しく生成してる。ってこと!
(あとでちゃんと召喚処理に書き換えるけどね。)
では最後に「GameManager」スクリプトを修正しましょう!
さっきエラーが出てた箇所についてですが、
現状「CreateCard」メソッドが他のスクリプトから使えない状態なのが原因ですね。
なので、CreateCardメソッドをパブリック化してあげましょう。
1 2 3 4 5 6 7 8 9 10 11 |
public class GameManager : MonoBehaviour { (省略) // カードを生成するメソッド(Publib化する) public void CreateCard(int cardId, Transform trans) { // cardPrefabをtransに生成する CardController card = Instantiate(cardPrefab, trans); card.Init(cardId); } } |
これでコードの修正は完了です!!!
2-4.Unityの設定
ではもっかいUnity側の設定に戻ります。
今のままだと、
PlayerFieldさんや。
GameManagerのCreateCardメソッドを動かしておくれ!
って言っても、
PlayerFieldさん的には「GameManagerって誰じゃい!!!」状態だからですね。
アタッチして教えてあげましょう!
- PlayerFieldを選択
- GameManagerをアタッチ!!
これで準備完了!!!
2-5.ゲームの実行
それではゲームを実行しましょう!!
まずカードが出てきて、、
カードをドラッグ!!
フィールドにドロップしたら、カードがフィールドに生成された!!
何枚でも置けるぜい!!!
ってなればOKですね。
今回の実装はここまでです!
最後までお疲れ様でした( ´∀`)
【終わりに】カード移動処理とドロップ処理の実装
皆さま、今回もお疲れ様でした!!!
移動処理や、ドロップ処理などはよく使う処理なので
使えるようになっておくと今後のゲーム制作に役立つかと思います!
まだもうちょっとオンライン機能の実装に向けたカードゲーム自体の実装が続きますが、
もう少しで終わるので、続けて実施してもらえると良きかと思います!!
ではまた次回!!
【次の記事】