unity 網路 --NetWorking
阿新 • • 發佈:2019-01-08
unity 5以後底層封裝了一些network模組。比較有名的是unet 就是unityNetworkmanager,還是很強大的,用來做一些同步,聯機小遊戲還是很方便的,因為不需要我們自己再去搭建底層,只需掛載一些元件即可完成過同步。
研究unet的時候,意外發現另一套網路架構--networking。這個相比uent雖然需要我們自己去寫更多指令碼,但是相比之下,uent效能並不十分穩定,延遲也是比較高的。而networking更類似於我們自己對socket的封裝,但是這些底層結構unity已經幫我們搭建,我們可以直接呼叫。不多說,結合例子開始講解。
首先作為伺服器端,我們可以直接打包,或者在unity上直接 開啟伺服器,更加直觀不想之前只能做Windows視窗程式。
//協議類 資料結構
public class UserMsg : MessageBase
{
public string SenderIP;
public string message;
public string type;
}
public class NetworkingMgr { private static NetworkingMgr instance = null; public static NetworkingMgr Instance { get { if (instance == null) instance = new NetworkingMgr(); return instance; } } public bool connected=false; /// <summary> /// 使用者資訊分類 /// </summary> private const short userMsg = 64; public string Ip; //伺服器IP /// <summary> /// 獲取本機IP /// </summary> /// <returns></returns> private static string GetInternalIP() { IPHostEntry host; string localIP = "?"; host = Dns.GetHostEntry(Dns.GetHostName()); foreach (IPAddress ip in host.AddressList) { if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { localIP = ip.ToString(); break; } } return localIP; } #region 伺服器邏輯 //玩家連線個數 public int count = 0; private List<NetworkConnection> clients = new List<NetworkConnection>();//記錄客戶端 /// <summary> /// 啟動 /// </summary> /// <param name="ip"></param> /// <param name="port"></param> public void SeverStart(string ip ,int port) { if (!NetworkServer.active) { if (ip == "") { ip = GetInternalIP();//預設本機做伺服器 } if (port == 0) port = 4455; Ip = GetInternalIP (); connected = NetworkServer.Listen(ip, port); Debug.Log("伺服器啟動狀態:" + connected); if (connected) ServerRegisterHandler(); } else Debug.Log("伺服器已經開啟"); } /// <summary> /// 伺服器端註冊事件 /// </summary> private void ServerRegisterHandler() { NetworkServer.RegisterHandler(MsgType.Connect, OnServerConnected); NetworkServer.RegisterHandler(MsgType.Disconnect, OnServerDisconnected); NetworkServer.RegisterHandler(MsgType.Error, OnServerError); NetworkServer.RegisterHandler(userMsg, ServerGet);//接受訊息 } //伺服器接受到客戶端資訊 private void ServerGet(NetworkMessage netMsg) { UserMsg Msg = netMsg.ReadMessage<UserMsg>(); Debug.Log("收到客戶端資訊:" + Msg.message); ServerSendAll(Msg); //for (int i = 0; i < clients .Count ; i++) //{ // SeverSendToClient(Msg, netMsg); //} } //伺服器錯誤事件 private void OnServerError(NetworkMessage netMsg) { } //有客戶端斷開事件 private void OnServerDisconnected(NetworkMessage netMsg) { count--; clients.Remove(netMsg.conn); UserMsg msg = new UserMsg() { message = "掉線!", SenderIP = netMsg.conn.address, type = "OutLine", }; ServerSendAll(msg); } // 有客戶端登入時呼叫 private void OnServerConnected(NetworkMessage msg) { count++; clients.Add(msg.conn); Debug.Log("玩家登入:" + msg.conn .address); } //伺服器廣播 public void ServerSendAll(UserMsg um) { if (NetworkServer.active) { if (NetworkServer.SendToAll(userMsg, um)) { Debug.Log("Server send:" + um.message); } } } //傳送給指定客戶端 public void SeverSendToClient(UserMsg um, NetworkMessage netMes) { if (NetworkServer.active) { Debug.Log("向客戶端傳送資料:" + um.message + " ---- " + DateTime.Now); NetworkServer.SendToClient(netMes.conn .connectionId , userMsg, um); } } //停止伺服器 public void ShutdownServer() { if (NetworkServer.active) { ServerUnregisterHandler(); NetworkServer.DisconnectAll(); NetworkServer.Shutdown(); if (!NetworkServer.active) { Debug.Log("shut down server"); } } } //伺服器登出事件 private void ServerUnregisterHandler() { NetworkServer.UnregisterHandler(MsgType.Connect); NetworkServer.UnregisterHandler(MsgType.Disconnect); NetworkServer.UnregisterHandler(MsgType.Error); NetworkServer.UnregisterHandler(userMsg); } #endregion }
以上只是一個簡單是伺服器端,當然,如果你想要更視覺化,可以自己做些酷炫介面的。
然後是客戶端
public class NetworkingMgr { private static NetworkingMgr instance = null; public static NetworkingMgr Instance { get { if (instance == null) instance = new NetworkingMgr(); return instance; } } public bool connected=false; /// <summary> /// 使用者資訊分類 /// </summary> private const short userMsg = 64; public NetworkClient myClient;//本機客戶端 /// <summary> /// 做客戶端 連線伺服器 /// </summary> /// <param name="ip"></param> /// <param name="port"></param> public void Connected(string ip, int port,Action callback) { if (ip == "") { ip = GetInternalIP(); } if (port == 0) port = 4455; myClient = new NetworkClient(); myClient.Connect(ip, port); myClient.RegisterHandler(MsgType.Connect, (netMsg) => { Ip = GetInternalIP (); connected = myClient.isConnected; Debug.Log("連線成功!!!"); if (callback != null) callback.Invoke(); }); } //向伺服器傳送資訊 public void ClientSend(UserMsg um) { if (myClient.isConnected) { um.SenderIP = Ip; if (myClient.Send(userMsg, um)) { Debug.Log("傳送成功!!"); } } } // 客戶端註冊事件 public void ClientRegisterHandler() { connected = true; //myClient.RegisterHandler(MsgType.Connect, OnClientConnected); myClient.RegisterHandler(MsgType.Disconnect, OnClientDisconnected); myClient.RegisterHandler(MsgType.Error, OnClientError); //myClient.RegisterHandler(userMsg, ClientGet); } //客戶端接受到伺服器資訊 //private void ClientGet(NetworkMessage netMsg) //{ // UserMsg Msg = netMsg.ReadMessage<UserMsg>(); // Debug.Log("收到伺服器資訊:"+Msg.message); //} //客戶端錯誤事件 private void OnClientError(NetworkMessage netMsg) { } //客戶端沖服務器斷開事件 private void OnClientDisconnected(NetworkMessage netMsg) { } //客戶端連線到伺服器事件 //private void OnClientConnected(NetworkMessage netMsg) //{ // connected = myClient.isConnected; // Debug.Log("連線成功!!!"); //} // 停止客戶端 public void ShutdownClient() { if (myClient.isConnected) { ClientUnregisterHandler(); myClient.Disconnect(); //NetworkClient.Shutdown()使用後,無法再次連線。 //This should be done when a client is no longer going to be used. //myClient.Shutdown (); } } // 客戶端登出事件 private void ClientUnregisterHandler() { myClient.UnregisterHandler(MsgType.Connect); myClient.UnregisterHandler(MsgType.Disconnect); myClient.UnregisterHandler(MsgType.Error); myClient.UnregisterHandler(userMsg); }
這些方法介面都是unity封裝完成開放的,直接呼叫就行,啟動一個伺服器,一個客戶端,測試,通過!!
若有問題歡迎諮詢指正!!!.
demo下載地址:https://download.csdn.net/download/nt_xs_j/10502072