//tips
//photonロビーprefab周り
RoomListViewスクリプトにアタッチできるprefabとできないprefabがあるのでスクリプトの中身を確認していく。
・RoomlistEntry(アタッチできる)
RoomlistEntryボタン+Room list entryスクリプト
|―name(text mesh pro)
|―message(text mesh pro)
|―counter(text mesh pro)
・RoomlistEntryB(アタッチできない)
RoomlistEntryBボタン +input field buttonスクリプト +NetworkmanagerBスクリプト
|-input field
|―place holder(text)
|―roomname(text)
|―submit button
|―text
|―Enter button
|―text
Prefabのタイプ指定にGameObjectではなくクラスを使用していることがわかる。
PrefabはScene内のオブジェクトを参照できないので、シーン内のスクリプトから生成prefabが必要な情報を提供する必要がある。
RoomListViewスクリプトはprefabが含むRoomListEntryクラスの参照をベースにして構成されており、スクロールビューにprefabを生成するときのリスト情報の更新などを請け負っている。
ただ、今回作成したものはnameLabel、messageLabel、playerCounter情報を更新させる必要がなく、削除ボタンも別途作成すれば良いのでRoomListEntryクラスの内容はほぼ必要ない。
PrefabをRoomListEntryクラスの[SerializeField]で体現しているかどうか、クラスのphoton周りが設置されているか、RoomListViewの内容がinput field buttonスクリプトの内容とそぐわないからなどが焦点になるかと思われるので、まずはRoomListViewを修正するところから始める。
RoomListViewBを作成し、InputfieldButtonクラスとうまく組み合う形に変えていく 。
RoomListViewBスクリプトとInputfieldButtonクラスを下記の形で大幅修正することでアタッチすることができるようになった。
using System.Collections.Generic;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(ScrollRect))]
public class RoomListViewB : MonoBehaviourPunCallbacks
{
[SerializeField]
private InputfieldButton roomListEntryPrefab = default; // RoomListEntryのPrefabの参照
private ScrollRect scrollRect;
private Dictionary<string, InputfieldButton> activeEntries = new Dictionary<string, InputfieldButton>();
private Stack<InputfieldButton> inactiveEntries = new Stack<InputfieldButton>();
private void Awake()
{
scrollRect = GetComponent<ScrollRect>();
}
// ルームリストが更新された時に呼ばれるコールバック
public override void OnRoomListUpdate(List<RoomInfo> roomList)
{
foreach (var info in roomList)
{
InputfieldButton entry;
if (activeEntries.TryGetValue(info.Name, out entry))
{
if (!info.RemovedFromList)
{
// リスト要素を更新する
entry.Activate(info);
}
else
{
// リスト要素を削除する
activeEntries.Remove(info.Name);
entry.Deactivate();
inactiveEntries.Push(entry);
}
}
else if (!info.RemovedFromList)
{
// リスト要素を追加する
entry = (inactiveEntries.Count > 0)
? inactiveEntries.Pop().SetAsLastSibling()
: Instantiate(roomListEntryPrefab, scrollRect.content);
entry.Activate(info);
activeEntries.Add(info.Name, entry);
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//追加
using Photon.Pun;
using Photon.Realtime;
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(Button))]
public class InputfieldButton : MonoBehaviour
{
//InputFieldを格納するための変数
[SerializeField]
InputField inputField;
[SerializeField]
private Text roomname;
private RectTransform rectTransform;
private void Awake()
{
rectTransform = GetComponent<RectTransform>();
}
public void OnSubmit()
{
Debug.Log("決定");
// 入力できないようにする
inputField.interactable = false;
//inputField.text = "";
}
public void Activate(RoomInfo info)
{
gameObject.SetActive(true);
}
public void Deactivate()
{
gameObject.SetActive(false);
}
public InputfieldButton SetAsLastSibling()
{
rectTransform.SetAsLastSibling();
return this;
}
}
入室ボタンのonclickをNetworkManagerBの参照に直してあげると、無事勝手に遷移してしまう自体も防ぐことができるようになった。
その上でログを確認すると、
・ロビーに入室
・部屋名の決定
・room入室("room Sampleに入りました")
までは問題なくできた。
if (PhotonNetwork.InLobby)
{
PhotonNetwork.JoinOrCreateRoom("Sample", roomOptions, TypedLobby.Default);
Debug.Log("room Sampleに入りました");
PhotonNetwork.IsMessageQueueRunning = false;
Debug.Log("roomには"+ PhotonNetwork.CurrentRoom.PlayerCount + "人います");
if (PhotonNetwork.CurrentRoom.PlayerCount == 2)
{
SceneManager.LoadSceneAsync("Sample", LoadSceneMode.Single);
PhotonNetwork.IsMessageQueueRunning = true;
}
}
ただ、Debug.Log("roomには"+ PhotonNetwork.CurrentRoom.PlayerCount + "人います”);の部分でエラーが出ている。
NullReferenceException: Object reference not set to an instance of an object
NetworkManagerB.JoinOrCreateRoom () (at Assets/NetworkManagerB.cs:109)
これは先のRoomListEntryからInputFieldButtonに移行する時に削除した部分かと先のスクリプトを見直したところ、PhotonNetwork.CurrentRoom.PlayerCountはRoomListEntryの下記で表されていた。
public void Activate(RoomInfo info)
{
roomName = info.Name;
nameLabel.text = (string)info.CustomProperties["DisplayName"];
messageLabel.text = (string)info.CustomProperties["Message"];
playerCounter.SetText("{0}/{1}", info.PlayerCount, info.MaxPlayers);
// ルームの参加人数が満員でない時だけ、クリックできるようにする
button.interactable = (info.PlayerCount < info.MaxPlayers);
gameObject.SetActive(true);
}
これをみるとinfo.PlayerCountとして、PhotonNetwork自体が管理している数字であることがわかるのでphoton networkとの接続問題のように思われる。
Debug.Log(info.PlayerCount);をinputfieldbuttonのpublic void Activate(RoomInfo info)の中に組み込む。
RoomlistviewBの中にあるルームリストが更新された時に呼ばれるコールバックの方でも確認する。
public void Activate(RoomInfo info)
{
gameObject.SetActive(true);
Debug.Log(info.PlayerCount);
}
Debug.Log(info.PlayerCount);の反応が来る前に先のエラーで止まってしまう。
PhotonNetwork.IsMessageQueueRunning = false;を一旦削除してみたところ、room sampleではエラーが発生し、room sample部屋が存在しないものとして扱われ、新たな部屋を建て、そこにjoinしている。
Inputfieldで入力する名前と生成される部屋名とのリンクがうまくできていないからかもしれないのでその部分のスクリプトを見直す。