Unity--使用Socket完成一个聊天Demo

=====================================VS2017 + Unity 2017.4.10 =====================================   

 

还是用上篇 https://blog.csdn.net/MikuLingSSS/article/details/82393122 的代码,进行了小范围修改

Client: 新加了这些

Server:新加了这些

while (true)
{
    try
    {
        int length = client.Receive(result);
        if (length == 0)
            break;
        DeleEvent.sendMessage -= SendMessage;
        DataAnalysis.AnalysisMessage(Encoding.UTF8.GetString(result, 0, length));
        DeleEvent.sendMessage(clientID + ":" + Encoding.UTF8.GetString(result, 0, length));
        DeleEvent.sendMessage += SendMessage;
    }
    catch (Exception ex)
    {
        break;
    }
}
client.Shutdown(SocketShutdown.Both);
DeleEvent.sendMessage -= SendMessage;
client.Close();
receive = null;

    按照上篇博客,把Client打包成DLL,方便Unity调用

      为了项目不会很杂乱,我们先新建几个文件夹,前面加个下划线是为了优先级会更高一些,

在场景中新建一个Canvas,里面只有一个Button作为发送信息按钮,和一个InputFiled作为输入信息,为了方便查看,记得将相机调成纯色渲染

     接下来,新建一个脚本,命名为SendMessage 这个作为服务器的连接初始化,和UGUI的相关事件

using UnityEngine;
using UnityEngine.UI;
using Client;  // -- 我们打包出来DLL的 namespace

public class SendMessage : MonoBehaviour {

    public InputField inputMessage;

    private void Awake()
    {
        ConnServer.Initial("127.0.0.1", 9002);
        ConnServer.Instance.Conn();
        Input.imeCompositionMode = IMECompositionMode.On;   // 设置为可以输入中文
    }


    // 这个脚本在Canvas上,另一个_OnGUI在相机上
    public void SendButton()
    {
        string message = inputMessage.text;
        if (string.IsNullOrEmpty(message))
            return;
        // 如果是我们发送的信息,那么在UI显示上应该和其他的有分别,但是我们的服务器只会发送一个Str,这里懒了一下,没有修改参数
        Camera.main.transform.GetComponent<_OnGUI>().MyClient = true;
        // 这个是我们自己发送的信息
        Camera.main.transform.GetComponent<_OnGUI>().ReceiveMesEvent("-1:"+inputMessage.text);
        ConnServer.Instance.SendMessage(message);  // 将信息发送给服务器
    }
}

     首先,初始化一些数据

private void Start()
{
    style = new GUIStyle();
    Recv = new List<MessageArrtibute>();
    Temp = new List<MessageArrtibute>();
    Header = LabelHeight;  // 头像与标签高度一致
    MessageArrtibute mes = new MessageArrtibute(-1, "Welcome To ...", 0, 0, true);
    Recv.Add(mes);
    style.normal.textColor = new Color(1, 0, 0, 1);
    ReceiveEvent.Instance.AddEvent(ReceiveMesEvent);
}

     聊天室,当然最先考虑的就是如何把服务器发送过来的信息显示在最新的地方,这里我们用OnGUI实现

思路是:首先生命一些变量作为生成UI的数据

public int Header;            // 头像 高*宽
public int LabelHeight = 30;  // OnGUI的高度
public int LabelWidth = 300;  // 宽度
public int HeightOffset = 20; // 两条数据间间隔
public int WidthOffset = 25;  // 信息中的头像与信息之间的间隔

public List<MessageArrtibute> Recv;  // 接收到的服务器数据

private List<MessageArrtibute> Temp; // 临时数据存放 声明两个是为了防止 
                                     // “集合已被修改,无法***”这个问题

private GUIStyle style;              // 我们自己发送的信息的样式

,新建一个列表用来保存服务器发送过来的数据,而列表中应该有


public class MessageArrtibute
{
    public int clientID;           // 是谁的信息
    public string message;         // 信息内容是什么
    public int header;             // 我们应该显示的头像高*宽是多少
    public int x;                  // 这条数据应该显示在屏幕的那个坐标
    public int y;
    public bool myClient = false;  // 是不是我们自己的信息

    public MessageArrtibute(int clientID, string message, int x, int y, bool myClient)
    {
        this.clientID = clientID;
        this.message = message;
        this.x = x;
        this.y = y;
        this.myClient = myClient;
    }
}

接收到服务器发送过来的数据时,首先判断列表中最后一条数据的坐标,如果他的坐标+LabelHeight > Screen.Height就说明当他生成之后会超过屏幕的边界,这时我们应该把列表中的所有数据全部往后面偏移LabelHeight个单位

    public bool MyClient = false;   // 
    public void ReceiveMesEvent(string mess)
    {
        int clientID = Convert.ToInt32(mess.Substring(0, mess.IndexOf(':'))); //获取到发送者ID
        string message = mess.Substring(mess.IndexOf(':') + 1);               //获取到发送的信息
        int index = Recv.Count - 1;
        if (Recv[index].y > Screen.height - LabelHeight)
        {
            for (int i = 0; i < Recv.Count - 1; i++)   // 不知道为什么,我这里写<=会出现UI重叠
            {
                Recv[i].y -= LabelHeight;
            }
            MessageArrtibute _mes = new MessageArrtibute(clientID, message, Recv[index].x, (Recv[index].y), MyClient);
            Recv.Add(_mes);
            MyClient = false;
            return;
        }
        MessageArrtibute mes = new MessageArrtibute(clientID, message, Recv[index].x, (Recv[index].y + LabelHeight), MyClient);
        Recv.Add(mes);
        MyClient = false;
    }

,之后将其加入到列表的最后

现在,在OnGUi里面我们就可以直接生成相应的Label了

    private void OnGUI()
    {
        Temp = Recv;
        for (int i = Temp.Count - 1; i >= 0; i--)
        {
            if (Recv[i].myClient)
            {
                GUI.Label(new Rect(Recv[i].x, Screen.height - Recv[i].y - LabelHeight, Header, Header), Temp[i].clientID.ToString(), style);
                GUI.Label(new Rect(Recv[i].x + WidthOffset, Screen.height - Recv[i].y - LabelHeight, LabelWidth, LabelHeight), Temp[i].message, style);
            }
            else
            {
                GUI.Label(new Rect(Recv[i].x, Screen.height - Recv[i].y - LabelHeight, Header, Header), Temp[i].clientID.ToString());
                GUI.Label(new Rect(Recv[i].x + WidthOffset, Screen.height - Recv[i].y - LabelHeight, LabelWidth, LabelHeight), Temp[i].message);
            }
        }
    }

 

此时,运行Server,在开启两个客户端互相发送信息,你就会看到信息在不断的刷新。。。

    private void Update()  // 这个是为了查看已经被遮掩信息
    {
        if (Input.GetMouseButtonDown(0))
        {
            posY = Input.mousePosition.y;
        }
        if (Input.GetMouseButton(0))
        {
            lock (Recv)
            {
                for (int i = 0; i <= Recv.Count - 1; i++)
                {
                    Recv[i].y += (int)(Input.mousePosition.y - posY);
                }
                posY = Input.mousePosition.y;
            }
        }
        if (Input.GetMouseButtonUp(0))
        {
            posY = 0;
        }
    }

 

最后,别忘了

    private void OnDestroy()
    {
        ConnServer.Instance.Close();
    }

 源码 : https://github.com/MLMikuLing/Socket-18-09-05.git

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值