UNET:自动托管服务器或作为客户端加入
UNET: Automatically hosting server or joining as client
我试图避免手动确定 运行 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 ();
}
}
但是您似乎无法在启动客户端后启动 NetworkDiscovery
服务器。
The above code returns that error (StartAsServer fails because there
is already a client running)
从 OnReceivedBroadcast
函数中删除 NetworkManager.singleton.StartClient();
函数。每次调用 OnReceivedBroadcast
时都会尝试启动客户端。
至于自动连接服务器,不要那样做。相反,向玩家显示可用服务器列表,他们的工作就是选择一个。将您的代码分为服务器和客户端代码。
首先忽略OnReceivedBroadcast
函数中的字符串fromAddress
参数。不要使用那个。
在服务器上做什么:
在您的服务器代码上,创建一个简单的 class 来保存服务器的 ip 和端口号。使用Unity的将class序列化后保存到NetworkDiscovery.broadcastData
。您现在可以调用 StartAsServer();
.
在客户端做什么:
创建一个 List
保存那个 class 保存服务器的 ip 和端口。使用第二个参数 (string data
) 在 OnReceivedBroadcast
函数中填充此 List
。由于它是一个字符串,您必须使用 将其转换回 class。如果 ip 和端口不在 List
中,则仅将其添加到列表中。
就是这样。然后玩家可以从包含服务器 ip 和端口的 List
选择连接到哪个服务器。
我通过在 运行 作为客户端时没有发现主机时删除 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;
}
}
TestPlayerClient
代码:
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;
}
}
我试图避免手动确定 运行 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 ();
}
}
但是您似乎无法在启动客户端后启动 NetworkDiscovery
服务器。
The above code returns that error (StartAsServer fails because there is already a client running)
从 OnReceivedBroadcast
函数中删除 NetworkManager.singleton.StartClient();
函数。每次调用 OnReceivedBroadcast
时都会尝试启动客户端。
至于自动连接服务器,不要那样做。相反,向玩家显示可用服务器列表,他们的工作就是选择一个。将您的代码分为服务器和客户端代码。
首先忽略OnReceivedBroadcast
函数中的字符串fromAddress
参数。不要使用那个。
在服务器上做什么:
在您的服务器代码上,创建一个简单的 class 来保存服务器的 ip 和端口号。使用Unity的NetworkDiscovery.broadcastData
。您现在可以调用 StartAsServer();
.
在客户端做什么:
创建一个 List
保存那个 class 保存服务器的 ip 和端口。使用第二个参数 (string data
) 在 OnReceivedBroadcast
函数中填充此 List
。由于它是一个字符串,您必须使用 List
中,则仅将其添加到列表中。
就是这样。然后玩家可以从包含服务器 ip 和端口的 List
选择连接到哪个服务器。
我通过在 运行 作为客户端时没有发现主机时删除 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;
}
}
TestPlayerClient
代码:
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;
}
}