//tips
//PUNスクリプト確認
エラーの要因になってそうなRoomListViewのスクリプトを確認していく。
inactiveEntriesとは、private Stack<RoomListEntry> inactiveEntries = new Stack<RoomListEntry>();とRoomListViewスクリプトで宣言されており、箱に入れるものについてルールづけることを可能にする。
スタックへのデータ登録をするにはPushメソッドを使用し、スタックからデータを取りだすにはPopメソッドを使用する。Pop(inactiveEntries.Pop()が該当)で取り出すデータは最後に入れたものとなり、データ取得後、スタックから取得したデータは削除される。
データを削除せずに取り出したい場合はPeekメソッドを使用する。
スタックに登録されているデータの数はCountプロパティで調べる事ができ、stack.Count(inactiveEntries.Countが該当)で登録数を取得できる。
またその後に続く以下は,三項演算子(条件演算子)で、if文をより簡潔に書くことができるもの。
entry = (inactiveEntries.Count > 0) //inactiveEntries.Count > 0の条件
? inactiveEntries.Pop().SetAsLastSibling() //条件が真ならば実行
: Instantiate(roomListEntryPrefab, scrollRect.content); //条件が偽ならば実行
ここでボタンを末尾に追加するか、Instantiate (prefab, position, Quaternion.identity);で初期ボタンを生成するかで分岐している。
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);
}
}
リストのボタンに対して、複数の打ち手が必要で、一度Joinしたら再度Joinしないようにフラグを作る工夫(boolで変数を作り、Joinしたらtrueに変える。もしすでに変数がtrueなら遷移処理を行わないなど。)や自プレイヤーの部屋への通知をOnJoinedRoomを組み込んだ別スクリプトにして、ボタンではなくemptyオブジェクトにそのスクリプトをアタッチすることでボタンの重複を避けるなどの処置を考えていく。
//InventoryUIスクリプトのエラー修正
SampleSceneへ遷移するたびにInventoryUIスクリプトの下記のエラーが出ているのでそちらも修正する。
NullReferenceException: Object reference not set to an instance of an object
InventoryUI.UpdateUI () (at Assets/Script/InventoryUI.cs:18)
Inventory.Start () (at Assets/Script/Inventory.cs:26)
この問題は、InventoryUI.csのStart関数始まるよりも早く、Inventory.csのStart関数のInventoryUI.UpdateUI()が実行されてエラーが出ているとのこと。
<Inventory>
void Start()
{
InventoryUI = GetComponent<InventoryUI>();
InventoryUI.UpdateUI();
}
<InventoryUI>
void Start()
{
slots = slotsParent.GetComponentsInChildren<Slot>();
}
public void UpdateUI()
{
for(int i=0; i < slots.Length; i++)
{
if (i<Inventory.instance.items.Count)//UIで表示される前のインベントリの中身Inventory.instance.items
{
slots[i].AddItem(Inventory.instance.items[i]);
}
else
{
slots[i].ClearSlot();
}
}
Debug.Log("UpdateUI");
}
InventoryUI.csのStart関数をAwakeに変更する。
これにより、先のエラーを消すことができた。Start関数が実行される順番にも今後注意し、被りがある場合はAwakeで優先順位をつけるようにする。
また、Inventory.csでpublic static Inventory instance;の部分でアドバイスをいただき、staticを使うのはシーン内で1つだけのオブジェクトにつけるのが正しい使い方なので、現状の個別にinventoryを生成する運用には適さないとのこと。
単純にstaticを消すだけだと下記のエラーが出てしまうので、findタグなどを利用し、取得していく流れにする。
Assets/CubeD.cs(18,13): error CS0120: An object reference is required for the non-static field, method, or property 'Inventory.instance'