ZeroMQ 在 Unity 中不工作,但作为控制台应用程序工作
ZeroMQ doesn't work in Unity, but works as console application
我尝试通过 ZeroMQ 将我的 python 进程与 Unity 游戏连接起来。我有一个 python 脚本 server.py
通过 pair socket
发送消息
import zmq
context = zmq.Context()
socket = context.socket(zmq.PAIR)
socket.bind(f"tcp://*:5556")
socket.send(b"Server message to client")
print("Sent")
我有一个 MonoBehaviour
脚本附加到 Unity 中的游戏对象,它看起来像这样:
public class AiManager : MonoBehaviour
{
void Start()
{
using (var server = new PairSocket())
{
server.Connect("tcp://localhost:5556");
var msg = server.ReceiveFrameString();
Debug.Log(msg);
}
}
}
游戏永远挂在 ReceiveFrameString()
上并使 Unity 崩溃。另外 server.py
挂起并且不发送消息。
但是我创建了一个独立的控制台应用程序,代码完全相同:
class Program
{
static void Main(string[] args)
{
using (var server = new PairSocket())
{
server.Connect("tcp://localhost:5556");
var msg = server.ReceiveFrameString();
Console.WriteLine($"From Server: {msg}");
}
}
}
此应用程序完美运行。
我该如何解决?
它可以是一个完整的 PITA,确保 Unity(即 Unity 应用程序)仅具有本地对话的权限。
我假设您使用的是 PC,而不是 Mac,请仔细检查是否允许 Unity 进行此类网络连接。
Windows 防火墙设置可以是Unity的总PITA。
一个解决方案是,在 AWS 上启动一个真正的远程服务器,然后试试看!它通常比让本地主机工作更容易。
一个糟糕的问题很简单,在某些版本的 Windows 上,出现的愚蠢的“确定”对话框实际上出现在 后面 Unity,doh,可以浪费几个小时.
好的,经过几个小时的试验和浏览互联网,我已经解决了这个问题。
感谢@jdweng 的评论,首先要做的是首先从客户端向服务器发送消息。
Server doesn't do anything when a connection is made. The server is a slave and waits for a client to send a command. [...] It behaves differently as console application, because you are dealing with a different kernel/operating system with different drivers.
向客户端添加 server.SendFrameEmpty();
并向服务器添加 socket.recv()
解决了问题,但 Unity 仍然冻结。
我发现 this answer 说:
The key is to have AsyncIO.ForceDotNet.Force();
before you start and NetMQConfig.Cleanup();
before you end.
最后整个工作代码看起来像这样
public class AiManager : MonoBehaviour
{
void Start()
{
AsyncIO.ForceDotNet.Force();
using (var server = new PairSocket())
{
server.Connect("tcp://localhost:5556");
server.SendFrameEmpty();
var msg = server.ReceiveFrameString();
Debug.Log(msg);
}
NetMQConfig.Cleanup();
}
}
我尝试通过 ZeroMQ 将我的 python 进程与 Unity 游戏连接起来。我有一个 python 脚本 server.py
通过 pair socket
import zmq
context = zmq.Context()
socket = context.socket(zmq.PAIR)
socket.bind(f"tcp://*:5556")
socket.send(b"Server message to client")
print("Sent")
我有一个 MonoBehaviour
脚本附加到 Unity 中的游戏对象,它看起来像这样:
public class AiManager : MonoBehaviour
{
void Start()
{
using (var server = new PairSocket())
{
server.Connect("tcp://localhost:5556");
var msg = server.ReceiveFrameString();
Debug.Log(msg);
}
}
}
游戏永远挂在 ReceiveFrameString()
上并使 Unity 崩溃。另外 server.py
挂起并且不发送消息。
但是我创建了一个独立的控制台应用程序,代码完全相同:
class Program
{
static void Main(string[] args)
{
using (var server = new PairSocket())
{
server.Connect("tcp://localhost:5556");
var msg = server.ReceiveFrameString();
Console.WriteLine($"From Server: {msg}");
}
}
}
此应用程序完美运行。
我该如何解决?
它可以是一个完整的 PITA,确保 Unity(即 Unity 应用程序)仅具有本地对话的权限。
我假设您使用的是 PC,而不是 Mac,请仔细检查是否允许 Unity 进行此类网络连接。
Windows 防火墙设置可以是Unity的总PITA。
一个解决方案是,在 AWS 上启动一个真正的远程服务器,然后试试看!它通常比让本地主机工作更容易。
一个糟糕的问题很简单,在某些版本的 Windows 上,出现的愚蠢的“确定”对话框实际上出现在 后面 Unity,doh,可以浪费几个小时.
好的,经过几个小时的试验和浏览互联网,我已经解决了这个问题。
感谢@jdweng 的评论,首先要做的是首先从客户端向服务器发送消息。
Server doesn't do anything when a connection is made. The server is a slave and waits for a client to send a command. [...] It behaves differently as console application, because you are dealing with a different kernel/operating system with different drivers.
向客户端添加 server.SendFrameEmpty();
并向服务器添加 socket.recv()
解决了问题,但 Unity 仍然冻结。
我发现 this answer 说:
The key is to have
AsyncIO.ForceDotNet.Force();
before you start andNetMQConfig.Cleanup();
before you end.
最后整个工作代码看起来像这样
public class AiManager : MonoBehaviour
{
void Start()
{
AsyncIO.ForceDotNet.Force();
using (var server = new PairSocket())
{
server.Connect("tcp://localhost:5556");
server.SendFrameEmpty();
var msg = server.ReceiveFrameString();
Debug.Log(msg);
}
NetMQConfig.Cleanup();
}
}