対戦カードゲームをunityとc#とphotonで作りたい:手札をダブルクリックして相手に公開する(9)

Githubソースコード公開&まとめ

対戦カードゲームをunityとc#で作りたいと思います。今回は自分の手札をダブルクリックすると相手に手札を公開できる昨日を実装しようと思います。まずは、ダブルクリックを検知するスクリプトを探すところから始めます。

ダブルクリックを検知するにはいくつかの方法があるようですが、下のリンクのものが一番簡単そうだったのでやってみました。イベントシステムを使用するようです。

UnityのCollider2DやColliderに対してクリックやドラッグのイベントを使う

イベントシステムではマウスの入力を検知できるのでとても便利そうです。ページをメモしておきます。
イベントシステムについてはこちら
サポートされているイベント

ダブルクリックを検知したいオブジェクトに一番上のリンクのDoubleClick.csをアタッチします。ヒエラルキービューでUIの作成からEventSystemを選択します。

作成するだけで中身はいじりません。最後に、メインカメラのインスペクター上でPhysics2DRayCasterを加えます。これはコライダーに対応しているため、今回は2Dcolliderを使用している事で2Dを使用しています。

プログラムを走らせ、カードをダブルクリックすると、デバッグログにマウスをクリックした回数が返されます。これで、ダブルクリックを検知することが出来ました。

次はダブルクリックした時に相手側のプレイヤーのカードにカードインデックスの番号が渡り、表面をレンダーするという機能を使えるようにしたいと思います。参考にしたページは下記です。

【Unity】僕もPhotonを使いたい #07 位置の同期

ベストなやり方ではないのですが、カードのインデックス情報を位置の同期と同時に送ってしまいます。それから、そのカードがクリックされた回数も同時に送ります。そして、クリックされた回数が2回であれば、カードを表にしてレンダーします。

よってPlayerNetworkMover.csに下記の項目を書き加えます。

    CardModel card;
    DoubleClick doubleClick;
    void Awake()
    {
        card = GetComponent<CardModel>();
        doubleClick = GetComponent<DoubleClick>();
    }

そして、 OnPhotonSerializeViewの内容を書き換えます。これはフレーム毎にこの処理を行っているので位置の同期には良いのですが、インデックスを毎回したり、レンダーを継続してし続けるという事は不必要なのであまり良くない書き方です。現状、他のやり方がわからないので、こうしているだけで、違うやり方を見つけ次第修正していこうと思います。

    void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {

        if (stream.isWriting)
        {
            stream.SendNext(transform.position); //現在のポジションを送る
            stream.SendNext(card.cardIndex); //cardIndexの情報を送る
            stream.SendNext(doubleClick.clickNum); //クリックされた回数を送る
        }
        else
       {
           CardModel cardModel = GetComponent<CardModel>(); //受信先のCardModelを取得
           position = (Vector3)stream.ReceiveNext(); //現在のポジションを受信
           cardModel.cardIndex = (int)stream.ReceiveNext(); //cardIndexの情報を受信
           clickedNum = (int)stream.ReceiveNext(); //クリックされた回数を受信

            if (clickedNum == 2) //クリックされた回数が2回だった場合
            {
               cardModel.ToggleFace(true); //表をレンダー
           }
            else
           {
               cardModel.ToggleFace(false); //裏をレンダー
            }
       }
    }

ちなみにstream.SendNextの送る順序と、stream.ReceiveNextで受ける順序を揃える必要があるように思いました。情報を特定するキーが無いので、おそらくは順番に情報を処理しているのではと思います。if文で送る情報を制限しようとしたのですが、上手くいかなかったという事を記録しておきます。そもそも同期を取る必要が無い情報の同期を取っているので、もう少し違うやり方を後々考えたいと思います。

相手の手札が一部公開されました。これによって恣意的にカードを公開することができるようになりました。

おすすめの記事