Error loading level after disconnecting from room (PUN2 v2.16)

Options
BFX
BFX
Stack:
Unity 2019.2.19f1
MacOS
PUN2 v2.16

In our VR multiplayer game there are two rooms:
Lobby (scene 0) - single player
Forum (scene 1) - multiplayer

This is the flow:
  • Player 1 enter the Forum (starting from Lobby)
  • Player 2 enter the Forum (starting from Lobby)
  • Player 1 and Player 2 interact (everything ok)
  • Player 1 pushes the button to leave the room
  • Instead of leaving Scene 1 gets reloaded but Player 1 is alone
  • Player 1 pushes again the button to leave the room
  • Player 1 is back to the Lobby

The code which gets called for exiting is:
PhotonNetwork.Disconnect();
SceneManager.LoadScene(0);

This is happening after updating PUN2, before it was working fine.


Comments

  • BFX
    BFX
    edited February 2020
    Options
    I'm adding some other details:
    - the two clients I'm using are the Unity Editor and Oculus Quest
    - the problem happens on both platforms
    - the problem happens only when entering a room where there is another player
    - if I try to leave a room where there are no players the problem doesn't occur

    It's like the disconnection make fail the first call to LoadScene and therefore I'm forced to call it again
  • BFX
    BFX
    edited February 2020
    Options
    I have tried this, taken from an old forum answer :
    public void SwitchScene (int sceneNumber)
            {
                gameObject.SetActive(true);
                StartCoroutine (DoSwitchScene(sceneNumber));
            }
    
            IEnumerator DoSwitchScene (int sceneNumber)
            {
                PhotonNetwork.Disconnect();
                Debug.Log("[Multiplayer Manager] - Waiting to disconnect");
                while (PhotonNetwork.IsConnected)
                    yield return null;
                Debug.Log("[Multiplayer Manager] - Disconnected! Switching to scene:" + sceneNumber);
                SceneManager.LoadScene(sceneNumber);
            }
    
            public void LeaveRoom()
            {
                Debug.Log("[Multiplayer Manager]: Leaving room...");
                //PhotonNetwork.Disconnect();
                //SceneManager.LoadScene(0);
                SwitchScene(0);
            }
    

    if fixes the problem completely for the Unity Editor, but not on Oculus Quest where I get the following error:
    Coroutine couldn't be started because the game object 'MultiplayerManager' is inactive!

    MultiplayerManager is the prefab where all my call on my networking methods. It gets created inside the multiplayer rooms, but it's always active
  • BFX
    Options
    I have also tried:
    public override void OnDisconnected(DisconnectCause cause)
            {
                Debug.LogErrorFormat("[RoomService] OnDisconnected() was called by PUN with reason {0}", cause);
             SceneManager.LoadLevel(0);   
            }
    

    but OnDisconnected gets called only when I'm leaving an empty room
  • BFX
    BFX
    edited February 2020
    Options
    Update:
    apparently: exiting the room works ONLY when you are a MasterClient but if you joined the room as a guest the problem described at the beginning appears.

    A quick recap:

    when a user pushes a button for exiting a room, these commands get executed:
    PhotonNetwork.Disconnect();
    SceneManager.LoadScene(0);
    

    I have two callbacks for monitoring exiting a room and disconnection
    public override void OnDisconnected(DisconnectCause cause)
            {
                Debug.LogErrorFormat("[Room Service] OnDisconnected() was called by PUN with reason {0}", cause);
                
            }
    
    public override void OnLeftRoom()
            {
                Debug.Log("[Room Service]: OnLeftRoom() Local Player has left the room.");
            }
    


    Test 1 - Only Unity Editor (no other clients)
    - Player is in the lobby
    - Player pushes button to enter a room
    - Player Enter a room
    - Player is alone in the room
    - Player pushes button to exit
    - Player successfully get back to the lobby (onLeftRoom() callback is executed, OnDisconnected() callback is executed)

    Same behaviour if there is another player in the room.
    Same behaviour if Oculus Quest is the master client

    So, when you're master client everything is ok


    Test 2 - Oculus Quest (Player A) and Unity Editor ( Player B )
    - Players are in the lobby
    - Player A enters the room (so now A is master)
    - Player B enters the room (now B is a guest)
    - Player B pushes the button to exit the room
    - Scene fades out (like when SceneManager.loadScene() gets called) but instead of the lobby the same room gets reloaded, which means SceneLoader.LoadScene(0) failed)
    - Player B is now alone in the room (like the disconnection happened), onLeftRoom() was not executed, OnDisconnected() was not executed)
    - Player B pushes the button to exit the room (again)
    - Player B is now in the lobby (onLeftRoom() was not executed, OnDisconnected() was not executed)

    This is really weird....why does this work when the player exiting is a master client? It seems like the disconnection happens (although it doesn't propagate the call to my overridden method). Why is this preventing SceneManager from loading the Lobby scene??



  • BFX
    BFX
    edited February 2020
    Options
    B)B)B)B)B)B)
    After a whole night spent debugging and researching, I was able to find a workaround: it's a modification of the previous solution using a Coroutine.

    I have introduced a CoroutineHandler (thanks to a post in StackOverflow):
    public class CoroutineHandler : MonoBehaviour
        {
            private static CoroutineHandler instance = null;
            public static CoroutineHandler Instance
            {
                get
                {
                    if (instance == null)
                    {
                        GameObject inst = new GameObject("CoroutineHandler");
                        DontDestroyOnLoad(inst);
                        instance = inst.AddComponent<CoroutineHandler>();
                    }
                    return instance;
                }
            }
        }
    

    so I can call the coroutine without triggering the error when running on Oculus Quest:
    public void SwitchScene(int sceneNumber)
            {
                CoroutineHandler.Instance.StartCoroutine(DoSwitchScene(sceneNumber));
            }
    
            IEnumerator DoSwitchScene(int sceneNumber)
            {
                PhotonNetwork.Disconnect();
                Debug.Log("[Multiplayer Manager] - Waiting to disconnect");
                while (PhotonNetwork.IsConnected)
                    yield return null;
                Debug.Log("[Multiplayer Manager] - Disconnected! Switching to scene:" + sceneNumber);
                SceneManager.LoadScene(sceneNumber);
            }
    
            public void LeaveRoom()
            {
                Debug.Log("[Multiplayer Manager]: Leaving room...");
                SwitchScene(0);
                //PhotonNetwork.Disconnect();
                //SceneManager.LoadScene(0);
            }
    

    However, I think there is an underlying problem which requires a solution and not sure if this is due to a bug introduced with the latest update of PUN2.

    Any more efficient solution is very welcome.