Resetting a PhotonView ID without destroying it?

Options
When starting the game, the player object with a PhotonView component is created in offline mode(I spawn everything manually). When going online I get the duplicate view id error, which makes sense because both player objects have an id of 1001.

So my question is, is it possible to reset the view id on my PhotonView when connecting, without having to destroy and respawn the entire object? The reason I'd rather not do this is because it's a VR game and the camera rig is persistent.

Best Answer

  • JD1337
    JD1337
    Answer ✓
    Options
    After messing around with Photon for the past week I was able to resolve my issue using manual instantiation and some hacky modifications to Photon.

    Here's how I did it:
    • Go into offline mode
    • Spawn your player avatar normally using UnityEngine.Object.Instantiate
    • Connect to room
    • When connected call this:
      public override void OnJoinedRoom()
          {
              PhotonNetwork.LocalCleanPhotonView(photonView);
              photonView.ViewID = PhotonNetwork.AllocateViewID(PhotonNetwork.LocalPlayer.ActorNumber);
              PhotonNetwork.RegisterPhotonView(photonView);
              photonView.TransferOwnership(PhotonNetwork.LocalPlayer);
      
              object[] data = new object[]
              {
                  transform.position,
                  transform.rotation,
                  photonView.ViewID
              };
      
              RaiseEventOptions raiseEventOptions = new RaiseEventOptions
              {
                  Receivers = ReceiverGroup.Others,
                  CachingOption = EventCaching.AddToRoomCache
              };
      
              SendOptions sendOptions = new SendOptions
              {
                  Reliability = true
              };
      
              PhotonNetwork.RaiseEvent(NetworkService.CustomManualInstantiationCode, data, raiseEventOptions, sendOptions);
          }
      
    • Subsribe the following event to OnPhotonEventReceived callback:
      public void OnPhotonEventReceivedEvent(EventData photonEvent)
          {
              if (photonEvent.Code == CustomManualInstantiationCode)
              {
                  object[] data = (object[])photonEvent.CustomData;
                  GameObject player = UnityEngine.Object.Instantiate(Resources.Load("Remote Player"), (Vector3)data[0], (Quaternion)data[1]) as GameObject;
                  PhotonView photonView = player.GetComponent<PhotonView>();
                  photonView.ViewID = (int)data[2];
                  photonView.TransferOwnership(photonEvent.Sender);
              }
          }
      
    • In PhotonNetworkPart.RegisterPhotonView(PhotonView netView)
      Remove or comment the RemoveInstantiatedGO() and add LocalCleanPhotonView where it throws the duplicate found debug
    And it should work. There may be some more stuff that I changed that I forgot to post but this should be most of it to get it to work.

    This also allows for spawning different prefabs for local and remote players, which in turn allows for using abstract code for local and remote components removing the need for the ugly if(photonView.isMine) statements.

Answers

  • KubaisSVK
    Options
    hi @JD1337, just a little research before asking, have you read this ? https://forum.photonengine.com/discussion/13926/photonview-id-resetting
  • JD1337
    Options
    Thanks for your response, @KubaisSVK but that post seems to be about editor issues whereas I'm having trouble in runtime.
  • JohnTube
    JohnTube ✭✭✭✭✭
    Options
    Hi @JD1337,

    Good question.
    I think it's possible (didn't test it myself).

    pointers:

    - use manual instantiation all the way to control ViewIDs: use PUN's API to allocate those and sync them over the network: AllocateViewID and AllocateSceneViewID.
    - complex/advanced: custom prefab pool? that preloads GameObject w/ PhotonView and do not destroy GameObject w/ PhotonView but reassign them?

    By the way, this is not exactly the same thing as the rejoin issue here.
  • JD1337
    JD1337
    Answer ✓
    Options
    After messing around with Photon for the past week I was able to resolve my issue using manual instantiation and some hacky modifications to Photon.

    Here's how I did it:
    • Go into offline mode
    • Spawn your player avatar normally using UnityEngine.Object.Instantiate
    • Connect to room
    • When connected call this:
      public override void OnJoinedRoom()
          {
              PhotonNetwork.LocalCleanPhotonView(photonView);
              photonView.ViewID = PhotonNetwork.AllocateViewID(PhotonNetwork.LocalPlayer.ActorNumber);
              PhotonNetwork.RegisterPhotonView(photonView);
              photonView.TransferOwnership(PhotonNetwork.LocalPlayer);
      
              object[] data = new object[]
              {
                  transform.position,
                  transform.rotation,
                  photonView.ViewID
              };
      
              RaiseEventOptions raiseEventOptions = new RaiseEventOptions
              {
                  Receivers = ReceiverGroup.Others,
                  CachingOption = EventCaching.AddToRoomCache
              };
      
              SendOptions sendOptions = new SendOptions
              {
                  Reliability = true
              };
      
              PhotonNetwork.RaiseEvent(NetworkService.CustomManualInstantiationCode, data, raiseEventOptions, sendOptions);
          }
      
    • Subsribe the following event to OnPhotonEventReceived callback:
      public void OnPhotonEventReceivedEvent(EventData photonEvent)
          {
              if (photonEvent.Code == CustomManualInstantiationCode)
              {
                  object[] data = (object[])photonEvent.CustomData;
                  GameObject player = UnityEngine.Object.Instantiate(Resources.Load("Remote Player"), (Vector3)data[0], (Quaternion)data[1]) as GameObject;
                  PhotonView photonView = player.GetComponent<PhotonView>();
                  photonView.ViewID = (int)data[2];
                  photonView.TransferOwnership(photonEvent.Sender);
              }
          }
      
    • In PhotonNetworkPart.RegisterPhotonView(PhotonView netView)
      Remove or comment the RemoveInstantiatedGO() and add LocalCleanPhotonView where it throws the duplicate found debug
    And it should work. There may be some more stuff that I changed that I forgot to post but this should be most of it to get it to work.

    This also allows for spawning different prefabs for local and remote players, which in turn allows for using abstract code for local and remote components removing the need for the ugly if(photonView.isMine) statements.