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

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


本节讲解网络通信这一块,Hololens MR应用是UWP的,网络这块客户端使用.NET的System.Net.Sockets会有一些问题,有些同步方法不兼容UWP平台SocketAsyncEventArg可以使用,或者使用Windows.Networking.Sockets。对UWP开发不熟悉的开发者建议先去看一下官方的入门教程,先有个大概了解。为了快速开发,了解整个过程。我先使用Unity 提供的Unet网络模块,经测试是可以跑在Hololens上的。但为了稳定性、效率、可扩展性等因素,我之后会出一个用System.Net.Sockets 或者 Networking.Sockets的开发的教程。好了下面就开始吧!

1.Unet 介绍

不熟悉Unet的同学请百度之

想了解源码的请点击Unet源码

2.网络发现NetworkDiscover

网络发现用于在局域网内,客户端收到服务端发送的广播,发现服务端,这样就可以知道服务端的IP地址,用于自动连接,就不用在holoens上手势点击输入IP了,能够快速开始应用。

发送和接受广播
using UnityEngine;
using UnityEngine.Networking; 
public class NetworkDiscoveryManager : NetworkDiscovery
 {
   //是否收到广播
   public bool receivedBroadcast { get; private set; }
    //控制广播发送的频率(毫秒)
   private int BroadcastInterval = 1000;
   //发送广播设备的IP地址
    public string ServerIp { get; private set; }
   private void Start()
   {
    //初始化NetworkDiscovery。
    Initialize();
    if (NetworkManager.singleton == null)
     {
    Debug.Log("需要 NetworkManager组件");
    return ;
     }
     //作为客户端监听广播
     StartAsClient();
     //作为服务端发送广播(第一个启动的设备)
      StartAsServer();
    }
    //开始监听广播
   public override void OnReceivedBroadcast(string fromAddress, string data)
  {
            //从广播中接收ip数据,如果已经接收过了就不需要接收了
            if (receivedBroadcast)
            {
                return;
            }
            receivedBroadcast = true;
            //停止接听/发送广播
            StopBroadcast();     
            //把广播设备的IP保存
            ServerIp = fromAddress.Substring(fromAddress.LastIndexOf(':') + 1);
                  //设置NetworkManager的IP
            NetworkManager.singleton.networkAddress = ServerIp;            
            //自己作为一个客户端连接上服务器IP
            NetworkManager.singleton.StartClient();
   }
    private void StartAsServer()
  {
            //如果接收到了广播,说明已经有设备先广播了并作为了服务器,就接收广播,并连接

            if (receivedBroadcast)
            {
                return;
            }
             //如果没有接收到了广播,说明还没有设备创建服务器
             StopBroadcast();//停止接听/发送广播
            //开启本机服务器(也可以作为客户端)
            NetworkManager.singleton.StartHost();
            //开始发送广播
                 StartAsServer();
  }

3.同步Client Player

using HoloToolkit.Examples.SharingWithUNET;
using UnityEngine;
using UnityEngine.Networking;

//数据同步频率(秒)
[NetworkSettings(sendInterval = 0.1f)]
public class ClientManager : NetworkBehaviour
 {
    public Transform playerHeadPos;
    Transform cameraTransform;

    [SyncVar] private Vector3 headLocalPosition;

    [SyncVar] private Quaternion headLocalRotation;

    [Command]
    public void CmdTransform(Vector3 postion, Quaternion rotation)
    {
        if (!isLocalPlayer)
        {
            headLocalPosition = postion;
            headLocalRotation = rotation;
        }
    }
    void Start () {
        transform.SetParent(SharedCollection.Instance.gameObject.transform);
        cameraTransform= Camera.main.transform;
        playerHeadPos = transform.Find("Head");
        if (isLocalPlayer)
        {
            GlobleData.Instance.LocalMessageManager = transform.GetComponent<MessageManager>();
        }
    }
	
	void Update () {
        //如果Client是远端控制的,就把远端Clientr的位置信息同步过来
        if (!isLocalPlayer) 
        {
            //同步位置和旋转
            playerHeadPos.localPosition = Vector3.Lerp(playerHeadPos.localPosition, headLocalPosition, 0.1f);
            playerHeadPos.localRotation = Quaternion.Lerp(playerHeadPos.localRotation,headLocalRotation,0.1f);
        }
        //如果Client是本地控制的,不需要同步
        if (isLocalPlayer)
        {
            playerHeadPos.position = cameraTransform.position;
            playerHeadPos.rotation = cameraTransform.rotation;

            headLocalPosition = playerHeadPos.localPosition;
            headLocalRotation = playerHeadPos.localRotation;
            //向其他客户端同步Camera.main坐标信息
            CmdTransform(headLocalPosition, headLocalRotation); 
        }
    }
}

4.同步位置及命令

using HoloToolkit.Unity.InputModule;
using UnityEngine;
using UnityEngine.Networking;

public class MessageManager : NetworkBehaviour
{

    [SyncVar(hook = "MessageChanged")]
    public string MessageName;

    [Command]
    public void CmdMessageChanged(string message)
    {
        MessageName = message;
    }
    private void MessageChanged(string message)
    {
        //具体消息类型自己定义
        if (message.Contains("Order"))
        {
            //同步命令到其他客户端(缩放、旋转、播放动画...)
            string[] ordermsg = message.Split('|');
            string order = ordermsg[1];
            Invoke(order,0);
        }
        else if (message.Contains("HandDragPosition"))
        {
            //同步物体拖拽后的位置
            SetPosition(message);
        }
        else {
            print(message+"--未能解析消息!!!");
        }
    }
    private void SetPosition(string v)
    {

        Vector3 position = new Vector3();
        string[] pos = v.Split('|');
        string name = pos[1];

        position.x = float.Parse(pos[2]);
        position.y = float.Parse(pos[3]); ;
        position.z = float.Parse(pos[4]);

        HandDraggable drag;
        if (GlobleData.Instance.handDraggableDic.TryGetValue(name, out drag))
        {
            drag.HostTransformlocalPosition = position;
            drag.transform.localPosition = position;
        }
    }
    private void CreatSphere() {
        GameManager.Instance.CreatSphere();
    }

}
using System.Collections;
using System.Collections.Generic;
using HoloToolkit.Unity.InputModule;
using UnityEngine;

public class GlobleData : MonoBehaviour {

    public static GlobleData Instance;
    public MessageManager LocalMessageManager;

    public Dictionary<string,HandDraggable> handDraggableDic = new Dictionary<string, HandDraggable>();


    private void Awake()
    {
        Instance = this;

    }
 
}

using HoloToolkit.Examples.SharingWithUNET;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour {

    public static GameManager Instance;
    public GameObject TestSphere;
    //所有同步的物体需要放到SharedCollection下面,
    //同步其相对于SharedCollection坐标
    private Transform SharedCollectionTransform;
    int TestSphereNum;
    private void Awake()
    {
        Instance = this;
        SharedCollectionTransform = SharedCollection.Instance.gameObject.transform;

    }
    public void CmdCreatSphere(){
        GlobleData.Instance.LocalMessageManager.CmdMessageChanged("Order|CreatSphere");
    }
    public void CreatSphere() {
        Vector3 pos = Camera.main.transform.position + Camera.main.transform.forward*2;
        GameObject go= Instantiate(TestSphere, SharedCollectionTransform) as GameObject;
        TestSphereNum++;
        go.name = "TestSphere:" + TestSphereNum;
        go.transform.position = pos;
        go.transform.LookAt(Camera.main.transform);
    }
}

本节的效果动图



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

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

获取源码请在群资料中下载( Hololens Unet Share 001)

Hololens MR 技术交流群 211031265

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论
Hololens是由微软开发的一款增强现实(AR)头戴式设备。它通过内置的传感器、摄像头和扬声器等硬件,使用户能够在现实世界中看到虚拟世界的元素,实现真实与虚拟的交互。 Hololens的网络通信模块是它连接互联网的关键部分之一。Hololens可以通过Wi-Fi或蓝牙与其他设备进行通信,从而实现数据的传输和共享。 首先,Hololens可以通过Wi-Fi连接到互联网。用户可以在Hololens使用浏览器访问网页、使用社交媒体应用,或者下载和安装其他的AR应用程序等等。通过互联网连接,用户能够获取各种信息、资源和数据,实现更丰富的AR体验。 其次,Hololens还可以通过蓝牙与其他设备进行通信。这种方式可以实现与其他周围设备的无线连接,比如与智能手机、平板电脑、电脑或其他Hololens设备之间的数据传输和共享。例如,用户可以使用Hololens与其他设备配对,将Hololens上的图像、视频或音频内容共享到其他设备上。 此外,Hololens还支持局域网通信。用户可以将多个Hololens设备连接到同一个局域网内,从而实现设备之间的协作和互动。这种方式可以在团队合作、培训或教育等领域中发挥重要作用,让多个用户在现实世界中共享虚拟信息,并进行协同工作。 综上所述,Hololens的网络通信功能非常重要,它可以通过Wi-Fi连接互联网,通过蓝牙与其他设备进行数据传输和共享,同时还支持局域网通信。这些功能使Hololens能够获得更多资源和数据,扩展其应用领域,并与其他设备进行协作,提高用户的增强现实体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山谷大叔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值