In about every game you need to instantiate one or more objects per player. For objects that should synchornize in a networked game, you need to use a special workflow.
PUN can automatically take care of spawning a networked object by passing a starting position, rotation and a prefab name to the
Requirement: The prefab should be available directly under "Resources" folder (to load it at runtime) and it must have a
Watch out with web players: everything in the resources folder will be streamed at the very first scene per default. Under the web player settings you can specify the first level that uses assets from the resources folder by using the "First streamed level". If you set this to your first game scene, your preloader and main menu will not be slowed down if they don't use the Resources folder assets.
When you need to setup new GameObjects when they got instantiated, you can implement
OnPhotonInstantiate(PhotonMessageInfo info) in a script on them.
It's being called with the info who triggered the instantiation. You can setup the GameObject as a player's Tag object, for example:
Lifetime of Networked Objects
GameObjects created with
PhotonNetwork.Instantiate will usually exist as long as you are in the same room.
When you swap rooms, objects don't carry over, just like when you switch a scene in Unity.
Whan a client leaves a room, all others destroy the GameObjects owned/created by that player.
If this doesn't fit your game logic, you can skip this step. Set
PhotonNetwork.autoCleanUpPlayerObjects to false for your game.
Alternatively, the Master Client can create GameObjects that have the lifetime of the room by using
The object is not associated with the Master Client but the room.
By default, the Master Client controls these objects but you can pass on control with
Check out the Demo for Ownership Transfer
Networked Scene Objects
It is perfectly fine to place PhotonViews on objects in a scene. They will be controlled by the Master Client by default and can be useful to have a "neutral" object to send room-related RPCs.
Important: When you load a scene with networked objects before being in a room, some PhotonView values are not useful yet.
For example: You can't check
isMine in Awake() when you're not in a room!
When you load a scene, Unity usually destroys all GameObjects currently in the hierarchy. This includes networked objects, which can be confusing at times.
Example: In a menu scene, you join a room and load another. You might actually arrive in the room a bit too early and get the initial messages of the room. PUN begins to instantiate networked objects but your logic loads another scene and they are gone.
To avoid issues with loading scenes, you can set
PhotonNetwork.automaticallySyncScene to true and use
PhotonNetwork.LoadLevel() to switch scenes.
If you don't want to rely on the Resources folders to instantiate objects over the network you'll have to manually instantiate them as shown in the example at the end of this section.
The main reason for wanting to instantiate manually is gaining control over what is downloaded when for streaming web players. The details about streaming and the resources folder in Unity can be found here.
You can send RPCs to instantiate objects. Of course you need some way to tell the remote clients which object to instantiate. You can't just send a reference to a GameObject, so you need to come up with a name or something for it.
As important as the type of object, is a network id for it.
PhotonView.viewID is the key to routing network messages to the correct gameobject/scripts.
If you spawn manually, you have to allocate a new viewID using
PhotonNetwork.AllocateViewID() and send it along.
Everyone in the room has to set the same ID on the new object.
Keep in mind that an RPC for instantiation needs to be buffered: Clients that connect later have to receive the spawn instructions as well.
If you want to use asset bundles to load your network objects, all you have to do is to add your own asset bundle loading code and replace the
playerPrefab from the example with the prefab from your asset bundle.