1. 程式人生 > >unity VR Unet 多人互聯的實現 以及unet元件的的坑

unity VR Unet 多人互聯的實現 以及unet元件的的坑

文筆不好,想要看懂需要有 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="https://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]函式一定要注意。我有很多次出錯都是因為這個方法。
如果你遇到類似的困難,一定要多看幾遍,文字表述能力較差,希望大家可以理解,有問題也可以和我交流啦。