MRが楽しい

MRやVRについて学習したことを書き残す

SharingWithUNETについてまとめる その5

本日は HoloToolKit の調査枠です。
SharingWithUNET のサンプルシーンを確認していきます。
bluebirdofoz.hatenablog.com

今回は Manager オブジェクトにある GenericNetworkTransmitter について機能を確認します。
f:id:bluebirdofoz:20180108224901j:plain

GenericNetworkTransmitter は作成したワールドアンカーデータの送受信を行います。
接続先のサーバのIPアドレスは NetworkDiscoveryWithAnchor スクリプトが検出し、本スクリプトの SetServerIp() に通知します。
サーバのIPアドレスに対して、接続要求を一定間隔で実施します。
サーバ側は UNetAnchorManager スクリプトがアンカーデータのシリアル化の完了と共に、本スクリプトの ConfigureAsServer() をキックしてソケットリスナーを起動します。

自作アプリを組み込む際にはひとまずノータッチでも問題なさそうです。
ただ、本スクリプトと UNetAnchorManager スクリプトはシェアリングのワールドアンカーの取り扱いをまとめたスクリプトですので、理解を深めて損はなさそうです。

Send Connection Port

アンカーデータの送受信を行うポート番号を指定する。

        /// <summary>
        /// Tells us who to contact if we need data.
        /// データが必要な場合に、連絡先を教えます。
        /// </summary>
        /// <param name="newServerIp"></param>
        public void SetServerIp(string newServerIp)
        {
            serverIp = newServerIp.Trim();
        }

        /// <summary>
        /// Configures the network transmitter as the source.
        /// ネットワークトランスミッタをソースとして設定します。
        /// </summary>
        public void ConfigureAsServer()
        {
#if !UNITY_EDITOR && UNITY_WSA
            Task t = new Task(() =>
            {
                // ソケットリスナーを作成する。
                networkListener = new StreamSocketListener();
                // 接続時のイベント関数として NetworkListener_ConnectionReceived を登録する。
                networkListener.ConnectionReceived += NetworkListener_ConnectionReceived;
                // StreamSocketListenerのバインド操作をローカルサービス名に開始する。
                networkListener.BindServiceNameAsync(SendConnectionPort.ToString()).GetResults();
            }
                );
            t.Start();
#else
            Debug.Log("This script is not intended to be run from the Unity Editor");
            // In order to avoid compiler warnings in the Unity Editor we have to access a few of our fields.
            // Unity Editorでコンパイラの警告を避けるために、いくつかのフィールドにアクセスする必要があります。
            Debug.Log(string.Format("serverIP = {0} waitingForConnection = {1} mostRecentDataBuffer = {2}", serverIp, waitingForConnection, mostRecentDataBuffer == null ? "No there" : "there"));
#endif
        }

#if !UNITY_EDITOR && UNITY_WSA
        /// <summary>
        /// When a connection is made to us, this call back gets called and
        /// we send our data.
        /// 私たちとの接続が確立されると、このコールバックが呼び出され、データが送信されます。
        /// </summary>
        /// <param name="sender">The listener that was connected to.(接続されたリスナー)</param>
        /// <param name="args">some args that we don't use.(私たちが使用していない幾つかの引数)</param>
        private void NetworkListener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
        {
            // If we have data, send it. 
            // データがある場合は送信する。
            if (mostRecentDataBuffer != null)
            {
                // データバッファにデータがある場合

                // 出力ストリームを取得する。
                IOutputStream stream = args.Socket.OutputStream;
                // ストリームにデータを書き込む。
                using (DataWriter writer = new DataWriter(stream))
                {
                    // 先頭32ビットにデータ長を設定する
                    writer.WriteInt32(mostRecentDataBuffer.Length);
                    // データバッファの内容を設定する。
                    writer.WriteBytes(mostRecentDataBuffer);
                    // バッファーのデータをコミットする。
                    writer.StoreAsync().AsTask().Wait();
                    // バッファーをクリアして書き込む。
                    writer.FlushAsync().AsTask().Wait();
                }
            }
            else
            {
                // 送信するデータはありませんが、接続されています。これは予期しないことです。
                Debug.LogError("No data to send but we've been connected to.  This is unexpected.");
            }
        }