This simple demo is a playground for a PUN feature that can be tricky to grasp. Simply put, Ownership Transfer allows you to pass control of any networked object. This page explains how to use this feature, some background and show which cases are more complex to handle.
The demo allows anyone to instantiate objects. On click, a ownership transfer is requested. The current owner can pass ownership or reject the request. A pointer above each object marks the currently owned (and controlled) GameObjects per client.
In PUN, every object can only be controlled by one client.
When a client instantiates something, it will be the owner of that new object,
PhotonView.isMine is true on that client only and if you use
OnPhotonSerializeView, only this client will write to the PhotonStream.
The others just receive and update accordingly.
If you want to pass control of a GameObject to another client, you will first have to configure the PhotonView.
In the Inspector, you can see the owner of the GameObject (prefabs only have one at runtime).
In the same line, you will find a dropdown which is
Fixed by default.
Other options are
- "Fixed" owner keeps the creator of a GameObject as owner.
- "Takeover" enables any client to take the GameObject from the current owner.
- "Request" asks the current owner to pass it over. This can be rejected.
Select the "OwnershipSphere" to see it is set to
It is used only once in the scene.
This makes it a "scene object" and anyone can take it anytime.
The "OwnershipCube" prefab is set to
Request, so the current owner can pass or reject ownership.
As toggle in this demo, we simply added a button in the top right corner (at runtime).
Request Ownership and Transfer
Both prefabs have a
When a GameObject with PhotonView gets clicked, this script calls
this.photonView.RequestOwnership(); to request ownership - no matter which setting the PhotonView has.
DemoOwnershipGui script is the one that answers requests (for the
When someone requests ownership, this will be called by PUN on the client that is the current owner.
As you can see, the current owner calls
view.TransferOwnership(requestingPlayer.ID) to actually transfer the PhotonView to it's new owner.
When a GameObject's current owner leaves, the Master Client becomes the new owner. The player who created a GameObject has to request ownership to get it back.
Ownership Transfer by itself should be relatively straighforward. Control of GameObjects can be requested and transferred and if the current owner is gone, the Master Client takes over.
As noted above, the GameObject lifetime is not affected when control changes. By default, all GameObjects created by one player will be destroyed when he/she leaves.
RPCs are not bound to the lifetime of the GameObject. If anyone uses RPCs on a GameObject he/she did not instantiate, (buffered) RPCs might still be sent to joining players.
In some cases, this can be ignored but you should be aware of this.
Also, you can clean up those RPCs corresponding to a PhotonView or the player who left.
Take a look at
A player might lose the GameObject he/she is currently controlling. This can be ok or annoying.
As possible workaround, the Master Client can instantiate GameObjects with
This way, the GameObject will stay in the room until the last player leaves.
You can destroy these GameObjects, of course.
And the Master Client can also pass the ownership to the player who should control the GameObject.
Alternatively you can deactivate the automatic cleanup of the Event Buffer for a room by setting
PhotonNetwork.autoCleanUpPlayerObjects to false.
Then Photon will keep all events of players, even when they leave.
Unless you clean up past Instantiate calls and buffered RPCs, the buffer will grow. Long running games (players joining and leaving for a while) will aggregate a lot of buffered events this way and might break (there is no limit for this by Photon).