- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试将 LAN 服务器发现添加到我的 Unity 游戏中。我正在使用 UDP 广播请求。如果网络上的任何人是服务器,他们将响应一些服务器数据。我已经弄清楚了这部分,但我需要使用一些 Unity 函数(包括其他自定义的 monobehaviour 脚本)来生成数据包数据。
Unity 不允许从除主线程之外的任何线程访问其 API。
我正在使用 UdpClient.BeginReceive , UdpClient.EndReceive , AsyncCallback流动。所以接收 AsyncCallback 函数(下面示例脚本中的 AsyncRequestReceiveData
)在另一个线程中运行,它不允许我使用任何 Unity 函数。
我用了this answer由 flamy 作为我剧本的基础。
我已尝试在 AsyncRequestReceiveData
中触发委托(delegate)和事件当脚本听到请求时,它似乎在同一个单独的线程中触发。
由单独线程在主线程中触发的事件会很好用,但我不确定如何做到这一点。
虽然脚本继承自 MonoBehaviour
(Unity 3D 中的基础对象)它应该可以独立运行。
脚本的输出应如下所示:
Sendering Request: requestingServers
Request Received: requestingServers
using UnityEngine;
using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
public class TestUDP : MonoBehaviour {
public delegate void RequestReceivedEventHandler(string message);
public event RequestReceivedEventHandler OnRequestReceived;
// Use this to trigger the event
protected virtual void ThisRequestReceived(string message)
{
RequestReceivedEventHandler handler = OnRequestReceived;
if(handler != null)
{
handler(message);
}
}
public int requestPort = 55795;
UdpClient udpRequestSender;
UdpClient udpRequestReceiver;
// Use this for initialization
void Start () {
// Set up the sender for requests
this.udpRequestSender = new UdpClient();
IPEndPoint requestGroupEP = new IPEndPoint(IPAddress.Broadcast, this.requestPort);
this.udpRequestSender.Connect(requestGroupEP);
// Set up the receiver for the requests
// Listen for anyone looking for us
this.udpRequestReceiver = new UdpClient(this.requestPort);
this.udpRequestReceiver.BeginReceive(new AsyncCallback(AsyncRequestReceiveData), null);
// Listen for the request
this.OnRequestReceived += (message) => {
Debug.Log("Request Received: " + message);
// Do some more stuff when we get a request
// Use `Network.maxConnections` for example
};
// Send out the request
this.SendRequest();
}
void Update () {
}
void SendRequest()
{
try
{
string message = "requestingServers";
if (message != "")
{
Debug.Log("Sendering Request: " + message);
this.udpRequestSender.Send(System.Text.Encoding.ASCII.GetBytes(message), message.Length);
}
}
catch (ObjectDisposedException e)
{
Debug.LogWarning("Trying to send data on already disposed UdpCleint: " + e);
return;
}
}
void AsyncRequestReceiveData(IAsyncResult result)
{
IPEndPoint receiveIPGroup = new IPEndPoint(IPAddress.Any, this.requestPort);
byte[] received;
if (this.udpRequestReceiver != null) {
received = this.udpRequestReceiver.EndReceive(result, ref receiveIPGroup);
} else {
return;
}
this.udpRequestReceiver.BeginReceive (new AsyncCallback(AsyncRequestReceiveData), null);
string receivedString = System.Text.Encoding.ASCII.GetString(received);
// Fire the event
this.ThisRequestReceived(receivedString);
}
}
最佳答案
该解决方案的工作原理是跟踪需要在主线程中执行的任务列表(队列),然后在 Update()
中运行该队列。通过 HandleTasks()
;执行并从队列中删除每个。您可以通过调用 QueueOnMainThread()
添加到任务队列并传递一个匿名函数。
我从 this answer 获得了一些灵感由 Pragmateek
您可以有一个单独的脚本来管理主线程任务,或者只是将其合并到您需要在主线程中运行某些东西的现有脚本中。
这里是 full source ,修复了我在问题中的原始片段的解决方案。
以下只是启动和运行队列的必要位:
// We use this to keep tasks needed to run in the main thread
private static readonly Queue<Action> tasks = new Queue<Action>();
void Update () {
this.HandleTasks();
}
void HandleTasks() {
while (tasks.Count > 0)
{
Action task = null;
lock (tasks)
{
if (tasks.Count > 0)
{
task = tasks.Dequeue();
}
}
task();
}
}
public void QueueOnMainThread(Action task)
{
lock (tasks)
{
tasks.Enqueue(task);
}
}
this.QueueOnMainThread(() => {
// We are now in the main thread...
Debug.Log("maxConnections: " + Network.maxConnections);
});
关于c# - 在主线程中获取 UdpClient 接收数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23588443/
有人可以向我澄清主线 DHT 规范中的声明吗? Upon inserting the first node into its routing table and when starting up th
我正在尝试使用 USB 小工具驱动程序使嵌入式设备作为 MTP 设备工作。 我知道 Android 从大容量存储设备切换到 MTP 设备已经有一段时间了,并且找到了 source code for M
我是一名优秀的程序员,十分优秀!