対戦カードゲームをunityとc#とphotonで作りたい:チップの同期とカウント(17)

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

前回までのスクリプトではチップをDestroyした時に、相手側からその動きが見えていませんでした。今回はその同期の取り方と、チップのカウントの仕方について考えました。

まずは同期の取り方ですが、下のサイトに凄く詳しくのっていたので、それを参考にスクリプトを書いてみました。

【Unity】僕もPhotonを使いたい #08 RPC() PhotonTargets編

私が説明する余地がないくらい詳細の解説が載っているので、説明は割愛します。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class ChipCreate : MonoBehaviour, IPointerClickHandler
{
    ChipCalculator chipCalculator;

    Vector3 temp;
    Vector3 position;

    private PhotonView m_photonView = null; //RPCを使うときに書き加える

    void Awake()
    {
        m_photonView = GetComponent<PhotonView>();//RPCを使うときに書き加える
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        if (eventData.clickCount > 1)
        {          
            temp = this.transform.position;
            GameObject pokerchip = (GameObject)PhotonNetwork.Instantiate("pokerchip2", temp, Quaternion.identity, 0);
            m_photonView.RPC("DestroyChip", PhotonTargets.All);//RPCを実行
        }
    }
    [PunRPC] //RPC本体
    private void DestroyChip()
    {
        Destroy(gameObject);
    }
}

これで、Destroyが実行されると、双方のプレイヤー画面で実行されることが確認できました。

次に、チップのカウントです。まずは立面のチップにタグをつけました。タグ付けされているチップをカウントしています。

通常では相手のチップまで一緒にカウントしてしまうため、IsMineを使って自分のチップのみタグを残し、自分のウィンドウの相手のチップのタグは全部Untaggedにしてしまいます。

   void Start()
    {
        if (photonView.isMine != true)
        {
            GetComponent<Chipcreate2>().enabled = false;
            gameObject.tag = "Untagged";
        }
    }

これによって、チップのカウントをする準備ができました。

チップのカウントはChipCalculator.csにまとめてあります。

 まず部屋に入ったら現在のチップを表示する必要があるので、初期値をRoomCustomPropertyに送り、Screenにも代入して、現在の点数をテキストで表示します。

次に、void Updateの中で常にチップの枚数をタグを用いて監視し、それが、現在表示されている点数と違う場合のみ、データをRoomCustomPropertyに送り、現在の点数をテキストで書き直します。

プレイヤー1の場合と2の場合と別々のパターンを想定してデータの送受信を行っています。

    void OnJoinedroom()//部屋に入ったら下記を実行
    {
        //room.custom.propertiesにチップの枚数を送る
        var properties = new ExitGames.Client.Photon.Hashtable();
        properties.Add(PhotonNetwork.player.ID + "pokerpoint", pokerpoint);
        PhotonNetwork.room.SetCustomProperties(properties);
        screen = pokerpoint + "point"; //現在のscreenのstring
    }

    void Update()
    {
        tagObjects100 = GameObject.FindGameObjectsWithTag("Hozchip100");//100チップを数える
        tagObjects500 = GameObject.FindGameObjectsWithTag("Hozchip500");//500チップを数える
        pokerpoint = tagObjects100.Length * 100 + tagObjects500.Length * 500;//描画されているチップの枚数
        tempscreen = pokerpoint + "point";//新しいscreenのstring
        

        if (screen != tempscreen)//現在のscreenと新しいscreenに違いがあれば
        {
            if (PhotonNetwork.inRoom == true)
            {
                //データをルームプロパティに送る
                var properties = new ExitGames.Client.Photon.Hashtable();
                properties.Add(PhotonNetwork.player.ID + "pokerpoint", pokerpoint);
                PhotonNetwork.room.SetCustomProperties(properties);


                if (PhotonNetwork.player.ID == 1)
                {
                    if (PhotonNetwork.room.customProperties[2 + "pokerpoint"] != null)
                    {
                        opponentscreen = (int)PhotonNetwork.room.customProperties[2 + "pokerpoint"] + "point";
                    }

                }
                else 
                {
                    if (PhotonNetwork.room.customProperties[1 + "pokerpoint"] != null)
                    {
                        opponentscreen = (int)PhotonNetwork.room.customProperties[1 + "pokerpoint"] + "point";
                    }
                }
            }
            screen = tempscreen;
        }
    }

最初はこれだけで解決すると思ったのですが、実際にプレイしてみると、相手のチップが更新された場合に、自分も更新しない限り、データの送受信がされないという問題が起こりました。

そこで、RoomCustomPropertiesのコールバックメソッドを調べ、データが書き換えられた場合に呼ばれる関数OnPhotonCustomRoomPropertiesChangedを使用しました。

 下記のサイトが参考になりました。

【Unity、PUN】Photon Unity Networkingのコールバックメソッド一覧

下記のスクリプトを足すことで、双方のプレイヤーのチップが更新されるようになりました。

これもプレイヤーが入れ替わる事を想定して書いています。

    void OnPhotonCustomRoomPropertiesChanged()
    {
        if (PhotonNetwork.player.ID == 1)
        {
            if (PhotonNetwork.room.customProperties[2 + "pokerpoint"] != null)
            {
                opponentscreen = (int)PhotonNetwork.room.customProperties[2 + "pokerpoint"] + "point";
            }

        }
        else
        {
            if (PhotonNetwork.room.customProperties[1 + "pokerpoint"] != null)
            {
                opponentscreen = (int)PhotonNetwork.room.customProperties[1 + "pokerpoint"] + "point";
            }
        }
    }

表示するテキストも二か所用意して、入れ替わる想定でスクリプトをアタッチしてあります。

using UnityEngine;
using UnityEngine.UI;

public class pokepoint2 : MonoBehaviour {

    ChipCalculator chipCalculator;
    float temp;
    Vector3 current;

    void OnPhotonCustomRoomPropertiesChanged()
    {
        if (PhotonNetwork.player.ID == 1)
        {
            ChipCalculator chipCalculator = GameObject.Find("ChipCalc").GetComponent<ChipCalculator>();
            this.GetComponent<Text>().text = chipCalculator.opponentscreen;
        }
        else
        {
            ChipCalculator chipCalculator = GameObject.Find("ChipCalc").GetComponent<ChipCalculator>();
            this.GetComponent<Text>().text = chipCalculator.screen;
        }

    }
}

お互いのチップがカウントされ、更新されるのが確認できました。

もしよろしければ、Photonについて私が知りえる限りの情報を徹底的にまとめてみたので、下記の記事も読んで下さいね!

おすすめの記事