0 支持
(190 ポイント)

Oculus Integrationのcamerarigを使用してマルチプレイゲームを制作しているのですが、

複数クライアントで実行すると片方が視点を移動させるともう片方の視点も同期して動いてしまいます。なにか対策法はないでしょうか?

1点 MonobitTransformViewのRotationを切ることによって同期させないことはできるのですが、

プレイヤー同士の画面でお互いの視点移動を確認することができないので今回の問題の解決にはいたりませんでした。何か実例等があればお教えいただけると幸いです。

回答 1

0 支持
(1.1k ポイント)
選択
 
ベストアンサー
CameraRigのオブジェクト同期をMonobitTransformViewを使わず(MonobitTransformViewを外して)、CameraRigに対し以下のスクリプトを埋め込むことで対応できるのではないでしょうか?

class Foo : MonobitEngine.MonoBehaviour {
    // オブジェクト同期
    void OnMonobitSerializeView( MonobitEngine.MonobitStream stream,
                                                MonobitEngine.MonobitMessageInfo info ) {
        // 自分が保持するオブジェクトでなければ送受信しない
        if(!monobitView.isMine) return;

        if(stream.isWriting) {
            stream.Enqueue(gameObject.transform.position);
            stream.Enqueue(gameObject.transform.rotation);
            stream.Enqueue(gameObject.transform.scale);
        } else {
            gameObject.transform.position = (UnityEngine.Vector3)stream.Dequeue();
            gameObject.transform.rotation = (UnityEngine.Quaternion)stream.Dequeue();
            gameObject.transform.scale = (UnityEngine.Vector3)stream.Dequeue();
        }
    }
}
(190 ポイント)
返信ありがとうございます。
試してみたのですが、MonobitViewを入れる場所やオブジェクトを
管理するところがわからないのでご確認いただけると幸いです。
https://drive.google.com/drive/folders/1FqsU2Msj55OgHZxLSFKBnxyQCcD5eUZY?usp=sharing
画像データも用意してあるのでよろしくお願いします。
(1.1k ポイント)
MonobitViewは親オブジェクト(Player)で良いと思います。加えて、同じPlayerにスクリプトを追加して(以下の例で言えばFoo.csという名前に変更して)、以下のようにコード組めばいけると思いますよ。

class Foo : MonobitEngine.MonoBehaviour {

    // cameraRigオブジェクト
    UnityEngine.GameObject camRigObj = null;

    // Start
    public void Start() {
        camRigObj = transform.Find( "OVR CameraRig" );
    }

    // オブジェクト同期
    void OnMonobitSerializeView( MonobitEngine.MonobitStream stream,
                                                MonobitEngine.MonobitMessageInfo info ) {

        // 自分が保持するオブジェクトでなければ送受信しない
        if(!monobitView.isMine) return;
        if(camRigObj == null) return;

        if(stream.isWriting) {
            // 送信
            stream.Enqueue(camRigObj.transform.position);
            stream.Enqueue(camRigObj.transform.rotation);
            stream.Enqueue(camRigObj.transform.scale);
        } else {
            camRigObj.transform.position = (UnityEngine.Vector3)stream.Dequeue();
            camRigObj.transform.rotation = (UnityEngine.Quaternion)stream.Dequeue();
            camRigObj.transform.scale = (UnityEngine.Vector3)stream.Dequeue();
        }
    }
}
(190 ポイント)
返信ありがとうございます。
スクリプトを追加し実行する際にMonobitTransformViewを使わない場合だと2台で試すと位置関係を同期できないため失敗してしまいました。
お手数だとは思うのですが、プロジェクトを一度確認いただけないでしょうか。
現在発生している問題が
プレイヤーを二人 配置した際のカメラの動きが相手のアバターにも同期してしまう
MonobitTransformViewをきってインスタンスをすると相手との位置同期ができない
の2点になります
たびたび申し訳ございません。よろしくお願いします
https://drive.google.com/drive/folders/1-6Hy5VnsCjibviik5MiXg-oOYOcLTHBG?usp=sharing
(1.1k ポイント)
回答に時間が掛かって申し訳ありません。もうすでに解決されているかも知れませんが、以下のように置き換えることで実現可能だと思います。まだ解決されていない場合には改めてご参照ください。

https://drive.google.com/drive/folders/1sMeA5v1OHssG9kE2S1asS-VHUr_KLHn2?usp=sharing

なお勝手ながら、プロジェクトの編集は Unity2018.4.0 で行なっていますので、不都合があったり開けなかったりした場合には仰ってください(一応適用内容を簡単に示した画像も添付しますので、それでご確認をいただければ大丈夫だと思います)。
(100 ポイント)
横から失礼します。
0125さんと同様、Oculus Integrationを用いてマルチプレイVR制作を試してみたいと思い、参考に最後の回答にあるGoogleドライブのプロジェクトをダウンロードしてみました。
プラットフォームをAndroidに変更して使用しているOculus Questにビルド+実行、Questを2台は持っていないので片方はUnityエディタで実行(プラットフォームはPCに戻しました)すればテストになるかな?と思ったところ、Questで見える2体のインサイドちゃん両方に自分の動きが適用されました。
この原因は分かりますでしょうか?プロジェクト中のスクリプト「Foo」は、6/26の回答にある
camRigObj = transform.Find( "OVR CameraRig" );
をしていないようですが、これは関係しますでしょうか?
VR制作でネットワークものを試すのは初めてで、見当違いのことをしていたら申し訳ありません。当方環境はUnity2018.4.4f1(64-bit)です。Unityエディタで実行する方はスクリプト「MUNtest」のinstantiateする位置を識別用に少しずらしました。

QuestではなくGoの操作系で認識されているようで、片方のコントローラのみ動きが反映され、トリガを引くとそれが左右入れ替わる現象も発生しています。OVR ManagerにてTarget Devicesを選ぶ箇所が無かったので、Oculus Integrationを再インポートしましたがどうしてもTarget DevicesのあるOVR Camera Rigにならず。こちらはネットワーク関連とは違う問題かと思いますが。

お手数をお掛けしますが、よろしくお願いします。
(1.1k ポイント)
編集
> プラットフォームをAndroidに変更して使用しているOculus Questにビルド+実行、
> Questを2台は持っていないので片方はUnityエディタで実行
> (プラットフォームはPCに戻しました)すればテストになるかな?と思ったところ、
> Questで見える2体のインサイドちゃん両方に自分の動きが適用されました。
> この原因は分かりますでしょうか?

単純な話で、OVR CameraRig, OVR Headset Emulator, OVR Manager が「認識された VR デバイスに依存して検出するから」ですね。VRデバイスが非搭載のものでは認識されず、VRデバイスのある側に釣られて動くだけです。

もしデバイスがない状態であれば、上記の Foo.cs に対し、

    void Update()
    {
        // 所有権がないオブジェクトの Oculus VR コンポーネントをひとまず無効化
        if(!monobitView.isMine)
        {
            gameObject.GetComponentInChildren<OVRCameraRig>().enabled = false;
            gameObject.GetComponentInChildren<OVRManager>().enabled = false;
            gameObject.GetComponentInChildren<OVRHeadsetEmulator>().enabled = false;
        }
    }


する必要があります。
加えて当然のことながら、この状態では OVR CameraRig 以下のオブジェクト操作自体が無効になるので、以下に示す通り、Foo.cs 内の OnMonobitSerializeView() メソッド内で「Playerオブジェクトに含まれるすべての子階層のTransform送受信処理」を組み込むことになると思いますが。

    void OnMonobitSerializeView( MonobitEngine.MonobitStream stream,
                                                MonobitEngine.MonobitMessageInfo info ) {

        if(camRigObj == null) return;

        if(stream.isWriting) {
            // 送信
            stream.Enqueue(camRigObj.transform.position);
            stream.Enqueue(camRigObj.transform.rotation);
            stream.Enqueue(camRigObj.transform.localScale);
            // 子オブジェクトの姿勢を送信
            foreach (Transform child in camRigObj.transform)
            {
                stream.Enqueue(child.gameObject.transform.position);
                stream.Enqueue(child.gameObject.transform.rotation);
                stream.Enqueue(child.gameObject.transform.localScale);
            }
        }
        else {
            // 受信
            camRigObj.transform.position = (UnityEngine.Vector3)stream.Dequeue();
            camRigObj.transform.rotation = (UnityEngine.Quaternion)stream.Dequeue();
            camRigObj.transform.localScale = (UnityEngine.Vector3)stream.Dequeue();
            // 子オブジェクトの姿勢を受信
            foreach (Transform child in camRigObj.transform)
            {
                child.gameObject.transform.position = (UnityEngine.Vector3)stream.Dequeue();
                child.gameObject.transform.rotation = (UnityEngine.Quaternion)stream.Dequeue();
                child.gameObject.transform.localScale = (UnityEngine.Vector3)stream.Dequeue();
            }
        }
    }

> プロジェクト中のスクリプト「Foo」は、6/26の回答にある
> camRigObj = transform.Find( "OVR CameraRig" );
> をしていないようですが、これは関係しますでしょうか?

これは関係しません。これと同じことを https://drive.google.com/drive/folders/1sMeA5v1OHssG9kE2S1asS-VHUr_KLHn2 の PlayerInspector.png でやってます。

加えて蛇足ながら。
関連する質問とはいえ、1度ベストアンサーがついたトピックで更なる質問を行なうのは好ましい状況ではないと思いますので(解決したかどうか判断できない)、これ以降の質問は別に質問トピックを立てて質問していただいた方がよいと思います。上記で解決できていればそれに越したことはないのですが。
...