LoginSignup
1
2

More than 3 years have passed since last update.

[Unity,Photon]Photon2で自動更新されるルームのリストを作る

Posted at

Photon2で下画像のようなルームリストを作りたい

前回の続きになります。
前回:[Unity,Photon2]Photon2でルームを作成したい

こんな感じで選択したボタンを押したらそのルームに入りたい。
今回はそのボタンを作成します。
image.png

表示させるボタン

今回使ったボタンのプレハブの構成はこんな感じです。
image.png
ボタンには押されたらボタンの中で表示されているRoomNameのルームに移動するという処理だけです。
調べたらいくらでも出てくるので割愛。

ボタンを生成、情報を入力

今回はボタンを並べたかったのでScroolView内のContentにボタンを生成します。
image.png
デフォルトから名前を変更した"RoomContet"に"ViewMatchWaitingPlayers.cs"というスクリプトを追加します。

ViewMatchWaitingPlayers.csの構成

ViewMatchWaitingPlayers.cs
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine.UI;

 public class ViewMatchWaitingPlayers : MonoBehaviourPunCallbacks
{
    public GameObject RoomButton;

    public void Start()
    {
        //ロビーへ移動する
        PhotonNetwork.JoinLobby();
    }

    //ルームに動きがあった場合
    public override void OnRoomListUpdate(List<RoomInfo> roomList)
    {
        Debug.Log("[function]ReloadRooms");
        foreach(RoomInfo r in roomList)
        {
            //プレイヤーが存在しているルーム
            if (r.PlayerCount > 0)
            {
                RoomButtonCreate(r);
            }
            else
            {
                RoomButtonDelete(r);
            }
        }
    }

    //ルームボタンの作成
    public void RoomButtonCreate(RoomInfo r)
    {
        //すでに存在していたのなら情報の更新
        if (gameObject.transform.Find(r.Name))
        {
            RoomInfoUpdate(gameObject.transform.Find(r.Name).gameObject, r);
        }
        //新しく作られたルームならばボタンの作成
        else
        {
            var roomButton = (GameObject)Instantiate(RoomButton);
            roomButton.transform.SetParent(gameObject.transform, false);
            RoomInfoUpdate(roomButton, r);
            //生成したボタンの名前を作成するルームの名前にする
            roomButton.name = r.Name;
        }
    }

    //ルームボタンの削除
    public void RoomButtonDelete(RoomInfo r)
    {
        //ボタンが存在すれば削除
        if (gameObject.transform.Find(r.Name))
        {
            GameObject.Destroy(gameObject.transform.Find(r.Name).gameObject);
        }
    }

    //ルームボタンのInfoの更新
    public void RoomInfoUpdate(GameObject button, RoomInfo info)
    {
        foreach (Text t in button.GetComponentsInChildren<Text>())
        {
            if (t.name == "RoomName")
            {
                t.text = info.Name;
            }
            else if (t.name == "MaxPLayerCount")
            {
                t.text = info.MaxPlayers.ToString();
            }
            else if (t.name == "RoomInPlayerCount")
            {
                t.text = info.PlayerCount.ToString();
            }
        }
    }
}

このコードの簡単な解説です

ルームの取得方法


public GameObject RoomButton;

public void Start()
    {
        //ロビーへ移動する
        PhotonNetwork.JoinLobby();
    }

public GameObjectで先ほど作成しておいたボタンのプレハブを指定します。

ロビーにいないとルーム情報を取得できないのでロビーに入っておきます。


public override void OnRoomListUpdate(List<RoomInfo> roomList)
    {
        foreach(RoomInfo r in roomList)
        {
            //プレイヤーが存在しているルーム
            if (r.PlayerCount > 0)
            {
                RoomButtonCreate(r);
            }
            else
            {
                RoomButtonDelete(r);
            }
        }
    }

この"OnRoomListUpdate()"でルーム情報を取得します。
自分はここで詰まってたのですが、この関数はルーム内で人数が変更されたり、ルームの情報が変更されたときのみ
変更が起こったルームだけroomListに入ります。
任意のタイミングでは実行できません。

ルームのリスト全部じゃないんかーい。好きなタイミングで呼び出せんのかーいって感じですが、仕様ならしょうがないです。

ちなみに、
ロビーに入ったときは何もない状態から"OnRoomListUpdate"を読み込む形になるのでルームが存在すればすべてのルームがroomListに入ります。
それ以降は先ほどと同じで人数が変わったなどの変更があったルームだけがroomListとして"OnRoomListUpdate()"が実行されます。

とりあえずこれでルームが取得できました。次はこのルーム情報をもとにプレハブのボタンに情報を表示させてボタンを生成していきます。

ルーム情報を可視化

"OnRoomListUpdate()"で更新があったルームリストがくるので、
そのリストの中のルームにプレイヤーがいる = 人数制限だとしても表示させるとしたら表示する。
なので、
プレイヤーが存在していたらボタンを作成していく方向で行きます。

public void RoomButtonCreate(RoomInfo r)
    {
        //すでに存在していたのなら情報の更新
        if (gameObject.transform.Find(r.Name))
        {
            RoomInfoUpdate(gameObject.transform.Find(r.Name).gameObject, r);
        }
        //新しく作られたルームならばボタンの作成
        else
        {
            var roomButton = (GameObject)Instantiate(RoomButton);
            roomButton.transform.SetParent(gameObject.transform, false);
            RoomInfoUpdate(roomButton, r);
            //生成したボタンの名前を作成するルームの名前にする
            roomButton.name = r.Name;
        }
    }

public void RoomInfoUpdate(GameObject button, RoomInfo info)
    {
        foreach (Text t in button.GetComponentsInChildren<Text>())
        {
            if (t.name == "RoomName")
            {
                t.text = info.Name;
            }
            else if (t.name == "MaxPLayerCount")
            {
                t.text = info.MaxPlayers.ToString();
            }
            else if (t.name == "RoomInPlayerCount")
            {
                t.text = info.PlayerCount.ToString();
            }
        }
    }

ルームの情報が更新されるたびに"OnRoomListUpdate()"が実行されるので
すでに存在しているルームならば情報の更新だけにしておきます。そうしないと人が抜けたり入ったりするだけで同じルームのボタンがいくつも生成されてしまいます。

これで生成したボタンに情報が入るようになります。

ルームが消えたらルームのボタンを消す

public void RoomButtonDelete(RoomInfo r)
    {
        //ボタンが存在すれば削除
        if (gameObject.transform.Find(r.Name))
        {
            GameObject.Destroy(gameObject.transform.Find(r.Name).gameObject);
        }
    }

人がいないルームをいつまでも表示させておくわけにはいかないので人が0人になったらボタンのリストから削除します。

これで冒頭にもあったルームリストが作成できます。
image.png

おわり

ルーム情報の取得はpublic override void OnRoomListUpdate(List roomList)
public override void OnRoomListUpdate(List roomList)を使うためにはロビーに入っておく
roomListには変更があったルームの情報しか入らない

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2