前回の解説で手札やフィールドにカード生成することが出来るようになりましたね!
見てない人はこちら参照↓

今回はカードを持って動かせるようにしていくよ!!
完成形としてはこんな感じ!
動かせるようになるとカードゲームらしくなって楽しいよね!!
そんなわけで早速いくぞ!!
Contents
カードを動かす為のコードの実装
ではまず、カードを持って動かしたり、フィールドに出せるようにするのに必要な実装の流れを説明していくよ!
流れはザッとこんな感じ↓
①.カードを動かすコードを書く
②.フィールドに置く為のコードを書く
③.カードにコードを貼り付ける(アタッチする)
④.フィールドにコードを貼り付ける(アタッチする)
コードの内容と貼り付け方は後で詳しく説明するから、
とりあえずの流れを頭に入れといて、やりながら「あー今はここをやってるのね」って思いながらやるといいよ!
そんな訳で実際にやっていくぞ!!
①②2つのコード記入
ここではまず
カードを動かすためのコードと、
フィールドに置くためのコードを書いていくよ!
1.スクリプトの作成
では新しいスクリプトを2つ作るよ。
名前は、
“CardMovement”
“DropPlace”
という名前で作ってね。
クラス作成方法が分からないひとは以下を参考にして!!

“CardMovement”と”DropPlace”という名前のクラスが出来たらOK!!↓

それぞれ
カードを動かすためのコード(”CardMovement”)
フィールドに置くためのコード(”DropPlace”)
になってるよ。
2.プログラムの記入
そしたら中身を開いて、中身を丸ごと全部コピぺしよう。
”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 25 26 27 |
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.SetParent(cardParent.parent, false); GetComponent<CanvasGroup>().blocksRaycasts = false; // blocksRaycastsをオフにする } public void OnDrag(PointerEventData eventData) // ドラッグした時に起こす処理 { transform.position = eventData.position; } public void OnEndDrag(PointerEventData eventData) // カードを離したときに行う処理 { transform.SetParent(cardParent, false); GetComponent<CanvasGroup>().blocksRaycasts = true; // blocksRaycastsをオンにする } } |
”DropPlace”はこっち↓
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; using UnityEngine.EventSystems; // フィールドにアタッチするクラス public class DropPlace : MonoBehaviour, IDropHandler { public void OnDrop(PointerEventData eventData) // ドロップされた時に行う処理 { CardMovement card = eventData.pointerDrag.GetComponent<CardMovement>(); // ドラッグしてきた情報からCardMovementを取得 if (card != null) // もしカードがあれば、 { card.cardParent = this.transform; // カードの親要素を自分(アタッチされてるオブジェクト)にする } } } |
③④コードの貼り付け(アタッチ)
無事コードが書けたら、今度はUnity側の設定をしていくよ!
まずはCardPrefabに”CardMovement”を張り付けよう。

①.Cardプレハブをクリック
②.右下の「Add Component」をクリック
③.CardMovementと入力して、選択する
④.右のInspecterビューに、CardMovementが表示されればOK!!
≪2020/07/13 追記≫
コメントでご指摘いただいた所についての追記になります。

⑤.上記に加えて「Canvas Group」の追加。(パラメータは上の画像に合わせて下さい)
他にも疑問点、抜けてる点などコメントしていただけるとめちゃくちゃありがたいです!
コメント頂きありがとうございました!!
同じように、PlayerFieldにも”DropPlace”を張り付けよう。↓

そしたら実行ボタンを押す!!
動かせるし、フィールドに出せる!!!
と、そんな感じでカードを自由に動かして出せるようになったかな??
そしたらコードの解説をしていくよー!
コードの解説
ではカードを動かしてる、
それぞれのコードについて説明していくよ!!
①CardMovement(カードを動かすためのコード)と、
②DropPlace(カードを置くためのコード)の順に説明していくよ。
①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 25 26 27 |
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.SetParent(cardParent.parent, false); GetComponent<CanvasGroup>().blocksRaycasts = false; // blocksRaycastsをオフにする } public void OnDrag(PointerEventData eventData) // ドラッグしてる時に起こす処理 { transform.position = eventData.position; } public void OnEndDrag(PointerEventData eventData) // カードを離したときに行う処理 { transform.SetParent(cardParent, false); GetComponent<CanvasGroup>().blocksRaycasts = true; // blocksRaycastsをオンにする } } |
ざっくりまとめるとこんな感じ↓
1.《カードをドラッグし始めた時の処理》→親要素を変更する(10~15行目)
2.《ドラッグ中の処理》→カードの場所をマウスポインターと同じにする(17~20行目)
3.《ドラッグし終わった時の処理》→親要素を変更する(22~26行目)
一番重要な”OnDrag”メソッド
今回一番重要なのが、17行目の”OnDrag”メソッド。
名前の通りだけど、
OnDragメソッドとは、
ドラッグしてる時にこのメソッドの中に書いてある処理を実行するというメソッド。
今回で言うと、
transform.position = eventData.position
なので、
ドラッグしてる間は、
transform.position(カードの場所)を
eventData.position(マウスポインターの場所)にするよ。
っていう処理をしてるってこと!!
他のメソッドについて
次に大事なのが、“OnBeginDrag”と”OnEndDrag”メソッド。
(”OnDrag”メソッドの上と下にあるメソッドのことね。)
これらはそれぞれ、
ドラッグし始めた時の処理(OnBeginDragメソッド)
ドラッグし終わった時の処理(OnEndDragメソッド)
が書かれてるよ。
それぞれメソッドの中に、
transform.SetParent(~,false)
って書かれてるけど、これの意味は
(この場合で言うと)カードオブジェクトの親要素を変更する。ってこと。
親要素って言うのはこれね。↓

今回の動きで説明すると、
ドラッグする前の手札のカード(赤枠で囲ってるカード)の親要素は、PlayerHand。

これをドラッグすると親要素がCanvasに変わる↓
※transform.SetParent(cardParent.parent, false)の処理による結果

ドロップしたらこうなる↓

という処理をここで行ってるよ!
〜Handlerについて
次はクラス名の後ろに書いてあるIDragHandlerとかについての説明。
ここね↓
1 2 3 4 |
public class CardMovement : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler { (省略) } |
ここの部分にいくつか書いてあるけど、
さっき説明した“OnDrag”メソッドを使う時は”IDragHandler“書かないと使えないよ。
って認識でOK。
それぞれ以下に対応してるよ↓
【クラス名】 | 【メソッド名】 |
---|---|
IDragHandler | “OnDrag”メソッド |
IBeginDragHandler | “OnBeginDrag”メソッド |
IEndDragHandler | “OnEndDrag”メソッド |
表の右のメソッドを使うには、対応したクラスを書く必要があるってことね。
継承部分についてもう少し詳しく知りたい人はコメント下さいな。
unityengine.eventsystemsについて
最後にこれ↓
1 2 3 4 5 6 7 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class CardMovement : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler {(省略)} |
これもすごくザックリ言うと、
さっき説明した、IDragHandlerとかを使う為に書く必要があるもの。
って認識でOK
これを書かないと使えないので書きましょう。ってだけ。
ここも詳しく知りたい人がいたらコメントくださいな。
②DropPlaceについて
次にフィールドに貼り付けたコードについての解説!
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; using UnityEngine.EventSystems; // フィールドにアタッチするクラス public class DropPlace : MonoBehaviour, IDropHandler { public void OnDrop(PointerEventData eventData) // ドロップされた時に行う処理 { CardMovement card = eventData.pointerDrag.GetComponent<CardMovement>(); // ドラッグしてきた情報からCardMovementを取得 if (card != null) // もしカードがあれば、 { card.cardParent = this.transform; // カードの親要素を自分(アタッチされてるオブジェクト)にする } } } |
ざっくり、やってる処理としては、
《ドロップされた時の処理》→カードの親要素をアタッチしてるオブジェクトに変える
ってだけ。
なので、この”DropPlace”クラスの親要素を変更する処理をコメントアウトすると、、
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; using UnityEngine.EventSystems; // フィールドにアタッチするクラス public class DropPlace : MonoBehaviour, IDropHandler { public void OnDrop(PointerEventData eventData) // ドロップされた時に行う処理 { CardMovement card = eventData.pointerDrag.GetComponent<CardMovement>(); // ドラッグしてきた情報からCardMovementを取得 if (card != null) // もしカードがあれば、 { // card.cardParent = this.transform; // カードの親要素を自分(アタッチされてるオブジェクト)にする } } } |
置けなくなる!!(実際にやってみてね)
と言うわけで、この処理を行う“DropPlace”クラスをアタッチしたから、カードが置けてる。ってことですな。
演習
今回は割と簡単な演習だからみんなやってみて!
【演習】
現在は自分の手札から、自分のフィールドにカードを置くことは出来るけど、
逆にフィールドから手札に戻すことは出来ない。自分のフィールドから相手のフィールドに置くことも出来ない。
ではフィールドのカードを手札に戻す、あるいは相手のフィールドに出せるようにするにはどうすれば良いか。
ヒントとしては、
コードが貼ってあるから置けるんだよ。
って話。
まあカードゲームとしては有り得ない仕様だけど、練習だと思ってやってみよう!
答え合わせ
出来たかな??
ただ単にコピペしてるだけだと全く身に付かないから、やり方を覚えながら進もうね。
んで、答えはこう↓

このふたつにDropPlaceをアタッチするだけ!!
変な仕様になっちゃうから終わったらアタッチしたのは消しといてね!!
【最後に】お詫びとか、今後について
更新がめちゃくちゃ遅くなってしまってごめんなさい!!
コメントしてくれた方々ほんとにありがとうございました!
これでもめちゃくちゃ原動力になってます。
記事を書いてる側としては、ほんとにたった一言のコメントでも力になるし嬉しいんです!
なのでほんの1mmでも応援して頂けたり、参考になったという方はぜひコメントをお願いします。
(もちろん「ここがちょっと分かりずらいよ!」などのコメントでも大丈夫です!参考にしますので!!)
その代わりと言ってはなんですが、
7月中にカードゲームの基本動作までの
解説記事を全て書いて投稿します。
(現時点で全く記事のストックとか無いけど。。笑)
具体的には下の動画で言うと、
マナコスト通りにカードを出して、
相手のカードとバトルする所までね。
(スペルカードとか、モンスター効果とかはその後に実装するよ)
ペースとしては週に2回の投稿を予定しています。
なので全10回程度の解説記事になると思います。
そして最終的には「初心者がカードゲームを作りたいなら”みじんこのブログ”を見ればいいよね」って言ってもらえるようなサイトにしたいと思ってます!
その為にはあなたのコメント一つがめちゃくちゃ力になるので、一言でもいいのでコメントの方よろしくお願いいたします!!
新しい記事を投稿したタイミングとか、
ゲームについての役立ち(そうなこと)など
知りたい方はフォローして下さいな→→mijinko_game000
あと質問などあれば、お気軽にどうぞ!!!
次の記事↓

前の記事↓

では今回は終わりっ!!



こんにちは。
記事参考になりました。続き楽しみです。
CanvasGroupを使われてますが、AddComponentで「CanvasGroup」も追加しないといけないのではないでしょうか?
>yukiさん
コメントありがとうございます!
あ、、完全に抜けてました。
これだとエラーめちゃくちゃ出ますね。。笑
すみません、CanvasGroupの追加は必要です!!
記事に追記したのでよろしくお願いします。
また何かあったらコメントお願いしますね!
次の記事は今日か明日に出せると思うので、また見て下さい!
凄く参考になりました
Unity初なので大変助かっています
DropPlaceをPlayerHandに入れて実行したら
入れたものがなくなっている現象に見舞われて困っていましたが
実行中に入れても戻るんですね(初心者杉;
>もっけさん
コメントありがとうございます^^
確かに実行中にアタッチしたものは、実行を停止すると消えますね(笑)
困ることも多いですが、特に初心者のうちはミスすればするほど色々知れるので、
解説に無いことでも気になることはガンガン試しながら作ってみてください!(バックアップは取っておいた方が良いかも。。)
大変参考になりました.
質問がありコメントいたしました.
カードの配置に関しての質問です.すでに解説されている内容でしたら申し訳ございません.
カードをきれいに配置する方法は,記事に書いてあり,わかったのですが,
カードをもって,任意の位置に配置することは可能でしょうか?
よろしくお願い致します.
>まさきさまさん
コメントありがとうございます!
カードを固定の位置に配置する方法ですかね??(遊戯王みたいな?遊戯王やってなかったらごめんなさい。。)
恐らく色々方法はあるとは思いますが、あくまで僕が実装するんだとしたら、
今ある「PlayerField」の幅を縮めたものを5つ分作って、1枚づつカードを置けるようにしますかね~(フィールドに5体まで出せるようにする場合の話)
って説明で分かりますかね、、??
いまいち分からなかったらまたコメント下さい!
(出来た時もコメントくれたら嬉しい。笑)
お返事、感謝いたします。
わかりやすい解説ありがとうございました。
今後もよろしくお願いいたします。
いつも参考にさせて頂いてます
CardMovementのスクリプトを作成して、プログラムを記入したのに、
Add Componentをクリックして
CardMovementで検索してもCardMovementが表示されません
どういった原因が考えられますでしょうか?
>ピーロさん
コメントありがとうございます!
んー、一番多いのは、コードに書かれているクラス名が間違っていることですかね。
なので一旦、コードのクラス名と検索した時のクラス名にスペルミスが無いかを確認してみて下さい!
特に間違ってなければ、、、(´・ω・`)ナンダロウ
コードに関しての質問です。コードを映しても書くやつで参照なしとなってしまい、動きません。
どうしたらいいのでしょうか?
Logを出そうとしてもOnBeginDrag・OnDrag・OnEndDrag・OnDrop
が動きませんでした。
>ラいさん
コメントありがとうございます!
返信遅れてすみません、届いてますよ!
んー、CardMovementとDropPlaceクラスの話ですかね?
4行目の
using UnityEngine.EventSystems;
は書いてありますか?
これが書いてないと、動かないので一旦確認してみて下さい!
ちなみにコードにエラーは出てないってことでいいですよね??
アタッチは出来てない状況なんですかね、、??
>コードを映しても書くやつで参照なしとなってしまい、動きません。
あとこの”書くやつ”って言うのが分からなくてなんとも、、、
どこのことでしょうか、、(´・ω・`)ゴメンヨ
using UnityEngine.EventSystems;は書いてありますね。エラーは出てません。public void OnBeginDrag(PointerEventData eventData)などの上に普通ならUnity メッセージ□個の参照と表示されるはずなのですが、0個の参照となって動きません。ということです。わかりにくくてすみません。
>ラいさん
あー、なるほど!分かりました!
OnBeginDragメソッドなどは、メソッドを別のところから呼び出してる訳ではないので0個の参照と表示されていて問題ないです。
コードにエラーが出てないのなら、プログラムにミスはないと思います。
“動かない”とありますが、実行ボタンを押した後に、カードをドラッグしても動かないってことですかね?
Cardプレハブにアタッチはされましたか??
解説通りにアタッチしてて、動かないなら、、(-ω-)ナンダロウ、、
あと、カードがPlayerFieldの下になってしまうのはどうしたらいいでしょうか?
>ラいさん
えーと、まずカードは動くようになったってことですかね??
私としても初心者の方に分かりやすいサイトを作ろうと思ってるので、質問していただくのはむしろウェルカムなのですが、流石に「今は~という状況で、…が出来ない」「これが原因だと思って、~と~を試したけど…になってしまう」など、今の状況を詳細に説明して頂かないと答えようがないです。。
解説してる通りの動きをしてない時点で、もうどんな状況になってるのか分からないので、、
質問内容を整理してると、案外自分で解決出来たりしますし、色々分からないながらも直すのはめちゃくちゃ勉強になると思います。
(あと僕がコメントを見て答えるより、自分で頑張った方が早い場合もあると思うので。笑)
一旦、「原因は何かな??」って色々悩みながら試して、それでも解決しなかったらまたコメント下さい。
詳細を説明していただければ、力になれるかも知れないので!!
わかりました!ありがとうございます。頑張ってみます!(でもできることもうなさそう…)
すいません、今「ドラッグしたけど攻撃しなかったカードをもとの位置に戻す」というようにコードを書き換えようとしています(今だと一度クリックしたカードは必ず一番右に動いてしまうので)
考え方として、CardMovementのOnBeginDragで動かす前のCardの親OriginalCardPosition、位置OriginalCardParentを保存しておき、OnEndDragで「Drag前と親が変わっていなければ親と位置をOriginalCardPosition、OriginalCardParentにする」という処理がいいかなと思うのですが
public void OnBeginDrag(PointerEventData eventData) // ドラッグを始めるときに行う処理
{
Transform OriginalCardPosition = transform.position;
Transform OriginalCardParent = transform.parent;
cardParent = transform.parent;
transform.SetParent(cardParent.parent, false);
GetComponent().blocksRaycasts = false; // blocksRaycastsをオフにする
}
ではTransform OriginalCardPositionのところでエラーになってしまいました。
現状あまりtransformの使い方を理解できていないのですが、どうやって元のカード親・位置を取得すればよいでしょうか?
>トキムネさん
あー、確かに気になりますよね。。笑
あとで「バグ修正」的な記事で解説しようとは思ってたので、細かい解説はそっちで。。。
で、肝心のやり方ですが、考え方としては完璧です!!(・ω・)スバラシイ!
ただ使うコード(position)がちょっと違いますね!
今回、Cardの位置が変わってしまうのは、Hierarchy上でCardの位置が入れ替わってることが原因です。
試しにゲーム実行中にPlayerFieldのCard(子要素)の順番をHierarchyビュー上で動かしてみて下さい。
ゲーム上でもカードの順番が変わると思います。
つまり今回重要なのは「子要素の順番」です!!
そしてこれを変更するコードは、“SetSiblingIndex”です。
※ちなみに元の子要素の順番を取得するコードは、“GetSiblingIndex”です。
このコードを使って実装できるので、是非色々試してみてください!!(ちょっと難しいかも知れないですけど、演習だと思って頑張って下さい!)
分からなかったらまた聞いて下さいー!
参考:https://unity-yuji.xyz/change-hierarchy-order/
できました!Imageを使わないでやってたようでした。ありがとうございます!
できました‼
using(略)
public class CardMovement : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler
{
public Transform cardParent;//
Transform OriginalParent;//元のカードの親を入れる
int Cnamber;//元のカードの順番を入れる
public void OnBeginDrag(PointerEventData eventData) // ドラッグを始めるときに行う処理
{
OriginalParent =this.transform.parent;
Cnamber = this.transform.GetSiblingIndex();
(元のOnBeginDragの処理を書く)
}
public void OnDrag(PointerEventData eventData) // ドラッグした時に起こす処理
{
(略)
}
public void OnEndDrag(PointerEventData eventData) // カードを離したときに行う処理
{
if (OriginalParent == cardParent)
{
transform.SetParent(OriginalParent, false);
transform.SetSiblingIndex(Cnamber);
GetComponent().blocksRaycasts = true; // blocksRaycastsをオンにする
}
else
{
(元のOnEndDragの処理を書く)
}
}
}
現状変な挙動していないのでこれで正解だと思います!
わざわざ参考URLまで教えていただき助かりました!
いつもコメントに反応していただき本当に助かってます。本当にありがとうございます!
>トキムネさん
おー!!!素晴らしい!!!
120点です!!完璧です!笑
ほぼ思っていた通りのコードになっていて、ちゃんと動いているので問題ないと思います!
(ちょっとだけ言うとnamberじゃなくて、numberかな。笑
でもぶっちゃけコードなんて動けばいいと思ってるので気にすることなしです!笑 完璧です!!)
こちらこそいつもコメントくれるので僕も助かってますよ!
今後ともよろしくお願いしますね~
いつもありがとうございます!!3日前にUnityダウンロードしたばかりでさっそく挫けかけてましたが、こちらの記事を見ながらだと楽しく出来てます!!
カードが動くことに感動してお礼の連絡でした!!
頑張って最後まで続けたいと思います!!
>アツシさん
始めたばかりだと分からないことばっかりですよね。笑
感動してもらえて嬉しいです(*´ω`)笑
まだ完結してないですが、頑張ってください!!
初めまして!
私は高校時代にHTMLを齧っただけのスキルしかないですが、
みじんこさんの分かりやすい記事のおかけで新しい趣味が広がりそうです!
応援してます!
>りんごさん
わー、ありがとうございます、嬉しいです(*´ω`)
僕はHTMLも書けないんで、りんごさんはもっとガンガン作っていけると思います!笑
ゲーム作成はめちゃめちゃ楽しい趣味になるので、一緒にやっていきましょう!!
すみません。早速詰みました。
コードの記載(フルコピペ)、カードプレファブへのアタッチ、グループ全て記載通りで問題ないかと思いますが、プレビュー(再生ボタン)を押してからドラッグしてもカードが移動しません。手札が5枚とフィールドに5枚の計10枚ですが、どのカードも動かないです。
ここまで順調にできてたので全く原因がつかめないです。。
>りんごさん
んー、なんでしょう。。
カードの移動処理を実装してるのは、
該当記事の「③④コードの貼り付け(アタッチ)」の章の部分なので、そこはもう一度よく確認いただけますか?
特に⑤で解説してる「Canvas Group」の「Blocks Raycasts」をオンにしているかどうかを確認してみて下さい!
みじんこさん
初日の作業から1から作り直ししてみましたがやはり動かず。。お手上げです><;
何度もすみません。
解決しました!
Hierarchyタブにeventsystemフォルダがなかった(おそらく自分で消した)ことが原因だったみたいです!
これでようやく次のステップへ行けます!
お騒がせしました><;
>みじんこさん
問題なくアタッチもできていて、Blocks Raycastsもチェックされているように見えます。
私のの何かのミスかと思いますので復習かねて1からやり直してみます!