I have a custom Network Manager which identifies when a connection and disconnection occurs.
The flow is:
- Choose Online
- Choose public or private match
- Join/Create match (if you quit and rejoin here theres no issue)
- Start Match (scene change occurs using MyNetManager.singleton.ServerChangeScene)
- Finish Match
- Rematch/Change Characters/Quit
Rematch and Changing Characters works fine but if you quit and rejoin one of the following errors will occur:
- A connection has already been set as ready. There can only be one.
- There is already a player at that playerControllerId for this connections.
The behaviour is that the last player to join the room is thrown into a blank version of the scene that is loaded in step 4 while the one who created the room seems to have a correctly loaded character select scene.
The network manager code is as follows. I have been trying a lot of things to try and get it to clean up the match correctly so it might look a mess to you.:
public class MyNetManager : NetworkManager {
bool shuttingDown = false;
loadingScreen ld;
void Start()
{
ld = GameObject.FindGameObjectWithTag("loading").GetComponent<loadingScreen>();
if (PlayerPrefs.GetInt("GameType", 0) < 2)
loading(false);
}
public override void OnMatchCreate(bool success, string extendedInfo, MatchInfo matchInfo)
{
if (success)
loading(false);
else
message("Please check your internet connection . . .");
base.OnMatchCreate(success, extendedInfo, matchInfo);
}
public override void OnMatchJoined(bool success, string extendedInfo, MatchInfo matchInfo)
{
if (success)
loading(false);
else
message("Please check your internet connection . . .");
base.OnMatchJoined(success, extendedInfo, matchInfo);
}
public override void OnStartClient(NetworkClient client)
{
loading(false);
base.OnStartClient(client);
}
// This is called when quit is selected in step 6
public void disconnectPlayer()
{
if (matchInfo != null)
{
matchMaker.SetMatchAttributes(matchInfo.networkId,false, matchInfo.domain, OnSetMatchAttributes);
Network.RemoveRPCs(Network.player);
Network.DestroyPlayerObjects(Network.player);
matchMaker.DropConnection(matchInfo.networkId, matchInfo.nodeId, matchInfo.domain, OnDropConnection);
}
else
returnToHome();
}
public override void OnClientDisconnect(NetworkConnection conn)
{
NetworkServer.DestroyPlayersForConnection(conn);
loading(true);
message("Player left the game");
}
public override void OnServerDisconnect(NetworkConnection conn)
{
NetworkServer.DestroyPlayersForConnection(conn);
loading(true);
message("Player left the game");
}
public override void OnDropConnection(bool success, string extendedInfo)
{
base.OnDropConnection(success, extendedInfo);
if (!shuttingDown)
returnToHome();
}
private void returnToHome()
{
shuttingDown = true;
Network.Disconnect();
StopHost();
SceneManager.LoadScene(0);
Destroy(gameObject);
}
void loading(bool show)
{
if (ld != null)
ld.gameObject.SetActive(show);
}
void message(string message) {
if(ld !=null){
ld.setAnimation(1);
ld.quit(message); // disconnectPlayer is called from here
}
}
}
The disconnect overrides do not call the super because it ends up giving a server timeout error.
Thank you for any explanations of what I have done terribly wrong, help or suggestions in advance