Photon(PUN2)でルーム情報を表示する
今日は久しぶりにPhotonについての記事です。
これまでの実装では1つのルームに対して入室していましたが、複数のルームに分けて情報共有することも可能です。
これを実施することで、同じPhoton CloudまたはPhoton Serverで複数組の情報共有が可能になります。
今回は公式の下記記事を参考にしています。
準備
アプリ起動時ロビーに入室させる
まずはこれまで作成したPhotonManager.cs
を編集し、Photon Cloud/Serverに接続後、ロビーに入室するようにします。
ルームリストはロビー入室時にしか確認することができません。
今回、ロビーで取得するルームリストは公式のUpdateCachedRoomList
を流用しています。
doc.photonengine.com
- PhotonManager.cs
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; using Photon.Pun; using Photon.Realtime; using Photon.Voice.PUN; namespace MRTKPhotonTest { /// <summary> /// Photon接続用クラス /// </summary> public class PhotonManager : MonoBehaviourPunCallbacks { /// <summary> /// 自インスタンス /// </summary> public static PhotonManager instance; /// <summary> /// ユーザ用プレハブ /// </summary> [SerializeField] private GameObject UserPrefab; /// <summary> /// 共有基準点 /// </summary> [SerializeField] public Transform SharingBaseTransform; /// <summary> /// ルーム情報 /// </summary> /// <typeparam name="string"></typeparam> /// <typeparam name="RoomInfo"></typeparam> /// <returns></returns> private Dictionary<string, RoomInfo> cachedRoomList = new Dictionary<string, RoomInfo>(); // 2022/03/21 追加 void Awake() { // シングルトン化 if (instance == null) { // 未作成の場合作成 instance = this; DontDestroyOnLoad(this.gameObject); } else { // すでに作成されている場合削除 Destroy(this.gameObject); } } void Start() { // PhotonCloudに接続 Connect(); } public void Connect() { if (!PhotonNetwork.IsConnected) { // 未接続の場合PhotonServerSettings.assetに従って接続 PhotonNetwork.ConnectUsingSettings(); } } private void UpdateCachedRoomList(List<RoomInfo> roomList) // 2022/03/21 追加 { for (int i = 0; i < roomList.Count; i++) { RoomInfo info = roomList[i]; if (info.RemovedFromList) { cachedRoomList.Remove(info.Name); } else { cachedRoomList[info.Name] = info; } } } /// <summary> /// サーバ接続した場合のCallBack /// </summary> public override void OnConnectedToMaster() { PhotonNetwork.JoinLobby(); // 2022/03/21 編集 } public void JoinRoom(string roomName) // 2022/03/21 追加 { // ルーム名roomNameに参加する。なければ作る。 PhotonNetwork.JoinOrCreateRoom(roomName, new RoomOptions(), TypedLobby.Default); } public void LeaveRoom() // 2022/03/21 追加 { if(PhotonNetwork.InRoom) { PhotonNetwork.LeaveRoom(); } } /// <summary> /// ルーム入室した際のCallBack /// </summary> public override void OnJoinedRoom() { Debug.Log("Entered Photon Room!"); if (UserPrefab != null) { // ユーザオブジェクトを生成する GameObject userObject = PhotonNetwork.Instantiate(this.UserPrefab.name, new Vector3(0f, 0.5f, 0.8f), Quaternion.identity, 0); if (SharingBaseTransform != null) { // 共有基準点の子オブジェクトにする userObject.transform.parent = SharingBaseTransform; } } } /// <summary> /// ルームリスト更新時処理 /// </summary> /// <param name="roomList"></param> public override void OnRoomListUpdate(List<RoomInfo> roomList) // 2022/03/21 追加 { UpdateCachedRoomList(roomList); } /// <summary> /// ロビー退出時処理 /// </summary> public override void OnLeftLobby() // 2022/03/21 追加 { cachedRoomList.Clear(); } /// <summary> /// 接続切断時処理 /// </summary> /// <param name="cause"></param> public override void OnDisconnected(DisconnectCause cause) // 2022/03/21 追加 { cachedRoomList.Clear(); } /// <summary> /// ルーム情報取得メソッド /// </summary> /// <returns></returns> public Dictionary<string, RoomInfo> GetRoomInfo() // 2022/03/21 追加 { return cachedRoomList; } } }
これで、アプリ起動時に自動でPhoton Cloud/Serverに接続し、ロビーに入室する処理が作成できました。
ルーム名を指定して入室する
今回は別スクリプトでルームリスト情報の表示や、ルーム入室を行う必要があります。
次にその処理を作成します。
まずは、入室したいルーム名を入力するためのInputFieldを用意します。
Hierarchy上で右クリックしてInput Filed - TextMeshProを選択します。
作成したオブジェクトのうち、Canvasを選択し、Convert to MRTK Canvas
を選択します。
これでCanvasサイズをシーン中で自由に変更できるようになるので、使いやすい大きさに変更します。
次に、Input Fieldの隣に入室用のボタンを2つ、TextMeshProを1つ追加します。
Hierarchy上で右クリックし、TextMeshProを選択します。
ボタンは1つは入室用、もう一つは退室用です。
下記スクリプトをアタッチし、入室、退室ボタンにそれぞれメソッドを設定します。
- EnterRoom.cs
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; using TMPro; using Photon.Pun; using Photon.Realtime; using Photon.Voice.PUN; namespace MRTKPhotonTest { public class EnterRoom : MonoBehaviour { [SerializeField] private TMP_InputField inputFiled; [SerializeField] private TextMeshPro logText; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } public void LeaveRoom() { PhotonManager.instance.LeaveRoom(); logText.text = $"Left room"; } public void EnterNamedRoom() { string roomName = inputFiled.text; if(!string.IsNullOrEmpty(roomName)) { PhotonManager.instance.JoinRoom(roomName); logText.text = $"Entered {roomName} room"; } } } }
これで、ロビー入室後のルーム入退室の準備ができました。
ルーム情報を表示する
最後にルーム情報を表示する設定を行います。
今回はテキストベースで既存のルーム名と、入室人数を表示する簡単なものにしています。
Hierarchy上で右クリックし、TextMeshProを選択します。
任意の大きさ、位置に設定して下記スクリプトをアタッチします。
- ShowRoomInfo.cs
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; using TMPro; using Photon.Pun; using Photon.Realtime; using Photon.Voice.PUN; namespace MRTKPhotonTest { public class ShowRoomInfo : MonoBehaviour { /// <summary> /// 更新間隔(秒) /// </summary> [SerializeField] private float timeInterval = 5f; /// <summary> /// 更新カウンタ /// </summary> private float timeCount = 0f; /// <summary> /// ルーム情報表示テキスト /// </summary> [SerializeField] private TextMeshPro infoText; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { timeCount += Time.deltaTime; if (timeCount > timeInterval) { ShowRoomInfomation(); timeCount = 0; } } /// <summary> /// ルーム情報表示メソッド /// </summary> private void ShowRoomInfomation() { infoText.text = ""; if (PhotonNetwork.InLobby) { Dictionary<string, RoomInfo> roomInfoDict = PhotonManager.instance.GetRoomInfo(); foreach (var info in roomInfoDict) { infoText.text += $"RoomName:{info.Key}, Num of User:{info.Value.PlayerCount}\n"; } } } } }
これで存在するルーム情報を表示する準備ができました。
動作確認
HoloLens2側で先にルーム「test」に入室した後に、PC側でアプリを起動すると、ルーム「test」の情報が表示されました。
また、ルーム「test」に入室すると、HoloLens2側のユーザが表示され、別のルーム「test2」の場合はルームを新規作成しているので、誰もいない新規ルームに入室できました。
久々にPhoton触って、ルーム情報取得とルーム名指定での入室試した。
— napo tech (@SubNapo) March 21, 2022
これでルーム管理もできたな。 pic.twitter.com/FzswtdJNFX