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处理数据并将数据 在UGUI、NGUI上显示出来)