Unity3D遊戲開發從零單排(七) - NetworkView的Demo

來源:互聯網
上載者:User

標籤:unity   遊戲開發   

提要

今天做了一個行動裝置的網路通訊demo,分兩個部分,一個是網路連接,一個是資料通訊。

        需要兩台Android裝置A,B。A作用戶端,B作服務端。

最終的效果是玩家控制裝置A中的方塊,B中的方塊也一起動,同時在A的加速度感應器的資訊在B中也即時更新。



網路連接

      首先兩台裝置要連網,且IP在同一個網段,比如串連在同一個路由上,或者通過筆記本發出wifi訊號,然後把裝置連在上面。

       在Unity3d中建立一個新工程,在情境中建立兩個空物體,一個Client,一個Server。

       在client建立一個指令碼client.cs

using UnityEngine;using System.Collections;public class client : MonoBehaviour {    private string IP = "10.66.208.191";    private string clientIp;    private string clientIpSplite;    private Vector3 acceleration;    public GameObject cube;    private bool cubeInitialed = false;    //Connet port     private int Port = 10000;    void Awake()    {        clientIp = Network.player.ipAddress;        string[] tmpArray = clientIp.Split(‘.‘);        clientIpSplite = tmpArray[0] + "." + tmpArray[1] + "." + tmpArray[2] + ".";    }        void OnGUI()    {        switch (Network.peerType)        {            case NetworkPeerType.Disconnected:                StartConnect();                break;            case NetworkPeerType.Server:                break;            case NetworkPeerType.Client:                OnConnect();                break;            case NetworkPeerType.Connecting:                break;        }    }    void StartConnect()    {        if (GUILayout.Button("Connect Server"))        {            NetworkConnectionError error = Network.Connect(IP, Port);            Debug.Log("connect status:" + error);               }    }    void OnConnect()    {        if(!cubeInitialed)        {            Network.Instantiate(cube, transform.position, transform.rotation, 0);            cubeInitialed = true;        }    }}


用戶端根據當前當前的狀態來執行相應的動作。StartConnect負責串連,用到了

static NetworkConnectionError Connect(string[] IPs, int remotePort)

第一個參數是Ip,第二個參數是連接埠。


串連上之後調用OnConnect函數初始化一個方塊。注意這個方塊是在用戶端初始化的,屬於這個用戶端,建立成功之後會在其他的一桶串連的裝置上都執行個體化一個cube出來,但是只有在這個client上NetworkView.isMine才為true。


接下來是服務端的代碼。

using UnityEngine;using System.Collections;public class server : MonoBehaviour {    private int serverPort;     public GUIText status;    void Awake()    {        serverPort = 10000;    }  //OnGUI方法,所有GUI的繪製都需要在這個方法中實現      void OnGUI()    {        //Network.peerType是端類型的狀態:          //即disconnected, connecting, server 或 client四種          switch (Network.peerType)        {            //禁止用戶端串連運行, 伺服器未初始化              case NetworkPeerType.Disconnected:                StartServer();                break;            //運行於伺服器端              case NetworkPeerType.Server:                OnServer();                break;            //運行於用戶端              case NetworkPeerType.Client:                break;            //正在嘗試串連到伺服器              case NetworkPeerType.Connecting:                break;        }        GUILayout.Label(Network.player.ipAddress);    }    void StartServer()    {        //當使用者點擊按鈕的時候為true          if (GUILayout.Button("建立伺服器"))        {            //初始化本機伺服器連接埠,第一個參數就是本機接收多少串連              NetworkConnectionError error = Network.InitializeServer(12, serverPort, false);            Debug.Log("錯誤記錄檔" + error);        }    }    void OnServer()    {        GUILayout.Label("服務端已經運行,等待用戶端串連");          int length = Network.connections.Length;        for(int i = 0; i < length; i++)        {            GUILayout.Label("用戶端" + i);            GUILayout.Label("用戶端ip" + Network.connections[i].ipAddress);            GUILayout.Label("用戶端連接埠" + Network.connections[i].port);          }    }    void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info){    // Always send transform (depending on reliability of the network view)     if (stream.isWriting)     {        Vector3 pos = transform.localPosition;         Quaternion rot = transform.localRotation;         stream.Serialize(ref pos);         stream.Serialize(ref rot);     }    // When receiving, buffer the information     else {        // Receive latest state information         Vector3 pos = Vector3.zero;         Quaternion rot = Quaternion.identity;         stream.Serialize(ref pos);         stream.Serialize(ref rot);    }}}


點擊螢幕上的建立伺服器之後就在裝置上建立了一個服務端,監聽對應的連接埠,當有其他裝置串連上來的時間,用戶端的資訊就會列印出來,可以支援多個裝置的串連。


還要建立一個cube的prefab,用於動態建立。



CubeController用於控制方塊的運動,NetWorkView用於資料通訊。


資料通訊

需要進行資料通訊的GameObject都要添加一個NetworkView 組件,資料通訊有兩種方式,狀態同步和RPC(遠端程序呼叫)。在CubeController.cs中,兩種方法都有用到。

using UnityEngine;using System.Collections;public class CubeController : MonoBehaviour {    private GUIText accelText;    void Start()    {        accelText = GameObject.FindGameObjectWithTag("AccelTip").GetComponent<GUIText>() as GUIText;        accelText.text = "";    }    void Update()    {        if(Network.isClient)        {            Vector3 acceleration = Input.acceleration;            accelText.text = "" + acceleration;            networkView.RPC("UpdateAcceleration", RPCMode.Others, acceleration);        }        Vector3 moveDir = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));        Vector3 cubescreenPos =  Camera.main.WorldToScreenPoint(transform.position);        if (Input.GetMouseButton(0))        {            moveDir = new Vector3(Input.mousePosition.x - cubescreenPos.x, Input.mousePosition.y - cubescreenPos.y, 0f).normalized;        }        Debug.Log("moveDir: " + moveDir);        float speed = 5;        transform.Translate(speed * moveDir * Time.deltaTime);    }    void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info)    {        if (stream.isWriting)        {            Vector3 pos = transform.position;            stream.Serialize(ref pos);        }        else        {            Vector3 receivedPosition = Vector3.zero;            stream.Serialize(ref receivedPosition);            transform.position = receivedPosition;        }    }     [RPC]    void UpdateAcceleration(Vector3 acceleration)    {        accelText.text = "" + acceleration;    }}

function OnSerializeNetworkView(stream : BitStream, info : NetworkMessageInfo) {}
這是在Network class中提供的一個func. 主要負責message sent / receive,他會同步被network view所關注的script中的對象,也就是當你寫了一個script內含OnSerializeNetworkView(){},並且丟到observed屬性中,則OnSerializeNetworkView()裡的code就會開始運作。基本上他透過BitStream物件收髮網路上的資訊,使用上不需要瞭解封包的問題,也不需要知道如何切割封包。在這的demo中,服務端只負責接收資訊,所以只執行else後面的代碼,用戶端發送資訊,執行if後面的代碼。

這裡cube的state synchronization選的是Unreliable,對應的通訊協議是UDP,特點是無串連,比較快。

RPC典型的應用情境就是聊天室,使用也非常簡單,首先定義一個rpc函數在(在上面加上[RPC]),然後通過NetWork.RPC來調用就可以了。這裡是把用戶端重力感應器的資料傳了出去,在介面上更新。


參考

unity3D的網路資料傳輸 & 角色控制 - http://ppb440219.blogspot.com/2011/12/unity3d.html

網路視圖 Network View - http://game.ceeger.com/Components/class-NetworkView.html

遠端程序呼叫的細節 RPC Details - http://game.ceeger.com/Components/net-RPCDetails.html

狀態同步的細節 State Synchronization Detailshttp://game.ceeger.com/Components/net-StateSynchronization.html

Unity Networking Tutorial - http://www.palladiumgames.net/tutorials/unity-networking-tutorial/




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.