対戦カードゲームをunityとc#とphotonで作りたい:手札を13枚配る編(7)

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

 

ネットワークゲームにおいて最初の手札13枚をどの様に配ったらよいかを考えます。

 

前回はFPSゲームのプレイヤーの初期配置の仕方を参考に、プレイヤーを配置する代わりに予め決められた場所にカードを一枚配置しました。

 

今回は1枚のカードではなく、13枚のカードを配ります。

 

しかも、同じデッキから配りたいと思います。という事は、デッキをシャッフルし、まず一人目のプレイヤーに配ったのち、残りのカードのインデックス情報を共有し、それを二人目のプレイヤーが受信し、手札を配るというようなコンセプトでやってみたいと思います。

 

カードシャッフルとインデックスの値はDeck.csで以前作ったスクリプトを流用します。

 

まずNetworkManagerにDeck.csをアタッチします。

 

     Deck deck; //Deckクラスを参照します
        deck = GetComponent<Deck>(); //Deck.csの取得

以上のスクリプトをNetworkManagerの所定の場所に追加します。お決まりのパターンです。

 

Deck.csのパブリックメソッドGetCards();からインデックスを呼び出します。この時はforeachを使用することになります。

 

  void OnJoinedRoom()
    {
        if (PhotonNetwork.playerList.Length == 1)
        {
            int index = 0;
            int cardCount = 0; //内部で使う値cardCountの宣言
            deck.Shuffle();

            foreach (int i in deck.GetCards())
            {
                if (cardCount < 13)
                {
                    float co = cardOffset * cardCount; //オフセット幅の計算
                    Vector3 temp = startfirst + new Vector3(-co, 0f);
                    //tempというオフセットした位置の計算
                    GameObject cardCopy = (GameObject)PhotonNetwork.Instantiate("Card", temp, spawnPoints[index].rotation, 0);
                    //カードプレファブのコピー

                    CardModel cardModel = cardCopy.GetComponent<CardModel>();
                    //コピーしたカードプレファブのCardModelクラスを取得
                    cardModel.cardIndex = i;//インデックスにiを代入
                    cardModel.ToggleFace(true);
                    //表面をレンダー(カードゲームを作りたい第2回目で作成したスクリプトを使用)

                    cardCount++; //cardCountをインクリメント
                }

部屋に入っているプレイヤーが一名の場合、foreachのcardCountの値が13に以下である場合に限りカードのコピー(場所をずらしながら)とインデックスの代入とレンダーを行うようになっています。

 

このPhotonNetwork.Instantiateすることで、両方のプレイヤーが見えるオブジェクトを作成できます。

 

ちなみにprefabにはphotonView.csをつけておかないとエラーがでます。詳しくは下記のリンクにとても丁寧に説明してあるのでご参照ください。

 

【Unity】僕もPhotonを使いたい #06 オブジェクトを作ろう

cardCountが13を超えた場合は26以下であればルームカスタムプロパティに値を保存します。

 

card13~card25という名前でカードをプロパティに保存しています。

 

ルームカスタムプロパティについては以下のウェブサイトが参考になりました。

 

私もまだよく理解はできていませんので、使いながらおいおい覚えていきたいと思います。

 

【Unity】僕もPhotonを使いたい #11 カスタムプロパティ

よくわかる?! Photonの仕組み??!

else if(cardCount < 26)
                {
                    var properties = new ExitGames.Client.Photon.Hashtable();
                        string card = "card" + cardCount;
                        properties.Add(card, i);
                        PhotonNetwork.room.SetCustomProperties(properties);
                    cardCount++;
                }
                else
                {
                    break;
                }

そして、プレイヤー2の処理に入ります。プレイヤー2はRoomCustomPropertyの値を参照して、そのカードインデックスを取得します。

 

そしてそれを同じくinstantiateされたカードに割り当てて、レンダーします。

 else
        {
          
            for (int i = 13; i < 26; i++)
            {
                float co = cardOffset * i; //オフセット幅の計算
                Vector3 temp = startsecond + new Vector3(-co, 0f);//tempというオフセットした位置の計算
                GameObject cardCopy = (GameObject)PhotonNetwork.Instantiate("card", temp, Quaternion.identity, 0);
                CardModel cardModel = cardCopy.GetComponent<CardModel>();  // Cardmodel を使用、

                string card = "card" + i;
                int indexnumber = (int)PhotonNetwork.room.customProperties[card];
                cardModel.cardIndex = indexnumber; //Cardmodel.csのcardIndex に 要素の値を渡す
                cardModel.ToggleFace(true);  // 表面レンダーする
            }

        }

ファイルをビルドして両方のプレイヤーがログインするとお互いのカードが見えているのが分かります。

 

この時、相手の手札は、情報を送っていないので見えないという事になります。

 

今回のスクリプトは長くなりましたので全体を表示しておきます。

 

ほとんどチュートリアルから持ってきた、継ぎはぎのスクリプトです。参考にしたチュートリアルは最下部に掲載しています。

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; //text 使うので

public class NetworkManager : MonoBehaviour {

    Deck deck; //Deckクラスを参照します

    [SerializeField] Text connectionText;
    [SerializeField] Transform[] spawnPoints;
    [SerializeField] Camera sceneCamera;

    public float cardOffset; //カードのずらし幅offsetの宣言
    public Vector3 startfirst;
    public Vector3 startsecond;
    GameObject player;
    
    void Start()
    {
        PhotonNetwork.logLevel = PhotonLogLevel.Full;
        PhotonNetwork.ConnectUsingSettings("0.1");

        deck = GetComponent<Deck>(); //Deck.csの取得
    }

    void Update()
    {
        connectionText.text = PhotonNetwork.connectionStateDetailed.ToString();

    }

    void OnJoinedLobby()
    {
        RoomOptions ro = new RoomOptions() { isVisible = true, maxPlayers = 2 };
        PhotonNetwork.JoinOrCreateRoom("Tomo", ro, TypedLobby.Default);

    }

    void OnJoinedRoom()
    {
        if (PhotonNetwork.playerList.Length == 1)
        {
            int index = 0;
            int cardCount = 0; //内部で使う値cardCountの宣言
            deck.Shuffle();

            foreach (int i in deck.GetCards())
            {
                if (cardCount < 13)
                {
                    float co = cardOffset * cardCount; //オフセット幅の計算
                    Vector3 temp = startfirst + new Vector3(-co, 0f);
                    //tempというオフセットした位置の計算
                    GameObject cardCopy = (GameObject)PhotonNetwork.Instantiate("Card", temp, spawnPoints[index].rotation, 0);
                    //カードプレファブのコピー

                    CardModel cardModel = cardCopy.GetComponent<CardModel>();
                    //コピーしたカードプレファブのCardModelクラスを取得
                    cardModel.cardIndex = i;//インデックスにiを代入
                    cardModel.ToggleFace(true);
                    //表面をレンダー(カードゲームを作りたい第2回目で作成したスクリプトを使用)

                    cardCount++; //cardCountをインクリメント
                } else if(cardCount < 26)
                {
                    var properties = new ExitGames.Client.Photon.Hashtable();
                        string card = "card" + cardCount;
                        properties.Add(card, i);
                        PhotonNetwork.room.SetCustomProperties(properties);
                    cardCount++;
                }
                else
                {
                    break;
                }
               
            }
              
        }
        else
        {
          
            for (int i = 13; i < 26; i++)
            {
                float co = cardOffset * i; //オフセット幅の計算
                Vector3 temp = startsecond + new Vector3(-co, 0f);//tempというオフセットした位置の計算
                GameObject cardCopy = (GameObject)PhotonNetwork.Instantiate("card", temp, Quaternion.identity, 0);
                CardModel cardModel = cardCopy.GetComponent<CardModel>();  // Cardmodel を使用、

                string card = "card" + i;
                int indexnumber = (int)PhotonNetwork.room.customProperties[card];
                cardModel.cardIndex = indexnumber; //Cardmodel.csのcardIndex に 要素の値を渡す
                cardModel.ToggleFace(true);  // 表面レンダーする
            }

        }

    }

}

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

 

 

おすすめの記事