unity VR Unet 多人互联的实现 以及unet组件的的坑

来源:互联网 发布:数据库物理设计阶段 编辑:程序博客网 时间:2024/06/03 15:36

文笔不好,想要看懂需要有 htc 开发基础 以及unet基础。


我们的程序VR 程序 需要 多人互联的功能,所谓需要什么我就去做什么原则,钻研了一个星期 终于算是把所需要的功能给实现了。(因为VR游戏不能像传统局域网游戏一样可以双开测试,所以每次测试都要把安装包发到另外一台电脑来测试,很是麻烦。而且因为是网络游戏,很容易出现host端正常运行,而服务器端出错的问题。所以我发了50次才实现了我们的需求。。心塞塞)

小技巧:开始测试时可以把发布设置中的支持VR关掉,使用屏幕控制方式来测试,这样会省很多时间,但是要是测试手柄功能的话,就没有办法啦。只能两台电脑测试。。或者你也可以自己写测试来测试手柄功能。

如果 你不太懂服务器 就像我一样,而且团队中没有专业的后台,但是你依然想做一个多人互联的VR 游戏,或许可以帮给你一个方向。

首先这个文章使用的网络组件是unity 自己的unet  说实话我觉得坑挺多的,用的比较多的photon也可以实现,但是这篇文章是针对unet的啦。

下载LRX.SteamVR.Network.Essentials工具包 这个在unity官方商店卖20刀,挺贵的,但是总有办法搞得到嘛。如果没有unet基础的我还是建议你先去看看unet的demo.这样学习这快一点。

demo研究透彻后,就可以根据自己的需求来改啦,他上面的手柄事件系统是自己写的,现在做VR程序的话都会用官方出的工具包吧,这里注意一定要在

  void GetLeftControlEvent()    {        ///left menu        leftcontrol = vrCameraRigInstance.transform.FindChild("Controller (left)");        //must can find         m_LeftControlEvent = leftcontrol.GetComponent<VRTK_ControllerEvents>();        if (m_LeftControlEvent == null)        {            Debug.LogError("can not find VRTK_ControllerEvents");        }        m_LeftControlEvent.ApplicationMenuPressed += new ControllerInteractionEventHandler(OnMenuClickDown);    }

vrCameraRigInstance下引用,这是必须的,这样就可以不用他的啦。
其他都需要根据自己的需求来自己实现了,下面就提一些unet遇到的一些坑。
因为unet现在的资料还是很少,所以有很多很坑,下面这些都是我自己踩过的坑,真的很坑人。
一般游戏中 主角一般都是一个 也就是你加入网络控制器生成的那个物体,只有这个物体的islocalplayer 属性是真,而你要执行[command]的脚本的属性的<pre name="code" class="csharp">islocalplayer 必须为真.一般传统局域网游戏中这没有什么问题,但是在VR游戏中,你控制的是3个物体,一个头盔 两个手柄。手柄上的脚本如何执行<pre name="code" class="csharp">[command]呢。
<pre name="code" class="csharp">[Command]    void CmdSpawnHands(NetworkInstanceId playerId)    {        // instantiate controllers        // tell the server, to spawn two new networked controller model prefabs on all clients        // give the local player authority over the newly created controller models        leftHand = Instantiate(leftHandPrefab);        rightHand = Instantiate(rightHandPrefab);        var leftVRHand = leftHand.GetComponent<NetworkVRHands>();        var rightVRHand = rightHand.GetComponent<NetworkVRHands>();        leftVRHand.side = HandSide.Left;        rightVRHand.side = HandSide.Right;        leftVRHand.ownerId = playerId;        rightVRHand.ownerId = playerId;        NetworkServer.SpawnWithClientAuthority(leftHand, base.connectionToClient);        NetworkServer.SpawnWithClientAuthority(rightHand, base.connectionToClient);    }

就需要用到这个
<pre name="code" class="csharp"><pre name="code" class="csharp">NetworkServer.SpawnWithClientAuthority(leftHand, base.connectionToClient);函数,分发权利,这样lefthand,righthand才能执行<pre name="code" class="csharp">[command]的命令。其次,这里给权利的两只手 并不是手柄,可以是手柄的模型什么的,不能把手柄的prefab放到这里,因为使用官方工具包的话,手柄是强制作为头盔
的子物体的。而且因为这个函数生成的物体必须的<img src="http://img.blog.csdn.net/20161104152557589?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />设置为localplayerauthority。但是设置<pre name="code" class="csharp">localplayerauthority这个属性的物体必须是根节点,手柄不会作为根结点,这双重原因导致了必须用生成出来的手(模型)来绑定控制器。
<pre name="code" class="csharp">public static void AttachAtGrip(Transform holder, Transform objectToAttach, string gripName = "Grip")    {        var grip = objectToAttach.FindChild(gripName);        objectToAttach.position = holder.position;        objectToAttach.rotation = holder.rotation;        objectToAttach.parent = holder;        objectToAttach.localPosition = grip.transform.localPosition;        objectToAttach.localRotation = grip.localRotation;    }
这个代码是用来将生成出来的物体 和手柄控制器绑定的。很简单的绑定代码,

再说这个<pre name="code" class="csharp">[Command]要求真的是很苛刻。不光上述所说的条件,使用这个标签的方法一定要以cmd开头不说,参数还必须是数据类型的,不能传递组件类型的,什么game object神马的都不可以
这个真的坑了我很长时间,这个标签的意思就是在调用到这个函数时,是服务器来执行里面的方法。所以,不要在这个函数内找其他的物体,找不到的!这个可能你会看不明白
,但我也不清楚要怎么描述,一般也遇不到。既然是服务器执行,想要执行networkserver内的方法一定要在这个标签函数内。否则是不会执行的。
<pre name="code" class="csharp">[Command]函数一定要注意。我有很多次出错都是因为这个方法。
如果你遇到类似的困难,一定要多看几遍,文字表述能力较差,希望大家可以理解,有问题也可以和我交流啦。

1 0
原创粉丝点击