Unity中使用Socket进行Tcp连接-网络线程无法访问UI问题(五)

跟風遠走 提交于 2019-12-22 10:53:04

由于unity中的UI只能在主线程中访问,在网络线程中接收到的协议,无法直接用来处理UI方面显示逻辑。因此,可以先将网络线程接收到的协议缓存起来,在从主线程中一条一条取出来处理。

static void OnReceiveData()
    {
        if (buffCount<2)
        {
            return;//收到数据小于字节长度描述
        }
        int bodyLength = BitConverter.ToInt16(readBuff,0);
        if (buffCount < 2 + bodyLength)
        {
            Debug.Log("收到数据不完整");
            return;//长度不够一条完整消息
        }
        string recStr = Encoding.Default.GetString(readBuff,2, bodyLength);
        Debug.Log("收到服务器消息" + recStr);
        MsgBase msgBase = MsgBase.Decode(recStr);
        lock (MsgHandler.Instance.msgList)//多线程访问,加锁
        {
            MsgHandler.Instance.msgList.Add(msgBase);
        }
        int start = 2 + bodyLength;
        int count = buffCount - start;
        Array.Copy(readBuff,start,readBuff,0,count);
        buffCount -= start;
        OnReceiveData();
    }

在MsgHandler中接收协议,在主线程的Update中取协议进行处理,根据由协议名称注册的事件去触发相应的操作。 

class MsgHandler
{
    public delegate void MsgDelegate(MsgBase msg);

    private Dictionary<string, MsgDelegate> listeners = new Dictionary<string, MsgDelegate>();
    public List<MsgBase> msgList = new List<MsgBase>();
    private static MsgHandler instance;
    public static MsgHandler Instance
    {
        get
        {
            if (instance == null)
                instance = new MsgHandler();
            return instance;
        }
    }

    public void AddListener(string msgName, MsgDelegate listener)
    {
        if (!listeners.ContainsKey(msgName))
        {
            listeners.Add(msgName, listener);
        }
        else
        {
            listeners[msgName] = listener;
        }
    }
    public void Start()
    {
        AddListeners();
    }
    public void Update()//在主线程中取协议
    {
        if (!NetManager.isConnected) return;
        if (msgList.Count <= 0)
        {
            return;
        }

        MsgBase msg = msgList[0];
        msgList.RemoveAt(0);

        if (listeners.ContainsKey(msg.protoName))
        {
            listeners[msg.protoName](msg);//根据协议名称触发事件
        }
    }
    void AddListeners()
    {
        AddListener("MsgHeartbeat", OnHeartbeat);//根据协议名称注册相应事件
       
    }
    void OnHeartbeat(MsgBase msg)//心跳检测
    {
        Debug.Log("收到服务器心跳包");
        GameManager.Instance.ResetTimer();
    }  
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!