Unity3D 使用Socket处理数据并将数据 在UGUI、NGUI上显示出来

Unity3d 不支持C#的线程直接调用Unity3D 主线程才能实现的功能。例如:给UGUI text 赋值、改变Color值等。怎样解决这个问题呢?使用一个Loom脚本。

按照惯例贴上代码。

首先Loom脚本

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Threading;
using System.Linq; 


public class Loom : MonoBehaviour 
{


    public static int maxThreads = 8;
    static int numThreads;


    private static Loom _current;
    private int _count;
    public static Loom Current
    {
        get
        {
            Initialize();
            return _current;
        }
    }


    void Awake()
    {
        _current = this;
        initialized = true;
    }


    static bool initialized;


    static void Initialize()
    {
        if (!initialized)
        {


            if (!Application.isPlaying)
                return;
            initialized = true;
            var g = new GameObject("Loom");
            _current = g.AddComponent();
        }


    }


    private List _actions = new List();
    public struct DelayedQueueItem
    {
        public float time;
        public System.Action action;
    }
    private List _delayed = new List();


    List _currentDelayed = new List();


    public static void QueueOnMainThread(System.Action action)
    {
        QueueOnMainThread(action, 0f);
    }
    public static void QueueOnMainThread(System.Action action, float time)
    {
        if (time != 0)
        {
            lock (Current._delayed)
            {
                Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action });
            }
        }
        else
        {
            lock (Current._actions)
            {
                Current._actions.Add(action);
            }
        }
    }


    public static Thread RunAsync(System.Action a)
    {
        Initialize();
        while (numThreads >= maxThreads)
        {
            Thread.Sleep(1);
        }
        Interlocked.Increment(ref numThreads);
        ThreadPool.QueueUserWorkItem(RunAction, a);
        return null;
    }


    private static void RunAction(object action)
    {
        try
        {
            ((System.Action)action)();
        }
        catch
        {
        }
        finally
        {
            Interlocked.Decrement(ref numThreads);
        }


    }




    void OnDisable()
    {
        if (_current == this)
        {


            _current = null;
        }
    }






    // Use this for initialization  
    void Start()
    {


    }


    List _currentActions = new List();


    // Update is called once per frame  
    void Update()
    {
        lock (_actions)
        {
            _currentActions.Clear();
            _currentActions.AddRange(_actions);
            _actions.Clear();
        }
        foreach (var a in _currentActions)
        {
            a();
        }
        lock (_delayed)
        {
            _currentDelayed.Clear();
            _currentDelayed.AddRange(_delayed.Where(d => d.time <= Time.time));
            foreach (var item in _currentDelayed)
                _delayed.Remove(item);
        }
        foreach (var delayed in _currentDelayed)
        {
            delayed.action();
        }






    }  
}


/*
 * 调用案例
 */ 


//public class LoomUse
//{
//    void ScaleMesh(Mesh mesh, float scale)
//    {
//       
//        var vertices = mesh.vertices;
//        //Run the action on a new thread  
//        Loom.RunAsync(() =>
//        {
//            //Loop through the vertices  
//            for (var i = 0; i < vertices.Length; i++)
//            {
//                //Scale the vertex  
//                vertices[i] = vertices[i] * scale;
//            }
//            //Run some code on the main thread  
//            //to update the mesh  
//            Loom.QueueOnMainThread(() =>
//            {
//                //Set the vertices  
//                mesh.vertices = vertices;
//                //Recalculate the bounds  
//                mesh.RecalculateBounds();
//            });


//        });
//    }  

//}

其次: Socket脚本

using System;
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace ReceiveMessage
{


    class ReceiveMessage : MonoBehaviour
    {
        public delegate void ReceiveMes(string str);
        public static event ReceiveMes receiveMes;
        //在内存中开辟一块1024缓存区域
        private static byte[] result = new byte[1024];
        //自定义一个端口
        private static int myProt = 8009;
        //定义服务器 Socket 对象
        private static Socket serverSocket;
        private static int SencenNum = 0;
        public Button mListenButton;
        public Text mMainMessagetext;


        private Thread MainThread;
        public GameObject[] obj;
        public string getInfo;
        public object Wait { get; private set; }
        void Start()
        {
            mListenButton.onClick.AddListener(ListenFunction);
        }
        //private void Update()
        //{
        //    mMainMessagetext.text = getInfo;
        //}
        void ListenFunction()
        {
            DontDestroyOnLoad(this.gameObject);
            IPAddress ip = IPAddress.Parse("192.168.2.176");
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            serverSocket.Bind(new IPEndPoint(ip, myProt));
            serverSocket.Listen(10);
            Console.WriteLine("启动监听{0}成功", serverSocket.LocalEndPoint.ToString());
            MainThread = new Thread(ListenClientConnect);
            MainThread.Start();
        }
        private void ListenClientConnect()
        {
            while (true)
            {
                Socket clientSocket = serverSocket.Accept();
                clientSocket.Send(Encoding.ASCII.GetBytes("Server Say Hello"));
                Thread receiveThread = new Thread(ReceiveMessage1);
                receiveThread.Start(clientSocket);
            }
        }
        private void ReceiveMessage1(object clientSocket)
        {


            Socket myClientSocket = (Socket)clientSocket;
            Boolean b = true;


            while (b)
            {
                try
                {
                    int receiveNumber = myClientSocket.Receive(result);
                    string str = Encoding.UTF8.GetString(result, 0, receiveNumber);

                    if (str.Equals(""))
                    {
                        b = false;
                    }
                    else
                    {
                        
                         Loom.RunAsync(() =>
                        {
                               //处理普通数据  例如:1+1,
                            Loom.QueueOnMainThread(() =>

                            {

                                receiveMes(str);// 调到 unity3d 主线程上
                            });
                        });

                    }
                }
                catch (Exception ex)
                {
                    Debug.Log(ex.Message);
                    myClientSocket.Shutdown(SocketShutdown.Both);
                    myClientSocket.Close();
                    break;
                }
            }
        }


    }

}

最后,UGUI 页面

using UnityEngine;
using UnityEngine.UI;
using System.Collections;


namespace ReceiveMessage
{
    public class Test : MonoBehaviour
    {
        public Text mText;

        

        private void OnEnable()

        {
            ReceiveMessage.receiveMes += ReceiveMes;
        }
        private void Start()
        {
            if (mText == null)
            {
                mText = GetComponent();
            }
        }


        private void OnDisable()
        {
            ReceiveMessage.receiveMes -= ReceiveMes;
        }


        private void OnDestroy()
        {
            ReceiveMessage.receiveMes -= ReceiveMes;
        }


        public void ReceiveMes(string str)
        {
            if (mText)
            {
                mText.text = str;
            }


        }
    }
}

总结,Loom是一个单例脚本,必须挂在场景中一个空物体上,不然,Loom不起作用





你可能感兴趣的:(知识点,Unity3D,Socket)