Hololens 使用Unet共享详细教程(四)

Hello World!我是山谷大叔~接下来我将出一系列Hololens开发教程(Hololens API解析空间共享、第三视角Spatial ViewMR交互设计视音频通讯服务器开发,多人游戏实战……),感兴趣的朋友可以关注我哦。下面开始放干货!(后续视频教程 群211031265)

本节讲解锚点数据的传输.

要想多台HoloLens共享,我们之前已经完成了用Unet实现消息的同步,现在还需要同步空间锚点,这样就能实现多台设备看到的物体实是在同一位置了。

Windows.Networking.Sockets 服务器和客户端

//UWP 下的命名空间
#if !UNITY_EDITOR && UNITY_WSA
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
using Windows.Networking;
using Windows.Foundation;
using System.Threading.Tasks;
using System;
 [Tooltip("网络连接端口")]
    public int SendConnectionPort = 11000;
    //IP地址
    private string serverIP;
    /// 
    /// 当数据到达时调用
    /// 
    public delegate void OnDataReady(byte[] data);
    public event OnDataReady dataReadyEvent;


    /// 
    ///是否有一个未完成的连接请求
    /// 
    private bool waitingForConnection = false;

    /// 
    /// 保存最新的数据缓冲区数据
    /// 
    private byte[] mostRecentDataBuffer;

    /// 
    ///要传给其他连接者的锚点数据
    /// 
    public void SetData(byte[] data)
    {
        mostRecentDataBuffer = data;
    }

    /// 
    ///要传送锚点数据的设备IP
    /// 
    public void SetServerIP(string ServerIP)
    {
        serverIP = ServerIP.Trim();
    }

    /// 
    ///重新连接服务器获取数据
    /// 
    public void RequestAndGetData()
    {
        ConnectListener();
    }

  //下面的代码只有只UWP下运行,编辑器下无法运行
#if !UNITY_EDITOR && UNITY_WSA

       // 客户端Socket连接对象
        private StreamSocket networkConnection;
       //服务器Socket监听器
        private StreamSocketListener networkListener;
       //连接失败时重新连接的等待时间
       private float timeToDeferFailedConnections = 10.0f;

        //配置服务器
        public void ConfigureAsServer()
        {
            //开始一个线程启动服务器监听
            Task t = new Task(() =>
            {
                networkListener = new StreamSocketListener();
                networkListener.ConnectionReceived += NetworkListener_ConnectionReceived;
                networkListener.BindServiceNameAsync(SendConnectionPort.ToString()).GetResults();
            }
                );
            t.Start();
        }

        // 有客户端连接时的回调
        private void NetworkListener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
        {
            //发送数据
            if (mostRecentDataBuffer != null)
            {
                IOutputStream stream = args.Socket.OutputStream;
                using (DataWriter writer = new DataWriter(stream))
                {
                    writer.WriteInt32(mostRecentDataBuffer.Length);
                    writer.WriteBytes(mostRecentDataBuffer);
                    writer.StoreAsync().AsTask().Wait();
                    writer.FlushAsync().AsTask().Wait();
                }
            }
            else
            {
                Debug.LogError("已经有客户端连接,但是没有要发送的数据!");
            }
        }

        //连接服务器,获取数据
        private void ConnectListener()
        {
            if (waitingForConnection)
            {
                return;
            }
            Debug.Log("Connecting to " + serverIP);
            waitingForConnection = true;
            HostName networkHost = new HostName(serverIP);
            networkConnection = new StreamSocket();

            IAsyncAction outstandingAction = networkConnection.ConnectAsync(networkHost, SendConnectionPort.ToString());
            AsyncActionCompletedHandler aach = new AsyncActionCompletedHandler(RcvNetworkConnectedHandler);
            outstandingAction.Completed = aach;
        }

        //当连接到服务器时,开始读取数据,调用此方法。
        private async void RcvNetworkConnectedHandler(IAsyncAction asyncInfo, AsyncStatus status)
        {
            // 连接成功时
            if (status == AsyncStatus.Completed)
            {
                DataReader networkDataReader;
                //接收数据
                using (networkDataReader = new DataReader(networkConnection.InputStream))
                {
                    //读取前四个字节用于获取数据长度
                    DataReaderLoadOperation drlo = networkDataReader.LoadAsync(4);
                    while (drlo.Status == AsyncStatus.Started)
                    {
                        // just waiting.
                    }

                    int dataSize = networkDataReader.ReadInt32();
                    if (dataSize < 0)
                    {
                        Debug.Log("数据解析错误");
                    }

                   //新建一个dataSize大小的缓冲区。
                    mostRecentDataBuffer = new byte[dataSize];
                   //读取数据
                    await networkDataReader.LoadAsync((uint)dataSize);
                    networkDataReader.ReadBytes(mostRecentDataBuffer);
                   //读取完成后,调用注册的方法
                   dataReadyEvent?.Invoke(mostRecentDataBuffer);
                }
            }
            else
            {
                Debug.Log("建立连接失败: " + asyncInfo.ErrorCode);
                //重新连接
                Invoke("RequestAndGetAnchor", timeToDeferFailedConnections);
            }
            //断开连接
            networkConnection.Dispose();
            waitingForConnection = false;
        }

#else
    //配置服务器接口(实际调用在上面的同名方法)
    public void ConfigureAsServer()
    {
        Debug.Log("ConfigureAsServer编辑器模式不执行");
    }
    //连接服务器,获取数据实际调用在上面的同名方法)
    private void ConnectListener()
    {
        Debug.Log("ConnectListener编辑器模式不执行");
    }
#endif


如果有什么疑问或者发现笔者的错误请留言!
下一节讲解 相关的内容~~~

获取源码请在群资料中下载

Hololens MR 技术交流群 211031265


你可能感兴趣的:(Hololens开发)