Unity之NetworkView聊天室功能

  • NetworkView是Unity封裝的一套快速實現多人聯機遊戲的功能。以此爲基礎,我們可以開發各種類型的多人遊戲,可以開發過關遊戲的雙人聯機,也可以開發類似於CS的射擊遊戲,以房間爲單位。
  • 屬性
    1.isMine : Network View 是否是由本機創建的。
    2.observed:指定被觀察及同步的組件或者腳本。
    3.stateSynchronization:Network View的類型。OFF爲沒有數據將被同步,ReliableDeltaCompressed
     爲當前數據發生變化時才發送,Unreliable爲強制發送數據。
    4.viewID:NetworkViewID類型的ID。
  • 函數
    1.RPC(Remote Procedure Call,遠程過程調用)。在Network系統中可以理解爲向其他機器發送消息,如果
      有同名函數將被調用。
    2.networkView.RPC(string funName,RPCMode mode,params object[] args);參數funName爲函數
     名,參數mode指定發送的範圍,可選範圍包括全部連接的機器包括本機,例如,All是發送給所有機器,
     Server是發送給服務器。args是傳遞的參數,可傳可不傳,支持類型包括int,float, string,   
     NetworkPlayer,NetworkViewID,Vector3,Quaternion,不支持List集合。
    3.只要有Network View,那麼任何遊戲對象上的腳本的函數體前用[RPC]標註,就可以通過RPC來通知調
     用,但是函數名必須是唯一的,否則其中只有一個會被調用。
  • 聊天室:要想達到信息共享,在有客戶端加入時要清除所有用戶(包括客服端與服務器)之前的數據,並在客戶端與服務器端都要重新加載(使用Unity自帶函數)。(比如需要記錄每個進入聊天室人的姓名,當某個人退出時,刪除他的名字,某個人進來時,記錄他的名字,並將之前的已經進入的人的名字發送給這個人。這一系列操作只需通過服務器來實現,當客戶端連接時,namesInfoDictionary添加信息併發送給所有客戶端,客戶端斷開時,移除信息併發送給所有客戶端。)

下面是製作過程:

本文做的只是一個簡單的Demo,用來參考。。。一個簡單的場景,場景裏全部都是UI,demo裏只有一個腳本名爲mychat,沒有其他了。具體如下:

新建場景,新建一些UI並命名如下(這些名字都可以在代碼裏找到,關鍵是代碼)

然後在Canvas上綁定自己寫的腳本mychat和network view組件,如下

 

重點是腳本,mychat的全部腳本如下:

using UnityEngine;
using UnityEngine.UI;
using Button = UnityEngine.UI.Button;
using System.Collections.Generic;
public class MyChat : MonoBehaviour
{
    public Text showtestplayer;

    private Text peopleCount;
    private Text peopleNames;
    private Text chatText;
    private InputField inputField;
    private Button senon;
    private InputField myNameField;
    private Button createServerButton;
    private Text createServeText;
    private Button connectServerButton;
    private Text connectServerText;
    private Text warn;
    private string ip = "192.168.239.1";
    private int port = 9001;
    private bool hasConnectServer;
    private bool hasCreateServer;
    private string myName;
    private Dictionary<string ,string> namesInfoDictionary=new Dictionary<string, string>();
   

   // private Dictionary namesInfoDictionary = new Dictionary();
    private NetworkView networkView;
    private string namesStr;
    void Start()
    {
        peopleCount = transform.Find("bg/count").GetComponent<Text>();
        peopleNames = transform.Find("bg/name").GetComponent<Text>();
        chatText = transform.Find("bg/Image/Scroll View/Viewport/Content/Text").GetComponent<Text>();
        inputField = transform.Find("bg/InputField").GetComponent<InputField>();
        senon = transform.Find("bg/sendBtn").GetComponent<Button>();
        myNameField = transform.Find("myname").GetComponent<InputField>();
        createServerButton = transform.Find("createBtn").GetComponent<Button>();
        createServeText = createServerButton.transform.Find("Text").GetComponent<Text>();
        connectServerButton = transform.Find("connectBtn").GetComponent<Button>();
        connectServerText = connectServerButton.transform.Find("Text").GetComponent<Text>();
        warn = transform.Find("warn").GetComponent<Text>();
        peopleCount.text = "0";
        peopleNames.text = "";
        chatText.text = "";
        createServeText.text = "CreateServer";
        connectServerText.text = "ConnectServer";
        warn.text = "請先創建自己的暱稱,根據自己需要創建/連接服務器。";
        networkView = transform.GetComponent<NetworkView>();
        senon.onClick.AddListener(delegate
        {
            networkView.RPC("SendMsg", RPCMode.All, myName + ":" + inputField.text);
        });

        createServerButton.onClick.AddListener(delegate
        {
            if (!hasCreateServer)
            {
                if (myNameField.text != null)
                {
                    NetworkConnectionError error = Network.InitializeServer(20, port, false);
                    if (error == NetworkConnectionError.NoError)
                    {

                        myName = myNameField.text;
                        hasCreateServer = true;
                        myNameField.text = "";
                        createServeText.text = "DestroyServer";
                        warn.text = "";
                        namesInfoDictionary.Add(Network.player.ToString(), myName);
                   

                        StoreName(namesInfoDictionary);
                        networkView.RPC("GetNames", RPCMode.All, namesStr);
                        networkView.RPC("SendMsg", RPCMode.All, myName + "創建了聊天室");
                    }
                }
                else
                {
                    warn.text = "請創建自己的名字";
                }
            }
            else
            {
                Network.Disconnect();
                hasCreateServer = false;
                createServeText.text = "CreateServer";
            }
        });
        connectServerButton.onClick.AddListener(delegate
        {
            if (!hasConnectServer)
            {
                if (myNameField.text != null)
                {
                    NetworkConnectionError error = Network.Connect(ip, port);
                    if (error == NetworkConnectionError.NoError)
                    {
                        myName = myNameField.text;
                        hasConnectServer = true;
                        myNameField.text = "";
                        connectServerText.text = "DisConnect";
                        warn.text = "";
                    }
                }
                else
                {
                    warn.text = "請創建自己的名字";
                }
            }
            else
            {
                Network.Disconnect();
                hasConnectServer = false;
                connectServerText.text = "ConnectServer";
            }
        });
    }
//---------------記錄name列表,因爲RPC不可以傳入List集合,所以要把信息轉爲字符串------------
    private void StoreName(Dictionary<string ,string> namesDictionary)
    {
        namesStr = "";
        foreach (var VARIABLE in namesDictionary)
        {
            namesStr += VARIABLE.Value + ";";
        }
    }
//-------------------------------------聊天,發送信息---------------------------------------
    [RPC]
    private void SendMsg(string info)
    {
        if (info != "")
        {
            chatText.text += info + "\n";
            inputField.text = "";
        }
    }
//----------------------客戶端調用,通知服務器,更改namesInfoDictionary---------------------
    void OnConnectedToServer()
    {
        networkView.RPC("PlayerJoin", RPCMode.Server, myName);
        networkView.RPC("SendMsg", RPCMode.All, myName + "進入了聊天室");
    }
//--------------------服務器調用,更改namesInfoDictionary,並共享name列表------------------
    [RPC]
    private void PlayerJoin(string name, NetworkMessageInfo info)
    {
        namesInfoDictionary.Add(info.sender.ToString(), name);

        StoreName(namesInfoDictionary);
        networkView.RPC("GetNames", RPCMode.All, namesStr);
    }
//-------------------------------客戶端斷開連接,服務器調用----------------------------------
    void OnPlayerDisconnected(NetworkPlayer player)
    {

        networkView.RPC("SendMsg", RPCMode.All, namesInfoDictionary[player.ToString()] + "離開了聊天室");
        PlayerRemove(player.ToString());
    }
//--------------不必使用RPC,因爲更新namesInfoDictionary只需在服務器端進行。----------------
    private void PlayerRemove(string nameID)
    {
        if (namesInfoDictionary.ContainsKey(nameID))
        {
            namesInfoDictionary.Remove(nameID);
        }
        StoreName(namesInfoDictionary);
        networkView.RPC("GetNames", RPCMode.All, namesStr);
    }
//---------------------------客戶端與服務器更新名字列表,參數不能爲List-------------------------
    [RPC]
    private void GetNames(string names)
    {
        namesStr = names;
        peopleNames.text = "";
        string[] str = namesStr.Split(';');
        foreach (var VARIABLE in str)
        {
            if (VARIABLE != "")
                peopleNames.text += VARIABLE + "\n";
        }
        peopleCount.text = (str.Length - 1).ToString();
    }
}

這樣就可以了。

打包開始測試:

打開exe後進入,看到如下畫面:此處我用箭頭標註了一下每個UI的作用。

之後填寫上用戶名,然後點擊場景server進行創建服務器。

再啓動一個exe,輸入用戶名然後點擊連接服務器,之後就輸入內容點擊button發送聊天消息了。如下:

 

本文參考網上一篇文章進行了整理,並非原創,找不到原文鏈接了,如有用到可以參考研究。

發佈了187 篇原創文章 · 獲贊 143 · 訪問量 78萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章