Leaving room in Photon

The whole answer can be found below.

Please note: The Photon forum is closed permanently. After many dedicated years of service we have made the decision to retire our forum and switch to read-only: we've saved the best to last! And we offer you support through these channels:

Try Our
Documentation

Please check if you can find an answer in our extensive documentation on PUN.

Join Us
on Discord

Meet and talk to our staff and the entire Photon-Community via Discord.

Read More on
Stack Overflow

Find more information on Stack Overflow (for Circle members only).

Write Us
an E-Mail

Feel free to send your question directly to our developers.

Leaving room in Photon

teofilo
2021-03-03 15:58:38

Hi everyone, I create a simple multiplayer game using PUN2 where one player can create a room with a specific name and another player can join this room by clicking its name in a simple list. After that I add an "exit button" that allow the player to leave the room before the start of the game using PhotonNetwork.LeaveRoom(); because I thounght that this code make the room re-joinable but the room is no more joinable after the leave of the player, indipendently if the player is the masterclient or not. So my question is: is there any method to make a room re-joinable after one player leaves it? Or in case that's not possible, is there any method that I can use to force to leave every player and close the room when someone click "exit button"? Thanks in advance and sorry for my bad English :)

Comments

Tobias
2021-03-04 16:11:30

The room should be "joinable", provided it's not closed or full.
But an empty room will be cleaned up (no active players -> room gets cleaned up and can't be re joined).

Steven123
2022-06-23 15:11:16

What about when you have the following situation:

  • Player X creates a room.

  • After the level loads up, he immediately exits (PhotonNetwork.LoadLevel("Lobby")).

  • And tries to create a room with the same properties, same name etc.

I tried to implement this and it gives me an error: "MissingReferenceException: THe object of type 'GameObject' has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object.".

Why does that happen? Does that have anything to do with the fact that when the player exits the room, only PhotonNetwork.LoadLevel() is called instead of LeaveRoom()?

Tobias
2022-06-24 09:58:10

First off: LoadLevel does not leave the room. You can not join new rooms unless the LBC is connected to the Master Server...

Why this happens? Because "The object of type 'GameObject' has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object."

You need to figure out which object is missing, then why it is missing. Usually, Unity destroys the old scene, when you load a new one, so that may be a hint.

It's not something I can dive deeper into but maybe the community can help.

tleylan
2022-06-26 11:54:33

Steven, I don't know PUN well but I learn a lot by trying to solve issues. They key here is confirm what your code does when you write "immediately exits" and "create a room", etc.

Are you calling PhotonNetwork.LeaveRoom() to leave? That's the start of the pattern. It will call OnLeftRoom which gives you a change to process more after having left.

Steven123
2022-06-30 16:43:17

So here is what I tried to implement. Sorry for the late reply.

This is how I create the room:

 RoomOptions options = new RoomOptions()    
        {    


            IsOpen = true,    
            MaxPlayers = (byte)nrPlayers_HostGame,    
            CustomRoomProperties = new ExitGames.Client.Photon.Hashtable()    
            {    
                { "C0", "yes" },    
                { "C1", HG_NameGame.text }    
            },    
            CustomRoomPropertiesForLobby = new string[]    
            {    
                "C0",    
                "C1",    
                "key"    
            }    
            //CleanupCacheOnLeave = false    
        };    


        if (!Public_Toggle.isOn)    
        {    
            options.CustomRoomProperties.Add("key", PasswordEncryptor.Encrypt(HG_PasswordGame.text));    
            options.IsVisible = false;    
        }    
        else    
        {    
            options.CustomRoomProperties.Add("public", true);    
            options.IsVisible = true;    
        }    




        PhotonNetwork.LocalPlayer.SetCustomProperties(new ExitGames.Client.Photon.Hashtable()    
        {    
            { "knowsPassword", true }    
        });    
        PhotonNetwork.CreateRoom(HG_NameGame.text, options, customLobby);    

I don't actually use the "C0" or "C1" things because I don't understand how the OnRoomListUpdated works since it is never called in any instance.

Anyhow, leaving that aside, this is how I exit a room. Nothing too crazy, just a simple button in the player's UI:

public void ExitButton_OnClick()    
    {    
        if (PhotonNetwork.InRoom)    
        {    
            if (PhotonNetwork.IsMasterClient && PhotonNetwork.CurrentRoom.PlayerCount > 1) MigrateMaster();    
            else    
            {    
                PhotonNetwork.DestroyPlayerObjects(PhotonNetwork.LocalPlayer);    
                PhotonNetwork.LeaveRoom();    
            }    
        }    
    }    

private void MigrateMaster()    
    {    
        var dict = PhotonNetwork.CurrentRoom.Players;    
        if (PhotonNetwork.SetMasterClient(dict[dict.Count - 1]))    
            PhotonNetwork.LeaveRoom();    
    }    


    public override void OnLeftRoom()    
    {    
        Debug.LogError("Left room");    
        PhotonNetwork.LoadLevel("Launcher");    
        Debug.LogError("Left room");    
    }    

Now, the biggest problem is that the button is pressed correctly and the "event" is detected. However, the Debug.LogError("Left room") in OnLeftRoom() method is NEVER called. And instead of loading the Launcher scene, it just stays in the Game scene with the player's instance being destroyed which is very suspicious to me.

Steven123
2022-06-30 17:31:45

I just further tested this scenario and it makes me believe only one thing:

The player is destroyed way too early and the OnLeftRoom() method which is in the same script will never get called.

I tried to make call DontDestroyOnLoad() for the instance off the player, but that doesn't solve it.

Any suggestions at this point?

Steven123
2022-06-30 17:57:18

I actually solved this issue by using OnPlayerLeftRoom(Player otherPlayer).

The best solution I found, and it works whether you are a master client or not in a room, is to let a Manager script (usually the one that spawns the players in the room) handle the Destroy methods instead of the player who leaves the room at that instance.

It's best to leave the room option CleanupCacheOnLeave to false so that the Manager script can destroy the inactive players manually. I guess this way you have more control and you know each time when each player was destroyed or not.

And so the player can just have **PhotonNetwork.LeaveRoom()**and the OnLeftRoom() callback in the player script and the manager script will **PhotonNetwork.Destroy(otherPlayer)**in the OnPlayerLeftRoom(Player otherPlayer).

**P.S.:**The method **PhotonNetwork.DestroyPlayerObjects(otherPlayer)**also destroys the objects that the player instantiated, so be careful.

tleylan
2022-07-01 02:28:40

Hi @Steven123 I can't say exactly understand your intent but it looks like you are handing off the "Master" role. I do not know (someone can comment) if this is needed (maybe so) but the process (if needed) is surely templated somewhere.

You have a bit of spaghetti creeping in (from what I can see) which may make your logic slightly less than obvious. Assuming the "key" and "public" properties are always set one way or the other? It seems that Public_Toggle.isOn could be passed as a parameter to the constructor thereby getting back a fully-baked RoomOptions object.

Similarly I don't see the need for two branches in the Exit OnClick handler. When someone clicks the exit button they go to a single handler which determines how best to handle it. Then for instance you don't sometimes exit from the OnClick handler and sometimes from MigrateMaster.

And from a VR course I took we call PhotonNetwork.Disconnect from OnLeftRoom and then in OnDisconnected return them to a "home room". It apparently can help clean things up but I can't attest to it (just read it somewhere).

Bottom line is if things are seeming acting "weird" it may indicate something in your logic. The library has been used for a long time and if there were lots of "gotchas" I have to assume there would be list available.

Back to top