我想添加局域網服務器發現到我的Unity遊戲。我正在使用UDP來廣播請求。如果網絡上的任何人是服務器,他們將以一些服務器數據作出響應。我已經想出了這一部分,但我需要使用一些Unity函數(包括其他自定義monobehaviour腳本)來生成分組數據。獲取UdpClient接收數據返回主線程
Unity不允許從主函數以外的任何線程訪問其API。
我正在使用UdpClient.BeginReceive,UdpClient.EndReceive,AsyncCallback流。因此,接收AsyncCallback函數(下面示例腳本中的AsyncRequestReceiveData
)在另一個不允許使用任何Unity函數的線程中運行。
我用flamy作爲我的腳本的基礎,使用this answer。
當腳本聽到一個請求時,我試過讓一個委託和事件在AsyncRequestReceiveData
中觸發,但似乎是在同一個單獨的線程中觸發。
單線程在主線程中觸發的事件會很好,但我不確定如何完成此操作。
雖然腳本MonoBehaviour
(在Unity 3D基對象)繼承了它應該運行就好了獨立。
腳本的輸出應該是這樣的:
Sendering請求:requestingServers
收到申請: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);
}
}
我看過this question (Cleanest Way to Invoke Cross-Thread Events),但我似乎無法弄清楚它如何工作,以及如何納入。
這是WinForms? –
@AgentShark [Unity 3D](https://unity3d.com)在我的情況。雖然這個問題並不完全是Unity。 – MLM