OnSerializeView sets new value but then reverts it back to previous value

Options
Hi, this is driving me crazy so hope you can help me out. I have a method that is setting an object's boolean parameter (isOnOven) to false. This value is then supposed to be synchronized across all clients through the OnSerializeView callback. Notice that before setting the isOnOven parameter I m requesting object's ownership for the current client. The behaviour I am experiencing is the following: once the parameter assignment happens, it remains set to false for a second's fraction, and then it revert back to true (default value). The worst part is that this happens inconsistently: sometimes it goes as described, sometimes it works as expected.

I thought this had to do with the request ownership not being finished when I set the property to false. Therefore I implemented a simple coroutine that waits until the request ownership is done before setting the value to false. However this did not fix the weird behavior. I m attaching the relevant code below.

This is the method where the request ownership is called.
void PickUpCube()
    {
     
            if (Input.GetMouseButtonDown(0) && !isHolding)
            {
            
                if (Physics.Raycast(transform.position, transform.forward, out hit, range))
                {
                    if (hit.transform.tag == "block" )
                    {
                        //do not pick up if it's env or towerblock
                        if (!hit.transform.gameObject.GetComponent<Block>().isEnvironmentBlock && !hit.transform.gameObject.GetComponent<Block>().isTowerBlock)
                        {
                            block = hit.transform.gameObject.GetComponent<Block>();
                            isHolding = true;

                            block.RequestBlockOwnership();
                            StartCoroutine(nameof(WaitForOwnershipTransferred), block.GetComponent<PhotonView>().ViewID);
                            
                            if (block.foundationsBlock != null) {

                                block.foundationsBlock.RequestBlockOwnership();
                                //WaitForOwnershipTransferred(block.foundationsBlock.GetComponent<PhotonView>().ViewID);
                                block.foundationsBlock.SetIsAlreadyOccupied(false); 
                        
                            };
                    } 
               
                }
            }

        }

    }

This is the coroutine where I wait for the ownership transfer to be completed and then assign the value:
IEnumerator WaitForOwnershipTransferred(int photonViewID)
    {
        float timeSpentChecking = 0f;

        while (timeSpentChecking < 1f)
        {

            if (PhotonView.Find(photonViewID).IsMine)
            {
                Debug.Log("I can confirm the OWNERSHIP TRANSFEEEEEER");
                yield return new WaitForSeconds(.1f);
                block.isOnOven = false;
                timeSpentChecking = 0f;
                break;

            } else
            {
                Debug.Log("Ownership not transferred");
                timeSpentChecking += waitTimeforOwnershipTransfer;
                yield return new WaitForSeconds(.1f);

            }

        }

    }
This is the field serialization for the block object.
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        if (stream.IsWriting)
        {
   
            stream.SendNext(isTransformationBlock);
            stream.SendNext(isColorTransformationBlock);
            stream.SendNext(isEnvironmentBlock);
            stream.SendNext(isTowerBlock);
            stream.SendNext(isOnOven);
            stream.SendNext(isCooked);
            stream.SendNext(cookingState);
            stream.SendNext(isAlreadyOccupied);

        }
        else
        {
            isTransformationBlock = (bool)stream.ReceiveNext();
            isColorTransformationBlock = (bool)stream.ReceiveNext();
            isEnvironmentBlock = (bool)stream.ReceiveNext();
            isTowerBlock = (bool)stream.ReceiveNext();
            isOnOven = (bool)stream.ReceiveNext();
            isCooked = (bool)stream.ReceiveNext();
            cookingState = (float)stream.ReceiveNext();
            isAlreadyOccupied = (bool)stream.ReceiveNext();
        }
    }

And finally this is where I implemented the request ownership method. Notice that the object's transfer value is set to Takeover.
public void RequestBlockOwnership()
    {
        Debug.Log("the gameobj to transfer is " + gameObject);
        Debug.Log("the photon view on the gameobj is" + gameObject.GetComponent<PhotonView>());
        gameObject.GetComponent<PhotonView>().RequestOwnership();

    }

Any thoughts?


Answers

  • did you implement the ownership transfer callbacks correctly on the class in question that you are going to transfer ownership via???

    https://doc.photonengine.com/zh-cn/pun/current/gameplay/ownershipandcontrol
    Ownership Change Callback
    Whenever the owner of a PhotonView changes, IOnPhotonViewOwnerChange.OnOwnerChange(Player newOwner, Player previousOwner) is fired on classes that implement it and that are registered by the same respective PhotonView.
    
    Classes implementing IOnPhotonViewOwnerChange interface need to be registered using PhotonView.AddCallbackTarget and deregistered using PhotonView.RemoveCallbackTarget.
    
    Back To Top
    
    Explicit Ownership Transfer Callbacks
    There are two ownership changes callbacks in the same IPunOwnershipCallbacks interface:
    
    OnOwnershipRequest(PhotonView targetView, Player requestingPlayer) when someone requests ownership from the targetView.
    OnOwnershipTransfered(PhotonView targetView, Player previousOwner) whenever the owner changes for the targetView.
    Classes implementing IPunOwnershipCallbacks interface need to be registered using PhotonNetwork.AddCallbackTarget and deregistered using PhotonNetwork.RemoveCallbackTarget.
    
    Back To Top
    
    Control Change Callback
    Whenever the controller of a PhotonView changes, IOnPhotonViewControllerChange.OnControllerChange(Player newController, Player newController) is fired on classes that implement it and that are registered by the same respective PhotonView.
    
    Classes implementing IOnPhotonViewControllerChange interface need to be registered using PhotonView.AddCallbackTarget and deregistered using PhotonView.RemoveCallbackTarget.