天天看點

【UNet】初識Unity Network,制作一個簡單的網絡聊天室1.建立Offline場景2.建立Online場景3.制作玩家Prefab4.設定NetworkManager5.運作,測試

UNet官方文檔:https://docs.unity3d.com/Manual/UNet.html

1.建立Offline場景

建立一個新場景,命名為Offline,在場景中建立一個空GameObject,添加NetworkManager、NetworkManagerHUD兩個元件

Network Manager:

網絡管理器功能包括:

    • Game state management(遊戲狀态管理,NetworkManager中有大量Hook,例如OnServerConnect服務端啟動時自動調用,OnClientConnect用戶端連接配接時自動調用)
    • Spawning management(同步産生遊戲對象,例如有玩家進入遊戲,就需要Server端通知所有已連接配接Clients同步建立出這個玩家)
    • Scene management(場景管理,開始多人遊戲時進入聯網場景(Play Scene),斷開連接配接時切換到離線場景(Offline Scene))
    • Debugging information(調試資訊)
    • Matchmaking(這是Unity Cloud提供的服務,用于遊戲房間的建立、比對、加入、銷毀等)
    • Customization(NetworkManager雖然封裝了好了功能,但通常需要自己寫NetworkManager的擴充類以滿足自己遊戲的需求,例如Unity還有一個NetworkLobbyManager,也是繼承NetworkManager,但是擴充出一個遊戲大廳的功能)

Network Manager HUD:

這是用來配合NetworkManager的元件,隻是一個功能展示UI,控制NetworkManager的基本功能。如StartHost()啟動為主機,StartClient()啟動為用戶端等,一般隻有測試的時候才用這個元件

2.建立Online場景

1.搭建UI

建立場景,命名為Game,建立Scroll View作為聊天資訊顯示區域,建立InputField作為消息輸入框,建立一個發送Button。

2.制作消息框

1.建立一個Panel,添加VerticalLayoutGroup、ContentSizeFitter元件,并做一下設定,用于根據文字多少消息框自适應大小

【UNet】初識Unity Network,制作一個簡單的網絡聊天室1.建立Offline場景2.建立Online場景3.制作玩家Prefab4.設定NetworkManager5.運作,測試

2.在Panel下建立一個Text,用于顯示使用者發送的文字消息

3.儲存成Prefab,用于在代碼中動态建立消息框

3.制作玩家Prefab

1.建立空GameObject,添加NetworkIdentify元件,并勾選Local Player Authority,隻允許本地用戶端控制。NetworkIdentify是網絡物體必須要有的元件,用于網絡身份識别

2.建立腳本命名為Speaker,用于将用戶端輸入的消息發送給服務端,然後由服務端發給所有用戶端以實作消息同步.

代碼如下:

using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class Speaker : NetworkBehaviour
{
    public GameObject itemPrefab;
    private Transform content;
    private InputField inputBox;
    private Button sendButton;
    //[SyncVar(hook = "OnValueChanged")]
    [SyncVar]
    private int onlineNum = 0;
    void Start()
    {
        content = GameObject.Find("Canvas/Scroll View/Viewport/Content").transform;
        inputBox = GameObject.Find("Canvas/InputField").GetComponent<InputField>();
        sendButton = GameObject.Find("Canvas/SendButton").GetComponent<Button>();
        sendButton.onClick.AddListener(SendButtonCallback);
    }
    /// <summary>
    /// 顯示線上人數
    /// </summary>
    private void OnGUI()
    {
        if (!isLocalPlayer)
            return;
        GUI.Label(new Rect(new Vector2(10, 10), new Vector2(150, 50)),
            string.Format("線上人數:{0}", onlineNum));
    }
    /// <summary>
    /// 更新Serve端線上人數
    /// </summary>
    private void Update()
    {
        if(isServer)
            onlineNum = NetworkManager.singleton.numPlayers;
    }
    /// <summary>
    /// 發送按鈕響應事件
    /// 将使用者輸入消息發送給服務端
    /// </summary>
    void SendButtonCallback()
    {
        if (!isLocalPlayer)
            return;
        if (inputBox.text.Length > 0)
        {
            string str = string.Format("{0}:{1}{2}", Network.player.ipAddress, System.Environment.NewLine, inputBox.text);
            CmdSend(str);
            inputBox.text = string.Empty;
        }
    }
    /// <summary>
    /// 使用Command修飾的函數表示在用戶端調用,在服務端執行
    /// </summary>
    /// <param name="str"></param>
    [Command]
    void CmdSend(string str)
    {
        RpcShowMessage(str);
    }
    /// <summary>
    /// ClientRpc修飾的函數 表示由服務端調用,在所有用戶端執行
    /// </summary>
    /// <param name="str"></param>
    [ClientRpc]
    void RpcShowMessage(string str)
    {
        GameObject item = Instantiate(itemPrefab, content);
        item.GetComponentInChildren<Text>().text = str;
    }
}
           

代碼非常簡單,沒有寫發包收包卻實作了用戶端和服務端的消息同步,這就是UNet的強大之處,UNet的口号是讓網絡遊戲開發就像開發單機遊戲一樣,最重要的是UNet Server端與用戶端運作的是同樣的代碼,也就是說Server端有Unity所有的功能(實體引擎、網格導航等),這些資訊直接在Server端計算出來同步給Clients,而用其它網絡引擎就需要在Server端自己寫碰撞和導航系統。不過UNet也有很多不足,例如Server和Client執行的是同樣的代碼,一旦有用戶端被反編譯那麼Server端的邏輯也就暴露了。

代碼中有幾個UNet重要的關鍵字:

自動同步:

[SyncVar]或[SyncVar(hook="FuncName")]: 用于自動同步Server端變量,當Server端SyncVar修飾的變量發生改變時就會自動同步給所有Clients, 第二種寫法是當此變量改變時會自動調用FuncName函數,這種同步方法通常用于變化比較頻繁的變量。

手動同步:

[Command]:函數名必須以Cmd開頭,Command修飾的函數表示在用戶端調用,在服務端執行。如代碼中在用戶端調用CmdSend(string message), 把目前用戶端使用者輸入消息作為參數傳進去,該函數在用戶端調用時傳入了消息,然後此函數會在服務端執行,這樣服務端就得到了用戶端傳遞進來的消息。

[ClientRpc]:函數名必須以Rpc開頭,ClientRpc修飾的函數 表示由服務端調用,在所有用戶端執行。服務端執行了CmdSend()方法,而此方法又調用了RpcShowMessage(string str),把從用戶端傳來的消息又直接傳入了RpcShowMessage(), 而[ClientRpc]修飾的函數是服務端調用用戶端執行,服務端又将從用戶端收到的消息轉發給了所有用戶端,這樣就實作了消息的同步。

4.設定NetworkManager

如圖,把Offline和Game場景以及Speaker預制體拖入

【UNet】初識Unity Network,制作一個簡單的網絡聊天室1.建立Offline場景2.建立Online場景3.制作玩家Prefab4.設定NetworkManager5.運作,測試

5.運作,測試

想要使用Unity Cloud的線上遊戲房間比對系統需要在Unity開啟MultiPlayer服務

【UNet】初識Unity Network,制作一個簡單的網絡聊天室1.建立Offline場景2.建立Online場景3.制作玩家Prefab4.設定NetworkManager5.運作,測試

Build項目,然後運作兩個,一個啟動為Host,一個啟動為Client,啟動後NetworkManager會自動切換至Online場景:

測試圖:

【UNet】初識Unity Network,制作一個簡單的網絡聊天室1.建立Offline場景2.建立Online場景3.制作玩家Prefab4.設定NetworkManager5.運作,測試

繼續閱讀