C# UNET:自动托管服务器或作为客户端加入

C# UNET:自动托管服务器或作为客户端加入,c#,unity3d,networking,unity5,C#,Unity3d,Networking,Unity5,我试图避免手动确定正在运行的unity游戏的当前实例是主机还是客户端。有没有办法检测现有的游戏,如果有人加入游戏,如果没有人启动主机 请注意,玩家不知道网络内容,因此我不能期望他们启动自己的主机或选择现有主机进行连接 我使用NetworkDiscovery组件进行了如下尝试: public class TestPlayerSetup : NetworkDiscovery { private float timeToWait = 1f; private float timeWaited

我试图避免手动确定正在运行的unity游戏的当前实例是主机还是客户端。有没有办法检测现有的游戏,如果有人加入游戏,如果没有人启动主机

请注意,玩家不知道网络内容,因此我不能期望他们启动自己的主机或选择现有主机进行连接

我使用
NetworkDiscovery
组件进行了如下尝试:

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 ();
  }

}
公共类TestPlayerSetup:NetworkDiscovery{
专用浮动时间等待=1f;
私有浮动时间等待=0f;
private bool hostDiscovered=false;
无效开始(){
NetworkManager.singleton.networkAddress=“localhost”;
NetworkManager.singleton.networkPort=7777;
初始化();
StartAsClient();
}
无效更新(){
if(timewait
但在启动客户端之后,似乎无法启动
NetworkDiscovery
服务器


上面的代码返回该错误(StartAServer失败,因为 已经有一个客户端正在运行)

删除
NetworkManager.singleton.StartClient()功能。这是指每次调用OnReceivedBroadcast
时尝试启动客户端

至于自动连接到服务器,请不要这样做。相反,向玩家显示可用服务器的列表,他们的工作就是选择一个。将代码分为服务器代码和客户端代码

首先,在
OnReceivedBroadcast
函数中忽略字符串
fromAddress
参数。不要用那个

在服务器上执行的操作:

在服务器代码上,创建一个简单的类来保存服务器的ip和端口号。使用Unity序列化类并将其保存到
NetworkDiscovery.broadcastData
。现在可以调用
StartAsServer()

在客户端执行的操作:

创建一个
列表
,该列表包含包含服务器ip和端口的类。使用(
字符串数据
)作为第二个参数,在
OnReceivedBroadcast
函数中填充此
列表
。因为它是一个字符串,所以必须使用将其转换回类。仅当ip和端口不在
列表中时,才将其添加到列表中

就这样。然后,玩家可以从包含服务器ip和端口的
列表中选择要连接到的服务器


上面的代码返回该错误(StartAServer失败,因为 已经有一个客户端正在运行)

删除
NetworkManager.singleton.StartClient()功能。这是指每次调用OnReceivedBroadcast
时尝试启动客户端

至于自动连接到服务器,请不要这样做。相反,向玩家显示可用服务器的列表,他们的工作就是选择一个。将代码分为服务器代码和客户端代码

首先,在
OnReceivedBroadcast
函数中忽略字符串
fromAddress
参数。不要用那个

在服务器上执行的操作:

在服务器代码上,创建一个简单的类来保存服务器的ip和端口号。使用Unity序列化类并将其保存到
NetworkDiscovery.broadcastData
。现在可以调用
StartAsServer()

在客户端执行的操作:

创建一个
列表
,该列表包含包含服务器ip和端口的类。使用(
字符串数据
)作为第二个参数,在
OnReceivedBroadcast
函数中填充此
列表
。因为它是一个字符串,所以必须使用将其转换回类。仅当ip和端口不在
列表中时,才将其添加到列表中


就这样。然后,玩家可以从包含服务器ip和端口的
列表中选择要连接到的服务器。

当作为客户端运行时未发现主机时,我通过删除
网络发现组件
并添加一个新组件来启动主机,从而使其正常工作:

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;
  }
}

当作为客户机运行时未发现主机时,我删除了
NetworkDiscovery
组件,并添加了一个新组件以启动主机,从而使其正常工作:

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;
  }
}

如果
NetworkDiscovery
的可能重复项不起作用,请使用UDP实现您自己的。请参阅重复的问题。@Programmer没有办法让
NetworkDiscovery
这样做吗?对于一个简单的问题,UDP似乎是一个非常复杂的解决方案。“但是,在启动客户端之后,您似乎无法启动
NetworkDiscovery
服务器。”您认为这是为什么?上面的代码返回该错误(
StartAsServer
失败,因为已经有客户端在运行)如果
NetworkDiscovery
的可能重复项不起作用,请使用UDP实现您自己的。请参阅重复的问题。@Programmer没有办法让
NetworkDiscovery
这样做吗?对于一个简单的问题,UDP似乎是一个非常复杂的解决方案。“但是,在启动客户端之后,您似乎无法启动
NetworkDiscovery
服务器。”您认为这是为什么?上面的代码返回该错误(
StartAsServer
失败,因为已经有客户端在运行)其目的正是为了自动承载和连接,所以我不能忽视这一点。当然,请继续。制作一个自动连接到服务器的游戏。如果同一网络上有两台服务器,则自动连接到一台服务器,即使是i