0 支持
(140 ポイント)
MonobitNetwork.Instantiate(Player.name, trans.position, trans.rotation, 0, null, false, true, false);

上記の様な形でMonobitNetwork.Instantiateでキャラクターを生成して何度もルームに再入場すると(MissingReferenceException:Theobject of type 'GameObject' has been destroyed but you are still trying to access it Your script should either check if it is null or you should not destory the object.)というエラーが出ます。ホストは部屋にいたままでUnity上のエディタで観察してました。同じキャラクターが何度も出入りするとすでに破棄されたオブジェクトに破棄されてしまう事はあるのでしょうか?またこれの解決方法があったら教えていただけると幸いです。

回答 2

0 支持
(2.2k ポイント)

MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.

この例外がどういったスクリプト上で発生しているかによって、解決方法は異なります。

まずはその例外が発生したエラーメッセージについて「全文」を知る必要があるので、Unityエディタ上のコンソールから該当するメッセージをクリックして、コード上のどこに発生しているかということを確認してください。

https://imgur.com/TPQ3oLr

上記は RandomMatching サンプル上で故意にMissingReferenceExceptionを発生させたサンプルですが、上述のようにエラー文に引き続いて、 Assets/Monobit Unity Networking/Samples/Scripts/RandomMatching/OfflineScene.cs の 40 行目にエラーがあるとしっかり書かれます。

このような形で、具体的にどこで発生しているのかを明快にした状態であれば、解決の糸口が見つかると思いますので、スクリーンショットをどこかの画像アップローダ(あるいはGoogleDriveなどのオンラインストレージ)に共有してください。

0 支持
(2.2k ポイント)
編集

先の回答とは別のアプローチですが、GameObject が破棄されるタイミングを意識していますでしょうか?

https://docs.unity3d.com/ja/current/ScriptReference/Object.Destroy.html

通常 GameObject が破棄されるタイミングは、破棄が実行された後、次の Update() メソッドが実行されるのを待つ必要があります。そこまでオンメモリ上の GameObject は破棄されていません。

ネットワーク通信を介するのであれば、「あるクライアントがルームから退室したメッセージを受け取った時点から、更に次の Update() メソッドが実行される」まで GameObject は破棄されずに残ります。この間に「あるクライアントからの再入室メッセージを受け取る」というケースがあるのであれば、GameObject に対する MissingReferenceException は発生しうるかもしれません。

ただ、このケースが考えられるのが、例えば UDP などのパケット順が正順である保証がないプロトコルで接続し、十分なネットワーク帯域が担保されていない状態でアプリケーションを動作させた場合、サーバを介した他クライアント上において「あるクライアントに対する退室メッセージを受け取ったタイミングと、再入室メッセージを受け取ったタイミングが同時になる、または退室メッセージを後で受け取る」というケースくらいだと思うのですが、UDP の通信を行う上でパケットの順序が逆転するという(パケロスが発生しない環境では順序が逆になることは考えられない)劣悪な通信環境のまま、サーバへの接続を維持しつつ行なうという荒業自体が不可能だと思いますので、この現象自体を同一端末上から発生させるのは困難だと思います。

ただし、仮に先の回答内容で、junyaさんが作成したプログラム以外(例えばMUNの内部コードのどこか)で MissingReferenceException が発生しているとするならば、上記内容を鑑みて、退室→入室の送信タイミングに時間間隔を設けるなどする必要があると思います。例えば接続コールバック( http://www.monobitengine.com/doc/mun/contents/FeatureClient/CallbackFunction.htm )を利用して

bool flag = false;

void FooFunction() {
    // 入室処理は flag = false 以外に実行しない
    if( !flag ) {
        MonobitNetwork.JoinRoom(~);
    }
}

// フラグの ON/OFF は接続コールバックにより実行する
void OnJoinRoom() { flag = true; }
void OnLeftRoom() { flag = false; }
void OnDisconnectedFromServer() { flag = false; }

というように、接続コールバック(サーバからの応答)を待って処理をするなど、入退室の処理頻度を低減すれば、問題の発生を抑えられるのではないかと思います。

(140 ポイント)
ご丁寧な回答ありがとうございます。エラーを読み何度も検証した結果、MonobitNetwork.Instantiateが原因ではなく、所有権を持つキャラクターに所有権のない武器を持たせたままキャラクターが退室する→そして、その後にその人または他の誰かが入室するとホストだけにエラーがでるいう条件で発生するものでした。解決策は武器を拾った時にmonobitView.RequestOwnership()で拾ったキャラに所有権を移譲することで解決できました。わかりずらい質問で申し訳ありませんでしたが、丁寧なご回答をありがとうございました。
...