- NetworkView是Unity封裝的一套快速實現多人聯機遊戲的功能。以此爲基礎,我們可以開發各種類型的多人遊戲,可以開發過關遊戲的雙人聯機,也可以開發類似於CS的射擊遊戲,以房間爲單位。
- 屬性
- 函數
- 聊天室:要想達到信息共享,在有客戶端加入時要清除所有用戶(包括客服端與服務器)之前的數據,並在客戶端與服務器端都要重新加載(使用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發送聊天消息了。如下:
本文參考網上一篇文章進行了整理,並非原創,找不到原文鏈接了,如有用到可以參考研究。