Network.LoadLevel() not working (urgent)

Options
I'm currently trying to program transitions between games. Once a game ends, a RPC is sent out to tell all clients to re-enter my "match lobby" menu while still in the level that ended. (I'm completely re-using the match lobby menu from the main menu, and just throwing it in at the end of the game)

When the masterclient hits a "start match" button it calls Network.LoadLevel(), the same way it does when starting a match from the main menu. However, only the masterclient's level loads--the others stay frozen in the last scene and only see various state updates. In other words, "OnLevelWasLoaded()" is never triggered on the other client's games.

Any ideas why this might happen? I've also noticed some warnings from Photon on the masterclient's side, like receiving OnSerialization for nonexistent views.

I'm close to a deadline, so would I be able to work around this temporarily by doing manual level loading? (by sending out an rpc to load a level and pausing the message queue)
    [RPC]
    void EndGame(string conclusionString)
    {
        conclusion = conclusionString;
        GameObject.FindGameObjectWithTag("HUD").GetComponentInChildren<MenuManagerScript>().GoToMenu((int)HUDMenuScript.MenuName.LOBBY);
    }

void Update()
{
//...
            //check for end of game
            if (timeLimit > 0 && ((Time.time - (float)room.customProperties["st"]) > timeLimit))
            {
                room.SetCustomProperties(new Hashtable { { "on", false } });
                PhotonNetwork.RemoveAllBufferedMessages();
                PhotonNetwork.RemoveAllInstantiatedObjects();
                photonView.RPC("EndGame", PhotonTargets.All, "The game has ended...");
            }
//...
}

//elsewhere
void OnGUI()
{
if (PhotonNetwork.isMasterClient)
        {
            if(GUI.Button(new Rect(50, Screen.height - 120, 90, 70), "Start Match"))
            {
                PhotonNetwork.room.SetCustomProperties(new Hashtable { { "st", Time.time } });
                PhotonNetwork.LoadLevel("blahblahblahPlaygroundScene");
            }
}
}

Thanks!
-Scott

Comments

  • Merrik
    Options
    It looks to me like you are at no point telling the other players to load the level.

    [code2=csharp]if (PhotonNetwork.isMasterClient)
    {
    if(GUI.Button(new Rect(50, Screen.height - 120, 90, 70), "Start Match"))
    {
    PhotonNetwork.room.SetCustomProperties(new Hashtable { { "st", Time.time } });
    PhotonNetwork.LoadLevel("blahblahblahPlaygroundScene");
    }
    }[/code2]
    This ^ is only called on the master client.

    PhotonNetwork.LoadLevel("blahblahblahPlaygroundScene") does not tell all the other players to load the level, it only pauses the local message queue, loads the the level locally, and unpauses the message queue.

    You would either need to send an RPC such as:
    [code2=csharp]if (PhotonNetwork.isMasterClient)
    {
    if(GUI.Button(new Rect(50, Screen.height - 120, 90, 70), "Start Match"))
    {
    PhotonNetwork.room.SetCustomProperties(new Hashtable { { "st", Time.time } });
    photonView.RPC("StartNewLevel", PhotonTargets.All,"blahblahblahPlaygroundScene");
    }
    }

    [RPC]
    void StartNewLevel(string levelName)
    {
    PhotonNetwork.LoadLevel(levelName);
    }[/code2]
    Or look into using PhotonNetwork.automaticallySyncScene, but I don't know much about it.
  • SamusAranX
    Options
    That can't be it, because that code is also used from the main menu, which works correctly. (I am using Photon's auto sync.)

    edit: OOH! I only turn on autosync in the main menu, but perhaps it gets disabled when you switch scenes? let me check...

    edit: nope, that wasn't the problem. autosync doesn't get disabled when you switch scenes, so you don't have to reset it each time a scene is loaded. (which makes sense)

    Any other ideas?
  • SamusAranX
    Options
    Some new info that might help:

    I replaced the EndGame rpc call with a call to load the main menu scene, just to see if I could get any scene to load. That menu scene load synced correctly across the network, and the main menu even had its "OnLevelWasLoaded" function called. I then replaced that main menu load with a direct call to load the game scene again, but that didn't work, because the game scene didn't get the "OnLevelWasLoaded" call. So it appears that I can't count on Network.LoadLevel() to reload the same level twice in a row.

    Also, I got the other clients to at least unfreeze the game (I had some faulty timescale code in my HUD manager). Note that this doesn't actual fix the real issue, because they just unfreeze in the previous level that was loaded, without getting their OnLevelWasLoaded function called.
  • SamusAranX
    Options
    Ah! I hunted down the issue!
        /// <summary>Internally used to detect the current scene and load it if PhotonNetwork.automaticallySyncScene is enabled.</summary>
        internal protected void AutomaticallySyncScene()
        {
            if (PhotonNetwork.room != null && PhotonNetwork.automaticallySyncScene && !PhotonNetwork.isMasterClient)
            {
                string sceneName = (string)PhotonNetwork.room.customProperties[NetworkingPeer.CurrentSceneProperty];
                if (!string.IsNullOrEmpty(sceneName))
                {
                    //if (sceneName != Application.loadedLevelName)
                    //{
                        PhotonNetwork.LoadLevel(sceneName);
                    //}
                }
            }
        }
    

    The commented out lines are causing the error, which I would consider a bug with Photon. (Because the master client doesn't perform the same name check, so it reloads the same level, but the the other clients don't).

    Commenting out the lines caused my clients to attempt to reload the level over and over. I'm going to internally implement a "MatchIteration" custom room property so that I can perform a similar check that doesn't depend on the name of the level.
  • SamusAranX
    Options
    Got it working!!!

    New code:

    //PhotonPeer.cs line ~3200
    
        int matchIteration = 0;//starts at zero, which means no match has been loaded yet
        /// <summary>Internally used to detect the current scene and load it if PhotonNetwork.automaticallySyncScene is enabled.</summary>
        internal protected void AutomaticallySyncScene()
        {
            if (PhotonNetwork.room != null && PhotonNetwork.automaticallySyncScene && !PhotonNetwork.isMasterClient)
            {
                string sceneName = (string)PhotonNetwork.room.customProperties[NetworkingPeer.CurrentSceneProperty];
                if (!string.IsNullOrEmpty(sceneName))
                {
    
                    int newMatchIteration = (int)PhotonNetwork.room.customProperties["mi"];
    
                    if (sceneName != Application.loadedLevelName || newMatchIteration > matchIteration)
                    {
                        matchIteration = newMatchIteration;
                        PhotonNetwork.LoadLevel(sceneName);
                    }
                }
            }
        }
    
    //creating the room:
        private void CreateMatch()
        {
            if (matchName == "")
            {
                error = "Please enter a match name";
            }
            else
            {
                string[] roomPropsInLobby = { // blah blah blah };
                Hashtable customRoomProps = new Hashtable() { { "mi", 0 }, //blah blah blah }; //"mi" is match iteration, starts at zero, which means no match has been loaded yet
                PhotonNetwork.CreateRoom(matchName, true, true, 8, customRoomProps, roomPropsInLobby);
            }
        }
    [\code]
    
    //starting a new match iteration:
    public override void OnGUI()
        {
            if (PhotonNetwork.isMasterClient)
            {
                if(GUI.Button(new Rect(50, Screen.height - 120, 90, 70), "Start Match"))
                {
                    int matchIteration = (int)room.customProperties["mi"];
                    matchIteration++;
    
                    PhotonNetwork.room.SetCustomProperties(new Hashtable { { "mi", matchIteration }, //blah blah blah });
                    PhotonNetwork.LoadLevel("blahblahPlaygroundScene");
                }
          }
    }
    

    For some reason the match iteration strategy alone wasn't enough to get all clients sitting in the main menu to load up the first level, so I ORed my iteration check with the name check. I haven't tested to see if my match iteration strategy works for switching from one game scene to a different game scene correctly yet. It does work for getting started with the first game scene, and reloading the same game scene.
  • Tobias
    Options
    "The commented out lines are causing the error, which I would consider a bug with Photon. (Because the master client doesn't perform the same name check, so it reloads the same level, but the the other clients don't)."

    Good hunting.
    Yes, obviously the master behaves differently than the clients. On the other hand: I'd rather add the "same level check" to the master, too. It makes sure you don't load the level over and over for any reason.
    In any case, a log entry for skipping the room might be good.
  • slake_it
    Options
    Thanks for the debugging, I've solved it by loading an empty scene that only reloads the target scene