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