How does Manual Instantiation work?

Options
I am loading a 3D model through a network, not a prefab. The goal is that a master user can change the position or rotation of the model, while the clients can see the same change.

My loading process is like this. The master user clicks a button to load a model. The button action is synced with the RPC call. The client user calls the same loading function.

After the model is loaded (both master and client), I add PhotonView and PhotonTransformView components to the loaded object dynamically through AddComponent(). The RaiseEvent call is used to change PhotonView ID.

When I load the program, there is an error message: Changing a ViewID while it's in use is not possible.

The error message makes sense. The master and clients create their own local copies of the model. And the ViewID is created when the PhotonView component is added.

So my question is: how to use Manual Instantiation in this case? Or am I chosing the wrong approach in the beginning?
	public void buttonClick()
	{
		photonView.RPC("actionOnClick", RpcTarget.All, fileName);
	}

	[PunRPC]
    public void actionOnClick(string fileName)
    {
        LoadModel(fileName);
    }

    private void OnLoad()
    {
        Debug.Log("Model loaded.");
        myModel = Loader.LoadedGameObject;
        myModel.SetActive(true);
        myModel.transform.localPosition = ModelAnchor.position;

        PhotonView myPUNView = myModel.AddComponent<PhotonView>();
        PhotonTransformView myPUNTrans = myModel.AddComponent<PhotonTransformView>();
        myPUNView.observableSearch = PhotonView.ObservableSearch.AutoFindAll;
        myPUNView.OwnershipTransfer = OwnershipOption.Takeover;
        myPUNTrans.m_SynchronizeScale = true;

        if (PhotonNetwork.AllocateViewID(myPUNView))
        {
            Debug.Log("Create gameobj over network " + myPUNView.ViewID);
            object[] data = new object[]
            {
            myModel.transform.position, myModel.transform.rotation, myPUNView.ViewID
            };

            RaiseEventOptions raiseEventOptions = new RaiseEventOptions
            {
                Receivers = ReceiverGroup.Others,
                CachingOption = EventCaching.AddToRoomCache
            };

            SendOptions sendOptions = new SendOptions
            {
                Reliability = true
            };

            PhotonNetwork.RaiseEvent(CustomManualInstantiationEventCode, data, raiseEventOptions, sendOptions);
        }
        else
        {
            Debug.LogError("Failed to allocate a ViewId.");

            Destroy(myModel);
        }
        //myModel.AddComponent<DrawLine>();
    }

    public void OnEvent(EventData photonEvent)
    {

        if (photonEvent.Code == CustomManualInstantiationEventCode)
        {
            object[] data = (object[])photonEvent.CustomData;
            Debug.Log("OnEvent Triggered "+ (int)data[2]);
            myModel.transform.position = (Vector3)data[0];
            myModel.transform.rotation = (Quaternion)data[1];
            PhotonView photonView = myModel.GetComponent<PhotonView>();
            photonView.ViewID = (int)data[2];
        }
    }

Comments

  • JohnTube
    JohnTube ✭✭✭✭✭
    Options
    Hi @ttkrpink,

    Thank you for choosing Photon!

    As you can see on the documentation page here, the snipper shows that you instantiate prefab containing the PhotonView only when manual instantiation event is received.
    Or add the PhotonView component then instead of instantiating the player/avatar/character prefab instance.

    option 1:
    public void OnEvent(EventData photonEvent)
        {
    
            if (photonEvent.Code == CustomManualInstantiationEventCode)
            {
                object[] data = (object[])photonEvent.CustomData;
                Debug.Log("OnEvent Triggered "+ (int)data[2]);
                myModel = LoadOrInstantiateModelNow(); // replace with your own code, you can also make it async and move code after into callback when loading is done
                myModel.transform.position = (Vector3)data[0];
                myModel.transform.rotation = (Quaternion)data[1];
                PhotonView photonView = myModel.GetComponent<PhotonView>();
                photonView.ViewID = (int)data[2];
            }
        }
    

    option 2:
    public void OnEvent(EventData photonEvent)
        {
    
            if (photonEvent.Code == CustomManualInstantiationEventCode)
            {
                object[] data = (object[])photonEvent.CustomData;
                Debug.Log("OnEvent Triggered "+ (int)data[2]);
                myModel.transform.position = (Vector3)data[0];
                myModel.transform.rotation = (Quaternion)data[1];
                PhotonView photonView = myModel.AddComponent<PhotonView>(); // add PhotonView only now
                photonView.ViewID = (int)data[2];
            }
        }