Hello World!我是山谷大叔~接下来我将出一系列Hololens开发教程(Hololens API解析、空间共享、第三视角Spatial View,MR交互设计,视音频通讯,服务器开发,多人游戏实战……),感兴趣的朋友可以关注我哦。下面开始放干货!(后续视频教程 群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; /// <summary> /// 当数据到达时调用 /// </summary> public delegate void OnDataReady(byte[] data); public event OnDataReady dataReadyEvent; /// <summary> ///是否有一个未完成的连接请求 /// </summary> private bool waitingForConnection = false; /// <summary> /// 保存最新的数据缓冲区数据 /// </summary> private byte[] mostRecentDataBuffer; /// <summary> ///要传给其他连接者的锚点数据 /// </summary> public void SetData(byte[] data) { mostRecentDataBuffer = data; } /// <summary> ///要传送锚点数据的设备IP /// </summary> public void SetServerIP(string ServerIP) { serverIP = ServerIP.Trim(); } /// <summary> ///重新连接服务器获取数据 /// </summary> 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