Search Unity

Third Party [Photon] PhotonView TransferOwnership, but forever (destroy on Client quit)

Discussion in 'Multiplayer' started by Baroni, May 24, 2016.

  1. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    Hello Photonians,

    I'm kind of running into an issue with the TransformOwnership method on a PhotonView.

    Code (csharp):
    1.  
    2.     /// <summary>
    3.     /// Transfers the ownership of this PhotonView (and GameObject) to another player.
    4.     /// </summary>
    5.     /// <remarks>
    6.     /// The owner/controller of a PhotonView is also the client which sends position updates of the GameObject.
    7.     /// </remarks>
    8.     public void TransferOwnership(PhotonPlayer newOwner)
    9.     {
    10.         this.TransferOwnership(newOwner.ID);
    11.     }
    12.  

    The problem with that is, that I have to set the OwnershipOption from 'Fixed' to 'Takeover' or 'Request' for it to work. Fixed means that the network object will get destroyed when the owner leaves - so there is no ownership transfer. The other two options mean that the (new) master will be the new owner (and previous client networked objects won't get destroyed).

    My scenario: after the master client instantiated a networked object, I would like to transfer its ownership to another client forever - so the master is only responsible for the instantiation, but does not get the ownership back at any time, and the networked object gets destroyed when the client leaves. I can't see how that is possible with PUN.
    - First I've tried using the OwnershipOption to 'Takeover' in the editor and changing it back to 'Fixed' at runtime after transferring ownership, however the master will be the new owner regardless and client objects won't get destroyed once it leaves.
    - Also I've tried setting the OwnershipOption to 'Takeover' and destroying client owned objects in the OnPhotonPlayerDisconnected callback manually, but the issue here is that once that callback gets called, the networked objects are transferred to the master already and there are no networked objects on that leaving client anymore.

    How would I go about instantiating networked objects on the master, then transferring it to a client and leaving it there?
     
  2. tobiass

    tobiass

    Joined:
    Apr 7, 2009
    Posts:
    3,070
    This is a bit more complex:
    Instantiations usually get cleaned up when the creator of it leaves. The server buffers an "instantiate" event and buffered events get cleaned up (by default) when the sender of the event leaves. This only affects players who join later on (who get buffered events on join), however.
    When someone leaves, the remaining active clients get an event about that. This is used to clean up objects (via the PhotonViews). Currently, this also cleans up the objects created by that leaving player. So it's not about current ownership.

    If you need to avoid objects getting destroyed when a player leaves, the Master Client can instantiate the object by InstantiateSceneObject(). This defines "no one" as creator. You can interpret this as: the object got created by/for the room.


    In PUN, someone always is the owner. The Master Client takes over control over all objects that don't have an active owner. This is just a rule by PUN, to keep things simple. It clashes with your plan, it seems.
    But: Even if PUN says that the Master Client is in control, the owner's ID for the object should be set after an ownership transfer. So you should still be able to check if the Master Client is actually the owner or just in control (because the owner is not in the room anymore). Use PhotonView.isOwnerActive for example.

    With that knowledge, you could ignore objects that are not explicitly owned by the Master Client. They don't have to send updates then.

    You can also let the Master Client go through all instantiated objects and call Destroy() for each that must be removed due to a leaving player.


    If you don't move the instantiation of objects to the Master Client, things would be easier.
    I don't see the benefit of that process.
     
    nabergh, gareth_untether and Baroni like this.
  3. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    Thank you for your reply Tobias, I knew you were somewhere around here :)

    Unfortunately that doesn't work. With OwnershipTransfer set to Takeover, after a client (the old owner) leaves the owner is transferred back to the master immediately so on the master, isOwnerActive returns true on the PhotonView of the leaving client.

    From the debug log:
    Code (csharp):
    1. Player1 owner: 'Player1' (master), creatorActorId: 1, OwnerActorNr: 1, isOwnerActive: True, isMine: True
    2. Player2 owner: 'Player2' , creatorActorId: 1, OwnerActorNr: 2, isOwnerActive: True, isMine: False
    3. OnPlayerDisconnected: 'Player2'
    4. Player1 owner: 'Player1' (master), creatorActorId: 1, OwnerActorNr: 1, isOwnerActive: True, isMine: True
    5. Player2 owner: 'Player1' (master), creatorActorId: 1, OwnerActorNr: 1, isOwnerActive: True, isMine: True
    I can't do that either (in OnPhotonPlayerDisconnected), because I can't distinguish between which objects need to be destroyed, as the master is now the owner of all of them (which could accidentally destroy its own player object).

    In our game, the master client should instantiate all player objects, because it has to assign a team, spawn position and max health variable to the player. I would like to have this part fully authoritative, as the other clients should not send these informations by themselves.
     
    Last edited: May 25, 2016
  4. tobiass

    tobiass

    Joined:
    Apr 7, 2009
    Posts:
    3,070
    In NetworkingPeer.DestroyPlayerObjects(), PUN re-assigns the creator of a view as owner, when the current owner leaves. If you comment that out, it should help. Find view.ownerId = view.CreatorActorNr; and comment the whole foreach block.
    I think this is a rare use case, so I would rather ask you to comment this out, than implementing a new option in PUN to skip this step, etc.

    You can assign those values by setting custom properties, if you wanted to. I'm just noting this, because here you work against a system in PUN without getting a clear benefit. If the values are defined, the instantiation itself is just a meaningless step, which can be done by anyone.
    To get this authoriative, consider actually checking who is sending/setting values. Just because it's only the Master Client who can do this now, doesn't mean that hacked clients couldn't send it anyways.
     
    Baroni likes this.
  5. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    Modifying the PUN package does not work out with the idea of selling an Asset Store package, where the user would have to modify his local version too. Also I'm using custom properties already, but you've reminded me of doing something differently so thank you very much for that!
     
  6. tobiass

    tobiass

    Joined:
    Apr 7, 2009
    Posts:
    3,070
    Ah, ok, of course I wasn't aware of the packaging.
    While not a requirement, it would be nice if you send us some info about your package when you're ready. So we're aware of it. Mail us: developer@exitgames.com

    Good to read you have a new idea and can work around your problem :)
     
    Baroni likes this.
  7. NirabhraDas

    NirabhraDas

    Joined:
    Aug 17, 2017
    Posts:
    3
    Hi, I have a similar but opposite problem.

    Scenario:

    The MasterClient Creates room and then creates two PhotonViews.
    A second client(P2) Joins room
    MC transfers one PhotonView to P2.
    P2 Leaves room

    Issue:

    On P2 leaving room, the PhotonView owned by P2 is not destroyed.
    PhotonView Owned by P2 is now owned by MC.
    I'd like to Destroy the PV owned by P2 when P2 leaves the room but cannot find out how

    Note:
    RoomOptions.CleanupCacheOnLeave is set to true
     
  8. tobiass

    tobiass

    Joined:
    Apr 7, 2009
    Posts:
    3,070
    The objects get destroyed when the creator of if leaves. It does not matter who controls the object.
    You can use PhotonNetwork.Destroy, as usual, to get rid of it.