for clients to discover host in an offline multiplayer game but its not listing found servers. how can i go about this, or whichother way can i se to achieve the result
I rewrote the NetworkDiscovery component shipped with UNET in the past and it worked with the UnetTransport for some time. However since Netcode 1.1.0 and using UnityTransport, basic broadcasting support seems to be broken even with all firewalls disabled. With the working, previous code, neither sending nor processing incoming broadcast messages could be done, after hours trying to work something out.
So, I just assume that the underlying technique of the NetworkDiscovery component is faulty. That’s why I have thrown the old implementation away and rewrote it using the UdpClient .NET class and .send, which does work e.g. with one PC connected via LAN and a Macbook connected via WiFi on the same router (still requires disabling firewalls). It did that in my asset Tanks Multiplayer.
Could you please open a feature request here? In this way, the team behind Netcode For GameObject will be able to prioritize your features, and you’ll be automatically updated about their status
I’m having the same issue. My current (unstable) solution looks like this:
host device starts a UDP server, which sends packages via every network adapter to everyone in the same LAN
client device starts a UDP client, which listens to the same port as the host
when the client receives a package, it parses the sender IP address from it
this ip is used to configure the NetworkManager of Unitys NGO package
then the client starts with that IP using NetworkManager.Singleton.StartClient()
However, whenever I try to leave a multiplayer session and try to start a second one. I get an error saying: “An application is already bound to the port…”. So I need to figure out. Why my cleanup functions are not working properly.
Here are my Udp classes:
public class UdpServer : MonoBehaviour
{
private UdpClient udpClient;
private int port = 7778;
private float sendInterval = 1.0f; // Time in seconds between each packet
private Coroutine sendCoroutine;
private void OnEnable()
{
udpClient = new UdpClient();
udpClient.EnableBroadcast = true;
sendCoroutine = StartCoroutine(SendDataPeriodically());
}
private void OnDisable()
{
if (sendCoroutine != null)
{
StopCoroutine(sendCoroutine);
}
if (udpClient != null)
{
udpClient.Close();
udpClient = null; // Nullify the udpClient to avoid reuse
}
}
private IEnumerator SendDataPeriodically()
{
string message = "MY_GAME_IDENTIFIER";
while (true)
{
try
{
byte[ ] data = Encoding.UTF8.GetBytes(message);
udpClient.Send(data, data.Length, new IPEndPoint(IPAddress.Broadcast, port));
}
catch (Exception e)
{
Debug.LogError(e.ToString());
yield break; // Exit the coroutine if an error occurs
}
yield return new WaitForSeconds(sendInterval);
}
}
}
and for the UDP client
public class UdpClientListener : MonoBehaviour
{
public UnityEvent<string> HostIpReceived;
private UdpClient udpClient;
private int port = 7778;
private bool clientConnectionInitiated;
private void OnEnable()
{
InitializeUdpClient();
BeginReceive();
}
private void InitializeUdpClient()
{
clientConnectionInitiated = false;
// Ensure any existing UdpClient is properly closed before initializing a new one
if (udpClient != null)
{
udpClient.Close();
}
udpClient = new UdpClient(port);
}
private void BeginReceive()
{
try
{
udpClient.BeginReceive(ReceiveCallback, null);
}
catch (Exception e)
{
Debug.LogError("BeginReceive failed: " + e.Message);
}
}
private void ReceiveCallback(IAsyncResult ar)
{
if (clientConnectionInitiated)
{
return; // Exit if a connection has already been initiated
}
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
byte[ ] bytes;
try
{
bytes = udpClient.EndReceive(ar, ref remoteEndPoint);
}
catch (Exception e)
{
Debug.LogError("ReceiveCallback failed: " + e.Message);
return;
}
string receivedMessage = Encoding.UTF8.GetString(bytes);
Debug.Log("Received: " + receivedMessage);
if (IsValidIpAddress(receivedMessage))
{
clientConnectionInitiated = true;
// Extract the sender's IP address
string senderIP = remoteEndPoint.Address.ToString();
Debug.Log("Received from IP: " + senderIP);
// Use the dispatcher to handle the IP address on the main thread
MainThreadDispatcher.Enqueue(() => HostIpReceived?.Invoke(senderIP));
}
BeginReceive(); // Restart receiving if still enabled
}
private bool IsValidIpAddress(string ipAddress)
{
return IPAddress.TryParse(ipAddress, out _);
}
private void OnDisable()
{
if (udpClient != null)
{
udpClient.Close();
udpClient = null; // Ensure the UdpClient is nullified to prevent reuse
}
}
}