众所周知,在游戏中,我们经常会简单带聊天系统。一般,我们常见的有公会聊天,也就是大家熟知的QQ群聊,还有就是私聊,相信大家都懂得。好了, 废话不多扯了,我们开工。
首先,我们来写服务器端的。
老规矩,我们先搭建基本的UI。我们这里仍然使用NGUI。服务器端,我们主要负责显示客户端接入情况和收集全部消息,然后同步给每个客户端。
首先,我们创建一个Sprite,重命名为BackGround,然后为其选择图集和精灵,将其颜色调整为黑色,大小为整个UIRoot。然后,我们创建一个Label,重命名为Title,这个需要什么选择一个支持中文在字体,我们可以从外部导入,不再赘叙。然后,我们输入“服务器端”,调整大小到页面顶部。然后,选中UIRoot,创建一个Sprite,命名为CreateServer,选择图集和精灵,修改颜色和尺寸。它是将用来管理我们创建服务器的。调整大小。说明下,我们所有的调整大小建议使用Anchors 来做,这样UI的尺寸比例不会再我们分辨率发生变化时改变,影响美观。然后,在CreateServer下创建一个Label用来显示“创建服务器”,一个Button,用来点击确认。
第二步,我需要创建一个Label,用来显示信息。首先,我们隐藏我们刚刚创建的CreateServer,然后创建一个Sprite,重命名为ShowInfo,调整大小和颜色。然后再其上,创建一个Label ,和一个Button。Label ,Attach一个BoxColider,然后添加TextList组件。好了,我们的服务器端的UI基本界面搭建完成了,下面开始编写脚本。
首先,我们创建一个脚本,用来管理我们的Ip地址,端口号和最大连接数。脚本如下:
using UnityEngine; using System.Collections; public class Global : MonoBehaviour { public static string ipAddress = "127.0.0.1"; //ip地址 public static int port = 41254; //端口号 public static int connectCount = 10; //最大连接数 }
Global
然后,我们保存,回到Unity中,在创建一个脚本,命名为ServerUIManager ,让后,将其挂在UIRoot上,脚本,我们用来处理服务器端的事物。包括,管理UI,点击事件等。脚本如下:
using UnityEngine; using System.Collections; public class ServerUIManager : MonoBehaviour { public GameObject createServer; //创建服务器的管理对象 public GameObject showInfo; //显示客户端信息的管理对象 private UITextList clientInfo; //用来显示客服端信息的Label private bool isCreateServer = false; //能否创建服务器 private string message = ""; //信息 void Start() { clientInfo = showInfo.transform.FindChild("ClientInfo").GetComponent<UITextList>(); createServer.SetActive(true); //显示 showInfo.SetActive(false); //隐藏 } void Update() { if (Network.peerType == NetworkPeerType.Disconnected) { //创建服务器 isCreateServer = true; } else if (Network.peerType == NetworkPeerType.Server) { //服务 isCreateServer = false; OnServer(); } } //当点击了创建服务器按钮时执行, public void OnCreateServerButtonClick() { if (isCreateServer) { //可以创建,创建服务器 NetworkConnectionError error = Network.InitializeServer(Global.connectCount, Global.port, false); if (error == NetworkConnectionError.NoError) isCreateServer = false; //创建成功 else Debug.Log("创建失败" + error); } } //当服务器,初始化完成 void OnServerInitialized() { Debug.Log("Server initialized and ready"); createServer.SetActive(false); //显示 showInfo.SetActive(true); //隐藏 clientInfo.Clear(); //清空下textList } public void OnCloseServerButtonClick() { createServer.SetActive(true); //显示 showInfo.SetActive(false); //隐藏 Network.Disconnect(); //断开连接 isCreateServer = true; //重置 } //服务脚本,用来获取客户端接入信息,可以收取全部客户端发的信息 void OnServer() { int length = Network.connections.Length; //获得链接的客户端数 //遍历增加信息 for (int i = 0; i < length; i++) { clientInfo.Add("客户端:" + i ); clientInfo.Add("Ip:" + Network.connections[i].ipAddress ); clientInfo.Add("端口:" + Network.connections[i].port + "\r\n"); clientInfo.Add(message); } } [RPC] void ReciveMessage(string msg, NetworkMessageInfo info) { //刚从网络接收的数据的相关信息,会被保存到NetworkMessageInfo这个结构中 message = "发送端" + info.sender + "消息: " + msg + "\n" + info.timestamp + "\n"; //+"时间"+info.timestamp +"网络视图"+info.networkView } }
ServerUIManager
好了,我们保存脚本,回到Unity中,选中UIRoot为其添加NetWorkView组件,然后为其拖脚本引用, 可以测试下,看有没有问题 。没有问题的话,我们就可以打包了,选择File-->Build Setting ,选择PC,...,点击PlayerSettings ,在Resolution and Presentation 选项栏中勾选上 Run In Background ,表示可以后台运行,然后打包。打包完成,我们的服务器端就完成了,然后我们编写客户端。为了以后修改方便,我们重新创建一个场景。用来编写客户端。
类似,我们先搭建基本的UI界面,在这个界面中,我们需要输入Ip地址,然后点击连接,跳转到聊天页面。在聊天页面,我们有一个面板用来显示我们的聊天信息,它需要加上UITextList组件。还需要一个Button按钮,用来发送信息。具体的跟服务器端类型,我就不赘叙了。我这边展示下我的Hierarchy面板,给大家一个参考。
好了,我们开始编写客户端脚本,我们创建一个脚本,命名为ClientUIManager ,将其挂在UIRoot上,打开脚本,编辑。在这个脚本中,我们需要获取用户输入的IP,然后连接到服务器,然后有个公共方法,用来接收用户输入的信息并且发送。然后,也是最重要的,我们有一个RPC方法,用来同步我们的信息。代码如下:
using UnityEngine; using System.Collections; public class ClientUIManager : MonoBehaviour { public GameObject connectToServer; //连接到服务器管理对象 public GameObject showMessage; //消息管理对象 private UILabel ipLabel; //用户输入的Ip private UITextList messageList; //用来展示信息 private UILabel messageLabel; //用来获取用户输入的信息 private string message = ""; //信息 private bool canConnect = false; //能否连接 private bool canSendMessage = false; //能否发送 private NetworkView nv; //NetworkView组件引用 void Start() { //获得各个引用 ipLabel = connectToServer.transform.FindChild("IpInput/Label").GetComponent<UILabel>(); messageList = showMessage.transform.FindChild("Message").GetComponent<UITextList>(); messageLabel = showMessage.transform.FindChild("MessageInput/Label").GetComponent<UILabel>(); nv = GetComponent<NetworkView>(); connectToServer.SetActive(true); showMessage.SetActive(false); } void Update() { //没有连接时,连接 if (Network.peerType == NetworkPeerType.Disconnected) { canConnect = true; } } //用户点击了连接按钮 public void OnConnectToServerButtonClick() { //检测输入是否为空,并且利用连接 if (ipLabel.text != "" && canConnect) { Global.ipAddress = ipLabel.text; //连接到对应的服务器端 NetworkConnectionError error = Network.Connect(Global.ipAddress, Global.port); if (error == NetworkConnectionError.NoError) canConnect = false; else Debug.Log("连接出错" + error); } } //连接到了服务器 void OnConnectedToServer() { Debug.Log("Connected to server"); canConnect = false; canSendMessage = true; connectToServer.SetActive(false); showMessage.SetActive(true); messageList.Clear(); //清空消息列表 } //用户点击了发送,或者按下Enter键时调用 public void OnSendMessageButtonClick() { if (canSendMessage) { message = messageLabel.text; //获得用户输入的文本 //使用RPC来同步信息 nv.RPC("ReciveMessage", RPCMode.AllBuffered,message); } } [RPC] void ReciveMessage(string msg, NetworkMessageInfo info) { //刚从网络接收的数据的相关信息,会被保存到NetworkMessageInfo这个结构中 //+"时间"+info.timestam00p +"网络视图"+info.networkView message = "发送端" + info.sender + "消息: " + msg + "\n" + info.timestamp +"\n"; messageList.Add(message); } }
ClientUIManager
好了,我们同样的需要为UIRoot添加NetWorkView组件,并为其拖脚本引用。OK后,我们可以先运行我们之前的打包的Server.exe程序,然后创建服务器,再在UnityEditor中运行我们的Client场景,点击连接,看是否OK。OK后,我们打包这个场景,打包跟刚才一样。
现在,我们来测试下,我们的聊天系统。
首先,我们需要打开服务端程序,点击创建服务器,然后打开几个客户端程序,输入本地Ip后,连接到本地,试着在每个客户端中发送一条消息。如下:
客户端1:
客户端2:
OK,我们的简单的聊天系统就实现了。
总结,首先,在这个聊天系统中,我们使用了NetWorkView组件,和RPC远程过程调用,这是Unity封装好的网络组件,很简单,但是效率很低,所以在Unity5.2版本以后,就弃用了这个。当然,关于聊天等更网络相关的,我们最后自己使用Socket去封装一遍。一来,自己封装的更能满足当前项目需求,其次有很大的灵活性,我们可以随意更改和删除我们不需要的功能,这样更加节省资源,更加高效。但是,之前有个大神给我讲了一下Socket,我们还是一头雾水。有了解的小伙伴,我们一起交流交流啊。哎,无论何时都要努力啊。毕竟活到老,学到老。在这个圈子,三天不学习,就落后了。加油!!!