天天看點

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