在统一中,当我调用静态方法时,程序不起作用

时间:2016-06-11 12:58:08

标签: c# unity3d

我想用Unity制作套接字网络程序,所以我制作了测试项目并在该项目中添加了NetworkManager类和PacketManager类进行测试。

程序启动时,我在connect()中调用NetworkManager方法,然后网络连接成功。我必须将数据包发送到字节流以便发送到服务器。所以我使用编组和调用PacketManager方法使getBytes()类(静态)。但它不起作用(统一程序终止)。

这是我的脚本

Move.cs

using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.Net;
using System;
using System.Runtime.InteropServices;

public class move : MonoBehaviour {

    private NetworkManager nManager;

    // Use this for initialization
    void Start () {
        Debug.Log ("start");

        nManager = new NetworkManager ();
        nManager.connect ();

        packet p = new packet();
        p.type = 100;
        p.msg = "abcdabcd";

        byte[] array = PacketManager.getBytes (p);

    }

    // Update is called once per frame
    void Update () {

    }
}

NetworkManager.cs

using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.Net;
using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct packet
{
    public int type;
    public int number;
    public int room;
    public float x, y, z;
    public float rotate;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
    public string msg;
}

public class NetworkManager : MonoBehaviour
{
    private const string serverIP = "127.0.0.1";
    private const int portNum = 9090;
    private const int buffersize = 128;

    private static TcpClient client = null;
    private static NetworkStream netStream = null;

    public NetworkManager() {}

    public Boolean connect()
    {
        Boolean success = false;

        try
        {
            Debug.Log("try to connenct..");
            client = new TcpClient(serverIP, portNum);
            netStream = client.GetStream();
            Debug.Log("connected success!");

        }
        catch (Exception e)
        {
            success = false;
            Debug.Log(e.Message);
        }

        return success;
    }

    public void sendPacket(packet p)
    {
        byte[] array = PacketManager.getBytes(p);
        netStream.Write(array, 0, buffersize);
    }

    public packet recvPacket()
    {
        packet p = new packet();
        byte[] bytebuffer = new Byte[buffersize];
        int totalByteRcvd = 0;
        int bytesRcvd = 0;

        while (totalByteRcvd < buffersize)
        {
            if ((bytesRcvd = netStream.Read(bytebuffer, totalByteRcvd, buffersize - totalByteRcvd)) == 0)
            {

                p = PacketManager.BytesToSturct<packet>(bytebuffer);

                break;
            }
            totalByteRcvd += bytesRcvd;
            Debug.Log("byte : " + totalByteRcvd);
        }

        return p;
    }

}

PacketManager.cs

using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.Net;
using System;
using System.Runtime.InteropServices;

public class PacketManager : MonoBehaviour
{

    public static byte[] getBytes(object str)
    {

        int size = Marshal.SizeOf(str);
        byte[] arr = new byte[size];
        IntPtr ptr = Marshal.AllocHGlobal(size);

        Marshal.StructureToPtr(str, ptr, true);
        Marshal.Copy(ptr, arr, 0, size);
        Marshal.FreeHGlobal(ptr);

        return arr;
    }

    public static T BytesToSturct<T>(byte[] buffer) where T : struct
    {
        int size = Marshal.SizeOf(typeof(T));

        IntPtr ptr = Marshal.AllocHGlobal(size);
        Marshal.Copy(buffer, 0, ptr, size);
        T obj = (T)Marshal.PtrToStructure(ptr, typeof(T));
        Marshal.FreeHGlobal(ptr);

        return obj;
    }

}

如果我删除:

byte[] array = PacketManager.getBytes (p);

move.cs中,日志打印得很好,但如果我调用任何方法(不仅仅是该方法),程序也会终止。

有什么问题?

1 个答案:

答案 0 :(得分:1)

  

“Unity编辑已经停止工作”消息是流行和统一程序   突然退出并转到桌面(我必须重新打开统一程序)所以我   无法检查log msg

我可以在您的代码中发现一些问题。

1 。您使用的synchronous socket没有Thread。使用synchronous socket时,您必须使用Thread,否则它会在等待客户端连接,连接到服务器或等待从客户端接收时冻结Unity。

另一种解决方案是使用asynchronous socket。您不需要Thread来使用它。

<强> 2 即可。while (totalByteRcvd < buffersize)。这将立即冻结Unity直到totalByteRcvd >= buffersize,在此之前,netStream.Read必须返回,但由于#1 中的问题,这不会很快发生。

所以让你的recvPacket()函数成为一个void函数,就像这样调用它:

receive();

void receive()
{
    System.Threading.Thread socketThread = new System.Threading.Thread(recvPacket);
    socketThread.Start();
}

这可以解决你的冰冻问题。如果这不起作用,那么代码中还存在其他问题。使用here中的工作服务器套接字代码。您只需将其转换为客户端代码即可。