//tips
//input fieldのボタンへの組み込み
input fieldの出力先のテキストをボタン内のテキストに変えて考えていく。
現状は下記の階層になっている。
Canvas
|-input field
|—place holder
|—roomname
|—submit button
|—text
|-textbox
なのでこれを①または②のやり方で整えることができないか考える。
①
Canvas
|-input field
|—place holder
|—roomname
|—submit button
|—text
|-button
|—text
②
Canvas
|-button
|-input field
|—place holder
|—roomname
|—submit button
|—text
まずはシンプルな②から試してみる。新たなシーンを作成し、試行する。
部屋名の入力だけで考えると、ボタン内のテキストにそのまま書き込む形を撮れれば良いので下記のようにスクリプトを変更した。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class InputfieldButton : MonoBehaviour
{
//InputFieldを格納するための変数
[SerializeField]
InputField inputField;
[SerializeField]
private Text roomname;
public void OnSubmit()
{
Debug.Log("決定");
// 入力できないようにする
inputField.interactable = false;
//inputField.text = "";
}
}
次にこのボタンをprefabとしてroom list viewに生成されるようにしたい。input field下に決定ボタンを付与していると自動生成されるときの位置も考えなければならないのでボタン内に、決定ボタンと入室ボタンを組み込む。削除ボタンは別途検討。
room list viewとroom list entryの関係を再確認する。
ルーム選択リスト(RoomListView)とそのリスト要素(RoomListEntry)で成り立っており、ルームリストの更新をコールバックで受け取り、受け取ったルーム情報を元にしてリスト要素を変更する処理をスクロールビューが付け加えられたRoomListViewで行っている。
なので、スクロールビューに先のinputfield付きボタンを表示するためには、リスト要素となるRoomListEntryの方のprefabとうまく入れ替えれば良い。
RoomListEntry自体はボタンでRoomListEntryスクリプトをアタッチされており、子要素に3種類のテキストを持っていた。
なので先に作成したボタンをそのままprefab化しても通用するように思われる。
まずは先の階層をprefab化。canvasは含まず、button以下のものでパックした。
Canvas
|-button
|-input field
|—place holder
|—roomname
|—submit button
|—text
そのまま放り込んだらContentの子要素にしてRoomListEntryの下に並べたらサイズが大きすぎてはみ出してしまったのでサイズ調整を行う。
これによりスクロールビューのコンテントとしてprefabを表示させることができた。
ここからは入室ボタンを押したら、roomに入場、さらに人数が一定数に達した時に遷移を行えるようなスクリプトを追加する。
その際にPUNとの接続を行えるようにスクリプトのusingを加えていくことも忘れない。
Prefab内のRoomLIstEntryBのボタンに現在InputfieldButtonスクリプトをアタッチしているが追加で、NetworkManagerスクリプトもアタッチして入室ボタンを押したらルームに入り、遷移をできるようにしてしまう。
NetworkManagerスクリプトを編集して、現在すぐに遷移してしまう動作をroomの参加人数を参照しながら、条件により遷移させることができるように編集する。
そのためにはroomへの参加人数をNetworkManagerの方でカウントできなければならない事になる。
下記のスクリプトを見直す。
public void JoinOrCreateRoom()
{
// ルームオプションの基本設定
RoomOptions roomOptions = new RoomOptions
{
// 部屋の最大人数
MaxPlayers = (byte)maxPlayers,
// 公開
IsVisible = isVisible,
// 入室可
IsOpen = isOpen
};
// 入室 (存在しなければ部屋を作成して入室する)
if (PhotonNetwork.InLobby)
{
PhotonNetwork.JoinOrCreateRoom("Sample", roomOptions, TypedLobby.Default);
SceneManager.LoadSceneAsync("Sample", LoadSceneMode.Single);
}
}
ロビーにいる状態でJoinOrCreateRoom()メソッドが実行された場合は、”Sample”room(シーン遷移では無い)に入り、その際の条件、最大人数、公開か否か、入室可能か否か、を基準とする。TypedLobby.Defaultは存在するロビーがデフォルトロビーであることを示す。
TypedLobby.Defaultとは、ロビーに関する設定をいじらなかった場合、1つだけ自動で作成されるロビーのことで、これをデフォルトロビーと呼ぶ。
そもそもロビーはTypedLobbyクラスという名前のサーバー上の特定のロビーと種別を参照するクラスで構成されており、NameとLobbyTypeの属性を持ち、これらの値の組み合わせでロビーを判別している。
TypedLobby.TypedLobby (
string name,
LobbyType type
)
ロビー一つで複数のroomを管理できるので大抵の場合は、デフォルトロビーで対応できる。
bool PhotonNetwork.JoinLobby()でデフォルトロビーに簡単に入れる。
こちら参考。
https://qiita.com/k0mach1/items/ecfe30165653969a408d
ここからroom情報をうまく使い、roomへの入室と遷移をうまく使い分けていく。
// 部屋の情報を表示
if (PhotonNetwork.InRoom)
{
Debug.Log("RoomName: " + PhotonNetwork.CurrentRoom.Name);
Debug.Log("HostName: " + PhotonNetwork.MasterClient.NickName);
Debug.Log("Slots: " + PhotonNetwork.CurrentRoom.PlayerCount + " / " + PhotonNetwork.CurrentRoom.MaxPlayers);
}
PhotonNetwork.CurrentRoom.PlayerCountの数値を条件にし、遷移が発動されるように考える。2名をroom上限とし、2名参加できた段階で遷移するようにする。また、ロビーで実体化するのではなく、遷移先のシーンの中で実体化させたいのでPhotonNetwork.IsMessageQueueRunning = false;を加えて、遷移前には実体化させないように配慮した。
if (PhotonNetwork.InLobby)
{
PhotonNetwork.JoinOrCreateRoom("Sample", roomOptions, TypedLobby.Default);
Debug.Log("room Sampleに入りました");
PhotonNetwork.IsMessageQueueRunning = false;
if (PhotonNetwork.CurrentRoom.PlayerCount == 2)
{
SceneManager.LoadSceneAsync("Sample", LoadSceneMode.Single);
PhotonNetwork.IsMessageQueueRunning = true;
}
}
これで入室ボタンを押すと修正前スクリプトのRoomListEntryの内容が実行されてしまう。
原因を探っていくとroom list viewスクリプトに格納されている。RoomListEntryの内容が当初のまま変わっておらず、これを変更後のものに修正しようとしたが、インスペクター上で簡単には変更できない。
room list viewスクリプトも見直し、RoomlistEntry部分の名前を変更してみても、新たに生成したRoomListEntryBはアタッチ可能なオブジェクトとしてインスペクターに認識されない。
・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
room list viewスクリプトの内容をinput field buttonに反映させて対応していくことにする。