Client disconnected between Application.LoadLevel and OnLevelWasLoaded

Hi everyone, I have a basic network level loading question.

To test the project, I use two copies of my unity project and use one Unity instance to launch the server, and the other one to run the client.

I followed the guidelines described in Unity’s documentation

I have a scene with one gameobject and a camera. The gameobject has a component NetworkManager. On the client, it instantiates a NetworkClientManager and on the server it instantiates a NetworkServerManager.

I successfully managed to connect the client and the server. So I tried to load a level from the server, but the client get disconnected during the level loading.

This is the server code

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(NetworkView))]
public class NetworkServerManager : MonoBehaviour
{
	private int LastLoadedLevelPrefix = 0;
	public NetworkConnectionError NetworkStatus {get;private set;}
	
	void Awake()
	{
		// Network group for network management
		networkView.group = 1;
	}
	
	void Start()
	{
		// Initialize server when NetworkServerManager is started
		NetworkStatus = Network.InitializeServer(10, 25000);	
	}
	
	void OnPlayerConnected(NetworkPlayer player) 
	{
        Debug.Log("Player connected " + player.ToString());
    }

	// This is called on the server
	void OnPlayerDisconnected(NetworkPlayer player) 
	{
		Debug.Log("Player disconnected " + player.ToString());
	}
	
	void OnGUI()
	{
		if (NetworkStatus == NetworkConnectionError.NoError && GUI.Button(new Rect(0, 0, 128, 64), "Load Level")) 
		{
			Network.RemoveRPCsInGroup(0);
			Network.RemoveRPCsInGroup(1);
			networkView.RPC("LoadLevel", RPCMode.AllBuffered, "main", LastLoadedLevelPrefix + 1);
		}
	}
	
	[RPC]
	void LoadLevel(string levelName, int prefix)
	{
		LastLoadedLevelPrefix = prefix;
		
		Network.SetSendingEnabled(0, false);
		Network.isMessageQueueRunning = false;
		
		Network.SetLevelPrefix(prefix);
		Application.LoadLevel("main");
		Debug.Log("Loading level");
	}
	
	void OnLevelWasLoaded(int level)
	{
		Debug.Log("Sending data");
		Network.isMessageQueueRunning = true;
		Network.SetSendingEnabled(0, true);
	}
}

And now, the client side code :

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(NetworkView))]
public class NetworkClientManager : MonoBehaviour
{
	public NetworkConnectionError? NetworkStatus { get; private set;}
	
	public void Connect(string ip)
	{
		NetworkStatus = Network.Connect(ip, 25000);
	}
	
	public void Disconnect()
	{
		Network.Disconnect(200);
	}
	
	void Awake()
	{
		networkView.group = 1;
	}
	
	void OnEnable()
	{
		NetworkStatus = null;
	}
	
	void OnDisable()
	{
		Disconnect();
	}
	
	void OnConnectedToServer()
	{
		Debug.Log("Connected to server");
	}
	
	void OnGUI()
	{
		if (GUI.Button(new Rect(0, 0, 128, 64), "Disconnect")) 
		{
        	Disconnect();
		}
	}
	
	void OnDisconnectedFromServer(NetworkDisconnection info) 
	{
		Debug.Log("Disconnected " + info.ToString());
		NetworkStatus = null;
		Destroy(this);
	}
	
	[RPC]
	void LoadLevel(string level, int levelPrefix)
	{
		Network.SetSendingEnabled(0, false);
		Network.isMessageQueueRunning = false;
		
		Network.SetLevelPrefix(levelPrefix);
		
		Application.LoadLevel(level);
		Debug.Log(Network.peerType);
	}
	
	void OnLevelWasLoaded(int level)
	{
		Debug.Log(Network.peerType);
		ObserverManager.ObserverCamera.gameObject.active = true;
		
		Debug.Log("Sending data");
		Network.isMessageQueueRunning = true;
		Network.SetSendingEnabled(0, true);
	}
}

The logs on the server are:

  • Running as server. Player ID is 0.
  • New connection established (127.0.0.1:62466)
  • Network protocol version -2130706432 connected
  • New scope index 0 is now in scope for SceneID: 3 Level Prefix: 0
  • Allocated 2 batches of size 50 for player 1
  • Sent initalization to player 1
  • Player connected 1
  • 0 RPC function were removed with RemoveRPC
  • 0 RPC function were removed with RemoveRPC
  • Loading level
  • Sent RPC call ‘LoadLevel’ to all connected clients
  • Added RPC ‘LoadLevel’ to buffer.
  • Sending data
  • A client has disconnected from this server. Player ID 1, IP 127.0.0.1:62466
  • Player disconnected 1

And on the client :

  • Running as client. No player ID set yet.
  • Connected to 127.0.0.1:25000
  • Connected to server
  • Set player ID to 3
  • Received RPC ‘LoadLevel’- mode 2 - sender 127.0.0.1:25000
  • Relay RPC - name: LoadLevel - mode 2 - sender 127.0.0.1:25000
  • Client
  • Disconnected
  • Sending data

Well, you can see on the client the two logs : “Client”, followed by “Disconnected” which are the two calls to Debug.Log(Network.peerType) on LoadLevel and OnLevelWasLoaded

But the OnDisconnectedFromServer method is never called …

What am I missing ?

Are you actually disconnected? It seems Unity have some kind of bug that peerType won’t show the actual status in OnLevelWasLoaded. However you should make sure that your script isn’t destroyed(DontDestroyOnLoad) due to levelload. You have a “Disconnect()” in your OnDisable method so if the script get’s destroyed you will cause a disconnect.

To fully understand how the Network in Unity3d is working is with an example.

Go to this tutorial. You’ll never get something better explained!