Search Unity

Third Party PUN1 - Is it possible to ReconnectAndRejoin() without reinstantiating room objects?

Discussion in 'Multiplayer' started by MrConkin, Jul 29, 2022.

  1. MrConkin

    MrConkin

    Joined:
    Feb 11, 2013
    Posts:
    20
    Goal
    I am implementing a flow that gives players a 10 second window to reconnect and rejoin a room after they disconnect from my multiplayer game. If the reconnect and rejoin are successful, I would like to maintain the state of all of the objects on the reconnecting player's client and resume play. It is a turn-based game that takes place in a single scene, so I am fairly confident that changes will not have taken place which could compromise the game state.

    Problem
    Upon reconnecting, all of the room's gameobjects are reinstantiated and each one produces the following error:
    Code (CSharp):
    1. PhotonView ID duplicate found: 1001. New: View (0)1001 on Agent(Clone)  old: View (0)1001 on Agent(Clone) . Maybe one wasn't destroyed on scene load?! Check for 'DontDestroyOnLoad'. Destroying old entry, adding new.
    All of the objects are replaced, which means they lose their connections and context. After reading this thread, I also tried PhotonNetwork.DestroyAll() which solved for the errors, but connections and context are lost in that scenario as well. Manually re-establishing the state of each object would be prohibitively difficult.

    Question
    Is it possible to stop PUN from reinstantiating these objects on rejoin if they already exist?

    If this is not possible, do you have any recommendations for how to maintain connections and context(e.g. script/object references, tables of data, variables, etc.) on reinstantiation?
     
    Last edited: Jul 29, 2022
  2. tobiass

    tobiass

    Joined:
    Apr 7, 2009
    Posts:
    3,066
    You could modify PUN's code to keep the objects, which are existing locally already. This check is done in PhotonNetwork.RegisterPhotonView(). It should be simple to turn this around to keep the object that was found in the list.
     
  3. MrConkin

    MrConkin

    Joined:
    Feb 11, 2013
    Posts:
    20
    Thanks for the direction tobiass, will give that a shot.
     
  4. MrConkin

    MrConkin

    Joined:
    Feb 11, 2013
    Posts:
    20
    Success I think! I had to modify PUN in the following locations:

    In the RegisterPhotonView function in NetworkPeer.cs as you called out, I commented out the RemoveInstantiatedGO call and added a return if the viewID already exists.

    Code (CSharp):
    1.   public void RegisterPhotonView(PhotonView netView)
    2.     {
    3.         if (!Application.isPlaying)
    4.         {
    5.             this.photonViewList = new Dictionary<int, PhotonView>();
    6.             return;
    7.         }
    8.  
    9.         if (netView.viewID == 0)
    10.         {
    11.             // don't register views with ID 0 (not initialized). they register when a ID is assigned later on
    12.             Debug.Log("PhotonView register is ignored, because viewID is 0. No id assigned yet to: " + netView);
    13.             return;
    14.         }
    15.  
    16.         PhotonView listedView = null;
    17.         bool isViewListed = this.photonViewList.TryGetValue(netView.viewID, out listedView);
    18.         if (isViewListed)
    19.         {
    20.             // if some other view is in the list already, we got a problem. it might be undestructible. print out error
    21.             if (netView != listedView)
    22.             {
    23.                 Debug.LogError(string.Format("PhotonView ID duplicate found: {0}. New: {1} old: {2}. Maybe one wasn't destroyed on scene load?! Check for 'DontDestroyOnLoad'. Destroying old entry, adding new.", netView.viewID, netView, listedView));
    24.             }
    25.             else
    26.             {
    27.                 return;
    28.             }
    29.            
    30.             // Stop Photon from removing instantiated objects if they already exist - we need them in case of a reconnect
    31.             //this.RemoveInstantiatedGO(listedView.gameObject, true); // I commented this out
    32.             return; // I added this
    33.         }
    34.         // Debug.Log("adding view to known list: " + netView);
    35.         this.photonViewList.Add(netView.viewID, netView);
    36.         //Debug.LogError("view being added. " + netView);    // Exit Games internal log
    37.  
    38.         if (PhotonNetwork.logLevel >= PhotonLogLevel.Full)
    39.         {
    40.             Debug.Log("Registered PhotonView: " + netView.viewID);
    41.         }
    42.     }
    After doing that the existing objects were not being destroyed, but they were still being duplicated. So I also made a modification to DoInstantiate in NetworkingPeer.cs to check if a viewID exists before Instantiation. Hoping I'm not breaking any functionality I actually need here.

    Code (CSharp):
    1.     internal GameObject DoInstantiate(Hashtable evData, PhotonPlayer photonPlayer, GameObject resourceGameObject)
    2.     {
    3.      
    4.         // some values always present:
    5.         string prefabName = (string)evData[(byte)0];
    6.         int serverTime = (int)evData[(byte)6];
    7.         int instantiationId = (int)evData[(byte)7];
    8.  
    9.         // Check if an object with this ViewID already exists - If it does, it is (hopefully) because the player is rejoining a match after a disconnection and already has the objects
    10.         if (PhotonView.Find(instantiationId))
    11.         {
    12.             Debug.Log("PHOTON WITH VIEW ID " + instantiationId + " ALREADY EXISTS - HALTING INSTANTIATION");
    13.             return null;
    14.         }
    It seems to be working exactly as intended. Thanks again!
     
  5. tobiass

    tobiass

    Joined:
    Apr 7, 2009
    Posts:
    3,066
    Ah, right, you need to somehow take care of the duplicate object. I would have destroyed it but it's more elegant to skip creating it for sure.
    Sounds good. Should work.
     
  6. Weendie-Games

    Weendie-Games

    Joined:
    Feb 17, 2015
    Posts:
    75
    Hey @MrConkin did that solution worked for your use case?

    I tried that but now the game won't disconnect players when they do leave room / disconnect..