XRインタラクションToolKitとPUNをベースにしたVRマルチプレイヤーコラボレーション機能を実現

        最近、VR全体でマルチパーソンコラボレーションの開発に取り組んでいますが、このエリアを開発するためにあまり多くの人に連絡していないため、多くの落とし穴に遭遇しました。ここにいくつかの個人的な経験の要約を示します。

1.開発環境の構成

       Unityバージョン:2019.3.4

       関連するプラグインバージョン:

      ユニバーサルRP7.1.8

      XRインタラクションTookitプレビュー-0.9.4

      PUN2 2.22

    XRインタラクションTookitについて

      以前に関連する紹介と手順を実行しました。XRInteractionToolKitによって開発されたVRデュアルプラットフォーム互換プロジェクトに基づいたこの記事参照してください (1)ここで はあまり説明しません。

    PUN2について

        PUN(Photon Unity Networking)は、Unityでよく知られているマルチパーソンインタラクションソリューションです。インターネット上には多くの紹介や説明があるので、ここでは繰り返しません。ただし、ここで説明するPUN用に最適化できるネットワーク構成があります。PUNサーバーはデフォルトですべて海外にあるため、国内での使用が遅れる場合があります。中国のPotonの公式ウェブサイトにアクセスして、無料の国内サーバーを申請できます。具体的な方法は次のとおりです。

1.公式ウェブサイト(https://vibrantlink.com/)にアクセスします

2.ホームページで「ChinaPhotonCloudの無料アプリケーション」を見つけます

3.関連情報を記入し、審査のために提出します。ここで、中国地域にカットする必要がある公式Webサイトで作成されたappidは、申請フォームに入力する必要があり、選択しないように注意する必要があります。間違ったタイプ。

4. 1〜2営業日後にメールボックスで正常な電子メールが受信されたら、Unityで構成できます。

5. PUNの構成ファイルPhotonServerSettingsを1つに見つけ、内部の固定領域をCNに変更し、スクリプトLoadBalancingClient.csを見つけて、内部のNameServerHostの属性をns.photonengine.cnに変更します。

上記のオプションを構成した後、ネットワーク速度が基本的に50ms未満であることをテストしました。

2.開発の詳細

1.モデルのロードと同期

PUNが提供するPhotonNetwork.Instantiateメソッドを使用して、ローカルモデルを作成し、それぞれのクライアントに同期させることができます。ただし、サーバーにモデルリソースをダウンロードして他のユーザーと同期する場合は、他の関連する方法と協力して実現する必要があります。

Photonが提供するコンポーネント同期方法を使用して、同様の効果を実現しています。具体的な実装は次のとおりです。

a。PhotonNetwork.Instantiateを使用して空のオブジェクトを作成し、その上にphotonViewコンポーネントをマウントし、カスタム同期ロードクラスModelEntityもマウントします。このクラスはIPunObservableインターフェイスを継承し、OnPhotonSerializeViewメソッドを実装する必要があります。自動的にphotonViewが検出されます。

    ModelEntityの関連コードは次のとおりです。

public class ModelEntity : MonoBehaviourPunCallbacks, IPunObservable
    {

        string id;
        int num;
        public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
        {
            //拥有者 会把数据不断发送给其他人
            if (stream.IsWriting)
            {

                stream.SendNext(id);
                stream.SendNext(num);
            }
            else
            {

                // 其他用户 当拥有者发送数据会接收到数据
                id= (string)stream.ReceiveNext();
                num= (string)stream.ReceiveNext();


            }
        }

    }
}

b。同期されたgameObjectオブジェクトをインスタンス化した後、作成者は同期する必要のあるIDデータをModelEntityに渡し、サーバーシーンをローカルにロードします。他のユーザーは作成されたgameObjectオブジェクトの空のオブジェクトをPhotonネットワーク経由で取得します。対応するIDが検出されると、対応するIDのモデルがネットワークを介してローカルにロードされます。このようにして、サーバーのモデルを同期的にロードする機能が簡単に実現されます。

2.オブジェクトの乗っ取りと操作

アプリケーションで作成された同期オブジェクトは、デフォルトでは作成者のみが操作できます。他のユーザーがオブジェクトを引き継いで変換または削除操作を実行する場合は、オブジェクトを操作する権限を取得する必要があります。具体的な操作は次のとおりです。次のように:

a。同期されたオブジェクトによってマウントされたphotonViewコンポーネントの所有権の転送をTakeoverに設定し、このオブジェクトが引き継がれることを示します

b。コードを使用してこのオブジェクトのphotonViewを取得し、gameObject.GetComponent <PhotonView>()。TransferOwnership(PhotonNetwork.LocalPlayer)を設定します。この操作は、オブジェクトの制御権をローカルユーザーに強制するためのものです。

c。オブジェクトの変換情報を同期する必要がある場合は、PhotonTransformViewコンポーネントをオブジェクトに掛けて、必要に応じて位置、回転、スケールを確認できます。このようにして、ローカルユーザーはに直接ドラッグアンドドロップできます。シーンまたはコードで設定します。他のネットワークユーザーと同期します

d。オブジェクトの削除PhotonNetwork.Destroy()を介して、ネットワークによって同期されたオブジェクトを破棄できます。

 

3.VRユーザーオブジェクトの作成

マルチプレイヤーVRでは、カメラコンポーネントを介してワールドオブジェクトを表示するだけでよいため、ユーザーごとにカメラを作成する必要はありません。代わりに、他のユーザーカメラを追加するとエラーが発生します。他のVRユーザーを本当に同期する必要がある場合は、PhotonNetwork.Instantiateを使用してプレーヤーのオブジェクトモデルを作成し、ローカルカメラの位置をこのオブジェクトモデルに継続的に同期します(VR内のアバターの位置はカメラの位置です)

4.VR線画機能の実現

複数人のインタラクションで、ハンドルを「ペン」として使用して線を描画し、それを他のユーザーと同期する必要がある場合、これにはLineRendererと同期の知識ポイントが含まれます。LineRendererを使用して、ハンドルが通過する各パスポイントを記録して線として描画し、他のユーザーのワールド座標に同期します。ここで、線の「点」を同期的に描画する操作は、描画中に同期的にではなく、ユーザーが線を描画した後に行われることに注意してください。両側のネットワーク状態の遅延が何であるかわからないため、ルートを描画して同期している場合、ローカルでは正常に見えますが、他のネットワークユーザーに表示されるのは基本的に混乱です。

同時に、フレームごとにポイントを取ることはお勧めしません。そうしないと、ネットワークの負荷が大きすぎます。また、各位置でポイントを取ることはお勧めしませんが、ポイントとポイントの間の距離が特定のしきい値よりも大きいと判断した後にポイントを取ることは、多数のポイントが存在する状況を回避するために推奨されます。同じ位置。

5.部屋を出るユーザーの取り扱い

ユーザーが部屋を離れるとき、または異常なネットワーク切断のために、PhotonNetwork.Instantiateを介してユーザーが作成したオブジェクトは削除されませんが、デフォルトでClientMasterに転送されます。ユーザーが位置を同期するためのキャラクターモデルを作成した場合、この時点でシーンに残されます。したがって、ドロップされたオブジェクトを処理する必要があります。私の処理方法は、作成したユーザーアバターに部屋を出るユーザーの検出イベントを追加することです。ユーザーがこのアバターに対応するモデルであることが検出されると、オブジェクトが削除されます。具体的な実装コードは次のとおりです。

    public override void OnPlayerLeftRoom(Player otherPlayer)
    {
        if (owner == otherPlayer.NickName)
        {
            PhotonNetwork.Destroy(gameObject);
        }
    }

所有者は、オブジェクトがインスタンス化されたときに取得されるLocalPlayer.NickNameです。切断されたユーザー名を判断するためにphotonView.owner.NickNameを直接使用しない理由を尋ねる人もいるかもしれません。前述のように、ユーザーが切断すると、モデルはデフォルトでClientMasterに切り替わり、自然に取得されたphotonView.ownerはそれに対応しません。 。オンラインユーザー。

さりげなく要約

マルチパーソンのインタラクティブプログラミングに触れたのは初めてなので、多くのことが盲目でできており、それらのほとんどは最適な解決策ではないかもしれません。間違いがあれば、誰かがそれを修正してくれることを願っています。 。同時に、このブロガーの記事チュートリアル[私はオレンジ色です]にとても感謝しています。本当にたくさんのことを学びました。

 

おすすめ

転載: blog.csdn.net/ssssssilver/article/details/109531179