【问题标题】:in unity, when i call static method, program doesn't work在统一中,当我调用静态方法时,程序不起作用
【发布时间】:2016-06-11 12:58:08
【问题描述】:

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

程序启动时,我调用NetworkManager中的connect()方法,网络连接成功。而且我必须将数据包制作成字节流以发送到服务器。所以我使用编组和调用getBytes() 方法创建了PacketManager 类(静态)。但它不起作用(unity 程序被终止)。

这是我的脚本

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 中,日志打印得很好,但是如果我调用任何方法(不仅是那个方法),程序就会终止。

有什么问题?

【问题讨论】:

  • unity 程序终止 什么意思?结冰?
  • 你能调试到导致你的程序失败的行吗?终止是什么意思?崩溃、ErrorMessage、Frezze?
  • 我的意思是,“Unity 编辑器已停止工作”消息弹出,unity 程序突然退出并转到桌面(我必须重新打开 unity 程序)所以我无法检查日志消息

标签: c# unity3d


【解决方案1】:

“Unity Editor 已停止工作”消息弹出和 unity 程序 突然退出并转到桌面(我必须重新打开统一程序)所以我 无法查看日志消息

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

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

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

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

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

receive();

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

这应该可以解决您的冻结问题。如果这不起作用,那么您的代码中还有其他问题。使用来自here 的工作服务器套接字代码。您可以简单地将其转换为客户端代码。

【讨论】:

  • 是的。基本上,任何与 Unity 中的 Marshal Class 相关的东西
  • @Mark 很久以前用 Marshal 类做插件,没问题。您发布的链接说这个问题在 5.4 中得到修复,我使用 5.4.0.13b。我在这里回答了许多网络问题,通过查看她的代码,冻结是因为她没有使用异步套接字。她正在使用同步,这意味着Stream.Read 将阻塞直到收到某些内容。如果她将她的同步网络接收代码放在另一个Thread 中,只要她的网络代码经过 C# 测试并按预期工作,就应该可以解决这个问题。
  • 哈哈!我需要再次尝试在 Unity 中摆弄这个!感谢您提供详细信息,不胜感激!
猜你喜欢
  • 1970-01-01
  • 2017-02-18
  • 1970-01-01
  • 1970-01-01
  • 2013-10-24
  • 2018-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多