仮想と物理とエトセトラ

xRや物理とかごった煮の備忘録的技術ブログ

Netcode for GameObjects (旧MLAPI)をHoloLensで使ってみる その2

今回は前回の続きです。

xr-physics-work-etc.hatenablog.com

前回、Hostとして使用したHoloLens2の頭位置は共有されましたが、Clientとして接続したUnityEditorでは共有できませんでした。
この問題を解消します。

下記記事によると、以前のMLAPIからの変更点として、NetworkTransformでは、Server側からのTransform共有ができないようです。
Client側から共有する方法として、ClientNetworkTransformを用いる方法があるようです。

xrdnk.hateblo.jp

今回は下記を元にClientNetworkTransformを用いてClient側からも頭の位置を共有できるようにします。

docs-multiplayer.unity3d.com

前提

今回の環境は以下です。

Unity 2020.3.16
MRTK 2.7.3
Netcode for GameObjects 1.0.0-pre.4

準備

まずは、ClientNetworkTransformを用意します。
ClientNetworkTransformはnet code for GameObjectsの標準APIとしては存在しません。
サンプルとして用意されているため、まずはそれを導入します。

Unity上部メニューの「Window」→「Package Manager」からPackage Managerウィンドウを開きます。
f:id:napo909:20220116155345p:plain

Package Managerウィンドウから、「Netcode for GameObjects」を選択すると左欄に「Samples」という項目があります。
「Samples」の文字列をクリックすると用意されているサンプルが展開されます。
そこに「ClientNetwork Transform」があるので、Importボタンを押して取得します。
f:id:napo909:20220116155625p:plain

正常に導入できると、Assets/Samples/Netcode for GameObjects/1.0.0-pre.4ClientNetworkTransformフォルダが作成されています。
f:id:napo909:20220116160337p:plain

ClientNetworkTransform/Scriptsフォルダ内にClientNetworkTransform.csがあります。
ClientNetworkTransform.csを見ると、以下の記載がありました。

クライアント側の変更に伴うtransformの同期に使用します。これにはホストも含まれます。所有者としての純粋なサーバーは、これではサポートされていません。常にサーバーが所有するようなトランスフォームには NetworkTransform を使用してください。 (Deepl翻訳)

github.com

これは、L34にあるように、サーバ側にクライアントが所有しているオブジェクトのTransformを送り、サーバ側で処理しているためです。
サーバ用アプリを用意する場合は、NetworkTransform、ホスト、クライアントで用いる場合はClientNetworkTransformを使うのがよさそうです。

ユーザ位置はサーバ側アプリで使用しないため、Playerプレハブにアタッチするコンポーネントを、ClientNetworkTrnasformに変更しました。

f:id:napo909:20220116171811p:plain

HoloLens→PC接続

PCではUnityEditorからInspectorを用いて接続先IPを設定できましたが、HoloLensではそうもいきません。
そのため、HoloLensをClientとしてHostであるPCに接続するために、InputFieldを用いて接続先IPを設定する口を用意しました。
f:id:napo909:20220116172013p:plain

前回使用したNetworkConnectButtonFunctions.csを改修し、Input Filedが更新された際にIPアドレスとして設定されるようにします。

  • NetworkConnectButtonFunctions.cs
クリックで展開
using UnityEngine;
using Unity.Netcode;
using Unity.Netcode.Transports.UNET;
public class NetworkConnectButtonFunctions : MonoBehaviour
{
    /// <summary>
    /// ネットワークマネージャ
    /// </summary>
    private NetworkManager networkManager;


    void Start()
    {
        // ネットワークマネージャインスタンス取得
        networkManager = NetworkManager.Singleton;
        if(networkManager == null)
        {
            this.gameObject.SetActive(false);
        }
    }

    /// <summary>
    /// ホストとして接続
    /// </summary>
    public void ConnectAsHost()
    {
        networkManager.StartHost();
    }

    /// <summary>
    /// サーバとして接続
    /// </summary>
    public void ConnectAsServer()
    {
        networkManager.StartServer();
    }

    /// <summary>
    /// クライアントとして接続
    /// </summary>
    public void ConnectAsClient()
    {
        networkManager.StartClient();
    }

    /// <summary>
    /// 接続切断
    /// </summary>
    public void Disconnect()
    {
        networkManager.Shutdown();
    }

    /// <summary>
    /// 接続先設定 <-------追加箇所
    /// </summary>
    /// <param name="ipString"></param>
    public void SetIP(string ipString)
    {
        networkManager.gameObject.GetComponent<UNetTransport>().ConnectAddress = ipString;
    }
}

f:id:napo909:20220116172143p:plain

動作確認

今回は、PC側をHost (Server + Client), HoloLens側をClientで接続しました。
PCでHost接続後、HoloLensからClient接続しています。
f:id:napo909:20220116172430g:plain

ClientNetworkTransform.csを用いることで、Clientの動きもHost (Server)側から確認することができました。
これで、HostもClientもお互いの動きを確認できます。

次回は、共有で重要な同じ物体をHost、Clinetで動かし、位置を共有することを試します。