//tips
//PUN2 入室時エラー
下記のエラーは、Inputfieldで入力する名前と生成される部屋名とのリンクがうまくできていないからかもしれないと思っていたが、PhotonNetwork.JoinOrCreateRoom("Sample", roomOptions, TypedLobby.Default);には、部屋名にかかわらず"Sample”ルームに入るように設定しているので、部屋名のエラーでは無い。
NullReferenceException: Object reference not set to an instance of an object
NetworkManagerB.JoinOrCreateRoom () (at Assets/NetworkManagerB.cs:109)
if (PhotonNetwork.InLobby)
{
PhotonNetwork.JoinOrCreateRoom("Sample", roomOptions, TypedLobby.Default);
Debug.Log("room Sampleに入りました");
//PhotonNetwork.IsMessageQueueRunning = false;
Debug.Log("roomには"+ PhotonNetwork.CurrentRoom.PlayerCount + "人います"); //109行目
if (PhotonNetwork.CurrentRoom.PlayerCount == 2)
{
SceneManager.LoadSceneAsync("Sample", LoadSceneMode.Single);
PhotonNetwork.IsMessageQueueRunning = true;
}
そうすると
PhotonNetwork.CurrentRoom.PlayerCountにアクセスできないエラーか、
"Sample”ルームに入ると生成されるオブジェクトを参照するコードが走りエラーになっているか、
が要因として考えられる。
Debug.Log("roomには"+ PhotonNetwork.CurrentRoom.PlayerCount + "人います”);を一旦コードから抜いてみるとエラー位置が下の異なる位置に表示された。
これをみると、ルーム入室後に、オブジェクトの生成を使用としているが参照するオブジェクト自体がないため、nullとなっているように思える。
今まで省いていたPhotonNetwork.IsMessageQueueRunning = false;を再度コードに含めて確認するもエラーは継続。
PhotonNetwork.IsMessageQueueRunningは、ルームに入室した後、別のシーンに遷移し複数プレイヤーが操作するオブジェクトを生成する時に使われるもので、通常の順番に部屋に入ってからシーンに遷移してしまうと同期がうまくいかず、シーンが切り替わった段階でオブジェクトが破棄されてしまう現象が起きる。
このため同期をルーム入室時から取り始めるのではなく、シーンを切り替え終わってから始めることを可能にするのがPhotonNetwork.IsMessageQueueRunningである。
ルームに入った瞬間にPhotonNetwork.isMessageQueueRunning = falseを呼んでイベントを受け取らないようにし、シーン切り替え後にPhotonNetwork.isMessageQueueRunning = trueを呼んで一斉にイベントを受け取ることで各プレイヤーのシーンを一度に同期させることができる。
一人では遷移を行わせないようにしているので、このロビー内で新たに生成されるオブジェクトとして考えられるのはボタンのみなのでボタンの生成スクリプトを見直す。
Infield buttonスクリプトのgameObject.SetActive(true);を削除してみるが効果なし。
public void Activate(RoomInfo info)
{
//gameObject.SetActive(true);
Debug.Log(info.PlayerCount);
}
このgameObjectはスクリプトがアタッチされているprefabの親階層かと思われるので、prefabそのものを取得できていないからエラーが生じているのではないかと考える。
Prefabの取得はroomlistviewBスクリプトで行われており、下記で参照をとっている。
[SerializeField]
private InputfieldButton roomListEntryPrefab = default; // Prefabの参照
同時に定義されている下記も確認する。
private Dictionary<string, InputfieldButton> activeEntries = new Dictionary<string, InputfieldButton>();
private Stack<InputfieldButton> inactiveEntries = new Stack<InputfieldButton>();
Dictionaryはキーと値をセットで指定し、キーで検索して値を取得する事ができるもので、
Dictionary<キーの型, 値の型> dictionary = new Dictionary<キーの型, 値の型> ();
の形で宣言される。
ボタン情報の更新の箇所で、現在はボタンの生成というよりもボタン内の機能がきちんと働くかを確認したいのでこのエラーは一旦保留にしておいて良いかもしれないと考える。
今確認したいのは2人が入室したタイミングでシーン遷移し、それぞれの画面にお互いのプレイヤーが写っている状況である。
Demoで入室した後にunityのエディターから入室したところ、
RoomName: Sample
HostName: Naki
Slots: 2 / 2
と表示され、同じSampleルームには入れていることがわかる。
ただ、そのあとのPhotonNetwork.CurrentRoom.PlayerCount == 2を読み込まず、振り出しに戻る。
ボタンの複製部分でのエラーとPhotonNetwork.CurrentRoom.PlayerCountの関係がわからず、一旦保留。質問中。
//3Dオブジェクトのインベントリ内収容
先日2Dでのインベントリを作成したので、3Dのものへ拡張する。
Inventory3Dシーンを作成し、2Dの画像ではなく3dのオブジェクトをクリックしたらインベントリーに対応する2Dの画像が表示されるようにしていく。
まずは3Dcubeをdestroyするだけのシーンを作成した。colliderとEvent triggerをアタッチし、Event triggerコンポーネントにはPointer Clickでクリックしたら下記のDestroyメソッドが実行されるようにした。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CubeD : MonoBehaviour
{
private void Start()
{
Debug.Log("a");
}
public void Destroy()
{
Destroy(this.gameObject);
Debug.Log("aaa");
}
}
クリックを察知させるレイを飛ばさせる必要があるので、cameraにはphysics raycasterコンポーネントをアタッチ。
きちんとメソッドは実行されたものの、クリック判定がうまくできておらず、cubeを複数回クリックしてやっとメソッドが発動してくれる状態でかなりの不満が残る。Ethanプロジェクトを作成した時もraycastでうまく対象との接触判定が取れなかったので、カメラから出すレイとcolliderとの接触については検証の必要があるかもしれない。
DropItemスクリプトを参考に先のcubeDスクリプトを編集して3Dオブジェクトをitem画像紐付け、2Dインベントリに反映させることができた。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CubeD : MonoBehaviour
{
public Item item;
private void Start()
{
Debug.Log("a");
}
public void Destroy()
{
Destroy(this.gameObject);
Debug.Log("aaa");
//アイテム取得
Inventory.instance.Add(item);
}
}
一回cubeへのクリック判定を実施させるのに十数回クリックしなくてはいけないのはさすがにおかしく感じたので、colliderをboxではなくsphereにしたらかなり当たりやすくなった。
インベントリーのUIの表示を表示・非表示で切り替えながらアイテム取得ができるかを確認した。
新たに下記のUIManagerを追加している。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UIManager : MonoBehaviour
{
[SerializeField] GameObject inventory;
bool flag = true;
private void Update()
{
if (Input.GetKeyDown("space"))
{
SelectInventory();
flag = !flag;
}
}
void SelectInventory()
{
if (flag)
{
inventory.SetActive(true);
}
else
{
inventory.SetActive(false);
}
}
}
UIを非表示にしていてもきちんとインベントリにアイテムが収納されていることがわかる。
次はプレイヤーに移動させて接触でアイテムを取得させるようにすること、そして、photonのルーム内での活動として実行できるようにしていく。