0

I'm trying to avoid manually determining if the current instance of a running unity game is the host or client. Is there a way to detect existing games, and if there are join them, if there aren't start a host?

Note that players are not aware of networked content, so I cannot expect them to start an own host or pick an existing one to connect to.

I tried it with the NetworkDiscovery component as follows:

public class TestPlayerSetup : NetworkDiscovery {

  private float timeToWait = 1f;
  private float timeWaited = 0f;

  private bool hostDiscovered = false;

  void Start () {
    NetworkManager.singleton.networkAddress = "localhost";
    NetworkManager.singleton.networkPort = 7777;

    Initialize ();
    StartAsClient ();
  }


  void Update() {

    if (timeWaited < timeToWait) {
      timeWaited += Time.deltaTime;
      return;
    }

    if (!hostDiscovered) {
      NetworkServer.Reset ();
      NetworkManager.singleton.StartHost ();
      StartAsServer ();
      hostDiscovered = true;
    }
  }

  public override void OnReceivedBroadcast(string fromAddress, string data){
    Debug.Log ("received broadcast");
    NetworkManager.singleton.StartClient();
    hostDiscovered = true;
    setPlayerColor ();
  }

}

But it seems you can't start a NetworkDiscovery server after having started a client.

tb189
  • 1,942
  • 3
  • 22
  • 37
  • Possible duplicate of [How to get IP addresses of all devices in local network with Unity UNET in C#?](https://stackoverflow.com/questions/37951902/how-to-get-ip-addresses-of-all-devices-in-local-network-with-unity-unet-in-c) – Programmer Aug 22 '17 at 08:01
  • If `NetworkDiscovery` does not work, use UDP to implement your own. See the the duplicated question for this. – Programmer Aug 22 '17 at 08:03
  • @Programmer there is no way to get `NetworkDiscovery` to do this? UDP seems like a very complicated solution for a simple problem .. – tb189 Aug 22 '17 at 20:22
  • *"But it seems you can't start a `NetworkDiscovery` server after having started a client."* Why do you think this? – Programmer Aug 22 '17 at 21:26
  • The above code returns that error (`StartAsServer ` fails because there is already a client running) – tb189 Aug 22 '17 at 21:59
  • Here's the **full solution** https://forum.unity.com/threads/networkmanager-error-server-client-disconnect-error-1.439245/#post-3754939 – Fattie Nov 25 '18 at 04:32

2 Answers2

3

I got it to work by removing the NetworkDiscovery component when no host is discovered when running as a client, and adding a new one to start the host:

private float timeToWait = 1f;
private float timeWaited = 0f;
private NetworkDiscovery serverNetwork;
private TestPlayerClient clientNetwork;
private bool serverStarted = false;
private bool hostDiscovered = false;

void Start () {
  NetworkManager.singleton.networkAddress = "localhost";
  NetworkManager.singleton.networkPort = 7777;

  clientNetwork = gameObject.AddComponent<TestPlayerClient> ();
}

void Update() {

  if (timeWaited < timeToWait) {
    timeWaited += Time.deltaTime;
    return;
  }

  hostDiscovered = clientNetwork.hostDiscovered;
  if(clientNetwork != null && !hostDiscovered) {
    clientNetwork.StopBroadcast ();
    Destroy (clientNetwork);
    return;
  }

  if (!hostDiscovered && !serverStarted) {
    NetworkManager.singleton.StartHost ();
    serverNetwork = gameObject.AddComponent<NetworkDiscovery> ();
    serverNetwork.Initialize ();
    serverNetwork.StartAsServer ();
    serverStarted = true;
  }
}

TestPlayerClient code:

public class TestPlayerClient : NetworkDiscovery {

  public bool hostDiscovered {
    get;
    private set;
  }

    void Start () {
    Initialize ();
    StartAsClient ();
    Debug.Log ("trying client");
    hostDiscovered = false;
    }

  public override void OnReceivedBroadcast(string fromAddress, string data){
    Debug.Log ("broadcast received, starting client");
    StopBroadcast ();
    NetworkManager.singleton.StartClient();
    hostDiscovered = true;
  }

}
tb189
  • 1,942
  • 3
  • 22
  • 37
0

The above code returns that error (StartAsServer fails because there is already a client running)

Remove the NetworkManager.singleton.StartClient(); function from the OnReceivedBroadcast function. That is trying to start a client each time OnReceivedBroadcast is called.

As for connecting to server automatically, do not do that. Instead, show player List of available servers and it's their job to pick one. Seperate your code into Server and Client code.

First of all, ignore the string fromAddress parameter in the OnReceivedBroadcast function. Don't use that.

What to do on Server:

On your server code, create a simple class to hold ip and port number of the server. Use Unity's JsonUtility to serialize the class and save it to NetworkDiscovery.broadcastData. You can now call StartAsServer();.

What to do on Client:

Create a List that holds that class that holds the ip and port of the server. Populate this List in the OnReceivedBroadcast function with the (string data) which is it's second parameter. Since it's a string, you have to use JsonUtility to convert it back to class. Only add it to the List if the ip and port is not in the List.

That's it. Players can then chose which server to connect to from that List which contains sever ip and port.

Programmer
  • 121,791
  • 22
  • 236
  • 328
  • the purpose is exactly to host & connect automatically, so I cannot ignore that. – tb189 Aug 26 '17 at 09:22
  • Sure, go ahead. Make a game that automatically connects to a server. If there are two servers on the-same network, *automatically* connect to one even if player want's to connect to another one. Don't let the player connect to server they wish to. Note that I've answered why you are getting that error as StartClient is being called multiple times and which you should call once. Happy coding! – Programmer Aug 26 '17 at 09:31