//tips
嶋津様打ち合わせ
//ロビーボタンからの遷移
遷移先のシーンを順に選択していく方法を、キューを使って考えているが、RoomListviewのDictionaryとStackも解決にうまく使えないかコードを見返してみた。
ルームリストが更新されるごとに呼び出され、自身以外の挙動をロビーに反映させることが主目的であるため、ボタンの遷移はSceneMoveスクリプトに完全に頼っている。
また、現状ではphotonが管理するroominfo情報をボタンの表示に連携させている。room退出時にentry.Deactivate();とボタンの非表示処理をinputFieldButtonスクリプトの方で行っているが、public void Deactivate()の際に
inputField.text = "";
inputField.interactable = true;
を加えて新たにリサイクルして表示する際にはまっさらな形で表示されるように修正した。退出したroomはlistに存在し続けるのか確認し、消えない場合はボタンも消えないので誰も居なくなった時点でroom破棄の処理を行う予定。
どちらにしろキューの遷移管理は別途作成する必要がある。
public override void OnRoomListUpdate(List<RoomInfo> roomList)
{
Debug.Log("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); //Push:inactiveEntriesとしてデータ登録
}
}
else if (!info.RemovedFromList)
{
///*
// リスト要素を追加する
entry = (inactiveEntries.Count > 0)
? inactiveEntries.Pop().SetAsLastSibling() //Pop:inactiveEntriesからデータ取り出し
: Instantiate(roomListEntryPrefab, scrollRect.content);
entry.Activate(info);
activeEntries.Add(info.Name, entry);
//*/
}
//シングルトンについて
シングルトンとは、複数シーン内でも、ただ1つのオブジェクトを扱うときに使うテクニックで、下記のように、最初に生成したものをinstanceに代入した後、遷移シーンなどで再生成される際に、同一のものを削除することができる。
public static SceneListManager instance;
private void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
//Queueの扱いについて
まずシーン遷移を行うと遷移前のシーンのオブジェクトは全て破壊され、スクリプトの記憶も破壊されるという前提があり、それを理解していないためエラーが起きているよう。
今回の下記のエラーの要因は、最初のGameObjectMasterシーンでQueueを登録し、その中からシーン1を削除しているが、シーン1にいき、戻ってきたときのGameObjectMasterシーンでは最初のシーンの全ての記録が破壊されているので、Queueに何も登録されていない状態となる。それなのにdequeueしてしまうと、当然何も入っていないのでエラーが出てしまうということになる。
InvalidOperationException: Queue empty.
System.Collections.Generic.Queue`1[T].ThrowForEmptyQueue () (at <d2957de1c3fd4781a43d89572183136c>:0)
System.Collections.Generic.Queue`1[T].Peek () (at <d2957de1c3fd4781a43d89572183136c>:0)
SceneListManager.OnRemove () (at Assets/SceneListManager.cs:25)
なので、解決策としてはGameObjectMasterシーンのSceneListManagerがアタッチされているSceneListManagerオブジェクトを異なるシーンでも生かし続ける必要がある。
以前制作した迷宮ゲームでは、PlayerPrefsを使用していたが、これは値を保存するものなので、今回のリストの仕様とは異なってしまう。
取り得る方法は2つある。
1.DontDestroyOnLoad()の使用
DontDestroyOnLoad()を使用すれば、使用したSceneについて他のSceneに切り替わった場合でもオブジェクトが破棄されないため、最初のSceneListManagerオブジェクトのみを保持し、シーン遷移で戻ったときに生成される後続の同一オブジェクトは破壊。
この場合、上記のシングルトンを使用することになるためstaticの影響力が大きすぎて、分業でコードを各場合には、毎回staticの内容を確認しながら作業しなくてはいけなくなるので、使用はあまり推奨されていないよう。
2.SceneManager.LoadSceneAsync(Scene, LoadSceneMode.Additive);の使用
シーンの遷移をする際に最初のシーンを同時に表示したまま、次のシーンを写す形態をとる。一見すると見にくいように思われるが、遷移前シーンをグループ化し、遷移時にUI非表示で管理することでQueueを生かしながら表示させることができる。こちらが現unity開発手法の主流のよう。
なので、個人的には1の方がすっきりするが、メインの手法となる2の方を用いて、シーンの修正を行う。
一旦このように改変し、再生したら、遷移から帰ってきた際に、groupsの中に入れたcameraのレンダリングが出来ないというエラーが発生。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneListManager : MonoBehaviour
{
public GameObject gameObjects = default;
public Queue<int> queue = new Queue<int>();
public int dequeue ;
//public static SceneListManager instance;
private void Awake()
{
gameObjects.SetActive(true);
}
public void Onregister()
{
// 値を追加
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);
Debug.Log("キューに登録されている数: " + queue.Count);
}
public void OnRemove()
{
gameObjects.SetActive(false);
dequeue = queue.Peek();
//dequeue = Dequeue()
queue.Dequeue();
Debug.Log("Dequeueした値: " + dequeue);
string Scene = dequeue.ToString(); //scenes[1]
SceneManager.LoadSceneAsync(Scene, LoadSceneMode.Additive);
//SceneManager.LoadSceneAsync(Scene, LoadSceneMode.Single);
Debug.Log("キューに登録されている数: " + queue.Count);
}
}