Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Third Party RequestOwnership of hierarchy of PhotonViews?

Discussion in 'Multiplayer' started by Olipool, Aug 12, 2020.

  1. Olipool

    Olipool

    Joined:
    Feb 8, 2015
    Posts:
    320
    Hi all,

    I am making a game where players can grab objects, carry them around, and put them back on the table for example. this is working fine so far, I request ownership, parent the object to the player, and the PhotonView in syncing the movement to everyone.

    Now I have hierarchical objects for example a safe and the safe contains three valuable coins. Those can be grabbed once the safe is open, too. So they need a PhotonView as well. So if one player picks up the safe, the position of it and the coins get synced. Fine.

    But since the safe and coins send individual updates they arrive at slightly different times and with fast movements the coins may even step outside the safe for a moment. So I thought, why not just send the safe update, disable the child Views, and let the parent (safe) move the children (coins) at the client. This would look better and also save unnecessary updates.

    Sadly if someone who requests ownership of the safe and the coins, which are four requests in total, something goes wrong and the coins may end up in the air above the save. I tried to figure out what happens when exactly but with all updates and lag I can only guess, that the grabbing player starts sending position updates for the safe and the original owner just received one of the ownership requests e.g. the safe but not for the coins yet etc.

    Long story short: how can I handle this situation best? I wanted to try to send only an ownership request for the parent and the receiving owner would transfer his ownership for the children in one step but the code for this internal events seems to be in a dll.

    One solution I can think about is to deactivate all PhotonViews (or PhotonTransformView to be precise) on child objects that have a PhotonView on the parent at the start of the game and activate them if a child gets grabbed by a player and unparent it so it becomes a self-contained object.

    Thanks for reading so far and for any advice
     
  2. Olipool

    Olipool

    Joined:
    Feb 8, 2015
    Posts:
    320
    After a lot of debugging and sleepless nights :D I was able to track down the source of the problem why some child objects like coins jump out of a parent object like a chest.

    The first revelation is that disabled TransformViews are still serialized over the net, I don't know if this is a mistake because the Update() where the objects are moved is not called for those disabled components.

    The second and most important revelation - and this is so very clear that I did not think about it - the order of position updates is not always the same e.g. they don't care about the hierarchy at all. So if you send the update for the chest to client A, the chest gets moved and takes the coins with it because of the parenting. When the updates of the coins arrive, they are already more or less in place. That works well.
    BUT: if the update for the child arrives first then the child/coin gets moved to the target and - now out of the chest - after that, the parent gets moved to the target but because of the parenting the child/coin gets moved another time and by that stays outside the chest.

    This shouldn't be a problem if the child TransformViews stay enabled because there is a continuous adjustment but it is really not necessary, that is why I wanted to deactivate them. And it SHOULD work because the position of the disabled TransformViews only gets set in Update() which is not running, but there is a flag if an object is moving for the first time (after enabling it) and in that case, the position gets set directly in OnSerializeView.

    I don't know if this is intentional but it sounds like "bad" design, because the serialization method should just do one thing and Update() should do the movement, but there may be reasons. Now the serialization produces a side effect under certain conditions and may move the object.

    Anyway, my solution right now is to disable every child TransformView if one of the parents also has a TransformView and as the first line in the OnSerializeView I added: if (!enabled) return;
    This has two advantages like mentioned before, you may save a lot of bandwidth for example if you carry a chest with 100 single coins in it and it also looks much better because the child positions are set deterministically on every client through parenting and are not "wobbling" around because of interpolation and different lag for different coins.

    If you should see any disadvantage to this please let me know! One could even put this if (!enabled) test one level higher and don't even call OnSerializeView in disabled components.
     
  3. tobiass

    tobiass

    Joined:
    Apr 7, 2009
    Posts:
    3,062
    Sorry, I overlooked the post last week. Thanks for updating it!

    Inactive PhotonViews should not sync. I remember that some older PUN versions did this but PUN 2 has a check and skips the syncing code if view.isActiveAndEnabled == false.

    Which version of PUN do you use? Try the latest PUN 2. It also has a few changes that improve working with hierarchies and more.

    What OnPhotonSerializeView does, is up to customization. The PhotonTransformView is not a comprehensive solution for everything but a startingpoint for synchronization as needed for your game.

    I think your way to do it is right and sounds good.
    Syncing hundreds of coins individually (if not in a chest), is probably not a scalable idea though. But I see you're careful, so .. it may work in your game.
     
  4. Olipool

    Olipool

    Joined:
    Feb 8, 2015
    Posts:
    320
    Thanks for the info, it doesn't occur to me somehow that I could disable the PhotonView since it has no checkbox for that in the inspector. Anyway, this would not always work for me, as an example, I have a padlock in the game with three wheels where the player can set a combination of numbers. I, therefore, call an RPC "Interact" on every wheel so even when they are children they need an active PhotonView.
    I could check if the View also has a TransformView etc. but I have the gut feeling this gets messy quickly.

    But good to know that the TransformView is meant as a starting point I can play around with and don't have to fear to break something ;)
     
  5. tobiass

    tobiass

    Joined:
    Apr 7, 2009
    Posts:
    3,062
    Yes, this is because the script does not have a Update() method. Then Unity does not show the checkbox but the script can still be disabled.

    There is only a limited number of viewIDs. Networking wise it would be leaner to have a PV on the padlock but not on the wheels. If either wheel gets set, call the RPC to send the new number. The receiver can apply this to the wheels easily.
    The wheels should definitely not have PhotonTransformView scripts.
     
  6. Olipool

    Olipool

    Joined:
    Feb 8, 2015
    Posts:
    320
    Thanks for the clarification about the checkbox.

    And yes, the wheels don't have transform views and the reason I have PV on them is that the game was a singleplayer game, and the interactions were caught by the wheels. Also, the padlocks are modular and can contain any number of wheels so I put the "wheel logic" on those objects.
    Of course, I could change it and redirect the click event up to the parent, etc. but that would mean refactoring, testing etc.

    I will keep this in mind for the next time, but right now I only have about 100-120 PV in total, most of them as pure RPC receivers and maybe 30 with transform views that only sync data when the player inspects them (he can rotate them around), carrying them around is solved with parenting on all clients.

    Thanks again!