In Unity, you typically create a new game object using the
Instantiate function. Creating a game object with
Instantiate will only create that object on the local machine.
Spawning in Netcode for GameObjects (Netcode) means to instantiate and/or spawn the object that is synchronized between all clients by the server.
A network Prefab is any unity Prefab asset that has one
NetworkObject component attached to a
GameObject within the prefab. More commonly, the
NetworkObject component is attached to the root
GameObject of the Prefab asset because this allows any child
GameObject to have
NetworkBehaviour components automatically assigned to the
NetworkObject. The reason for this is that a
NetworkObject component attached to a
GameObject will be assigned (associated with) any
NetworkBehaviour components on:
- the same
NetworkObjectcomponent is attached to
- any child or children of the
NetworkObjectis attached to.
A caveat of the above two rules is when one of the children
GameObjects also has a
NetworkObject component assigned to it (a.k.a. "Nested NetworkObjects"). Because nested
NetworkObject components aren't permited in network prefabs, Netcode for GameObjects won'tify you in the editor if you are trying to add more than one
NetworkObject to a Prefab and won't allow you to do this.
NetworkBehaviour is assigned to a
NetworkObject.NetworkObjectId is used to help determine which
NetworkBehaviour component instance will receive an update to a
NetworkVariable or where to invoke an RPC. A
NetworkObject component can have one or more
NetworkBehaviour components assigned to it.
#Registering a Network Prefab
One of the requirements to be able to spawn a network Prefab instance is that it must be registered with the
NetworkManager via the "Network Prefabs" property list.
The two steps to registering a network Prefab with
- Create a network Prefab by creating a Prefab with a
NetworkObjectcomponent attached to the root
- Add your network Prefab to the Network Prefabs list poperty of the
#Spawning a Network Prefab (Overview)
Netcode uses a server authorative networking model so spawning netcode objects can only be done on a server or host. To spawn a network prefab, you must first create an instance of the network Prefab and then invoke the spawn method on the
NetworkObject component of the instance you created.
In most cases, you will want to keep the
NetworkObject component attached to the root
GameObject of the network prefab.
By default a newly spawned network Prefab instance is owned by the server unless otherwise specified.
See Ownership for more information.
The following is a basic example of how to spawn a network Prefab instance (with the default server ownership):
NetworkObject.Spawn method takes 1 optional parameter that defaults to
When you set the destroyWithScene property to
false it will be treated the same as when you set Object.DontDestroyOnLoad. Typically, you use this if you are loading a scene using LoadSceneMode.Single parameter.
Learn more about Netcode Scene Management here
#Destroying / Despawning
By default, a spawned network Prefab instance that is destroyed on the server/host will be automatically destroyed on all clients.
When a client disconnects, all network Prefab instances created during the network session will be destroyed on the client-side by default. If you don't want that to happen, set the
DontDestroyWithOwner field on
NetworkObject to true before despawning.
To do this at runtime:
To make this the default from the editor insepctor view:
As an alternative way, you can make the
NetworkObject.DontDestroyWithOwner property default to
true by setting it on the
NetworkObject itself like in the above screenshot.
Only a server can despawn a
NetworkObject, and the default despawn behavior is to destroy the associated GameObject. to despawn but not destroy a
NetworkObject, you should call
NetworkObject.Despawn and pass false as the parameter. Clients will always be notified and will mirror the despawn behavior. If you despawn and destroy on the server then all clients will despawn and then destroy the
GameObject that the
NetworkObjet component is attached to.
On the client side, you should never call
Object.Destroy on any
GameObject with a
NetworkObject component attached to it (this isn't supported and will cause an exception to be thrown). If you want to use a more client authority model, have the client with ownership invoke a ServerRpc to defer the despawning on server side.
The only way to despawn
NetworkObject for a specific client is to use
See: Object Visibility for more information on this.
If you have
GameObject children, with
NetworkBehaviour components attached, of a parent
GameObject, with a
NetworkObject component attached, you can't disable the
GameObject children before spawning or despawning. Doing so, in v1.0.0, can cause unexpected results and it's recommended to make sure all children are enabled in the hierarchy before spawning or despawning.
#Dynamically Spawned Network Prefabs
Netcode for GameObjects uses the term "dynamically spawned" to convey that the
NetworkObject is being spawned via user specific code. Whereas a player or in-scene placed
NetworkObject (with scene management enabled) is typically spawned by Netcode for GameObjects. There are several ways to spawn a network Prefab via code:
#Dynamic Spawning (non-pooled):
This type of dynamically spawned
NetworkObject typically is a simple wrapper class that holds a reference to the Prefab asset. In the example below, the
NonPooledDynamicSpawner.PrefabToSpawn property holds a reference to the network prefab:
Consumable and/or items that can be picked up by a player or NPC(that is, a weapon, health, potion, etc.) would be some examples of when you might want to use non-pooled dynamically spawned
While the NonPooledDynamicSpawner example is one of the simplest ways to spawn a NetworkObject, there is a memory allocation cost associated with instantiating and destroying the GameObject and all attached components. This design pattern can sometimes be all you need for the netcode game asset you are working with, and other times you might want to respawn/re-use the object instance. When performance is a concern and you want to spawn more than just one
NetworkObject during the lifetime of the spawner or want to repeatedly respawn a single
NetworkObject, the less proccessor and memory allocation intensive technique is to use pooled dynamic spawning.
Really, the when we use the term "non-pooled" more often than not we are referring to the concept that a
GameObject will be instantiated on both the server and the clients each time an instance is spawned.
#Pooled Dynamic Spawning
Pooled dynamic spawning is when netcode objects (
GameObject with one
NetworkObject component) aren't destroyed on the server or the client when despawned. Instead, specific components are just disabled (or the
GameObject itself) when a netcode object is despawned. A pooled dynamically spawned netcode object is typically instantiated during an already memory allocation heavy period of time (like when a scene is loaded or even at the start of your application before even establishing a network connection). Pooled dynamically spawned netcode objects are more commonly thought of as more than one netcode object that can be re-used without incurring the memory allocation and initialization costs. However, you might also run into scenarios where you need just one dynamically spawned netcode object to be treated like a pooled dynmically spawned netcode object.
Fortunately, Netcode for GameObjects provides you with a way to be in control over the instatiation and destruction process for one or many netcode objects by via the
INetworkPrefabInstanceHandler interface. Any
INetworkPrefabInstanceHandlerimplementation should be registered with the
NetworkPrefabHandler(for multiple netcode objects see Object Pooling) to accomplish this.
The easiest way to not destroy a network Prefab instance is to have something, other than the instance itself, keeping a reference to the instance. This way you can simply set the root
GameObject to be inactive when it's despawned while still being able to set it active when the same network Prefab type needs to be respawned. Below is one example of how you can accomplish this for a single netcode object instance:
You might run across a situation where you still want other components on the root
GameObject of your network Prefab instance to remain active. Primarily, you want to be able to easily disable the components that would normally be active when the netcode object is considered spawned.
Below is an example of what a non-pooled friendly Prefab might look like:
The issues you might run into with the above Prefab hierarchy is that everything is on a single
GameObject, and as such if you wanted to disable the
MeshRenderer and the
NetworkObjectLabel, one of our classes in the Netcode for GameObjects test project, you would need to get those component types before disabling them (that is, during
OnNetworkSpawn or get them when
OnNetworkDespawn is invoked).
To reduce this level of complexity, a more "pooled dynamic spawning" friendly Prefab heirarchy might look like this:
NetworkObject sits at the root
GameObject of the network prefab. The child
GameObject, SpawnedComponents, then has everything that you might want to have disabled when the network Prefab instance isn't spawned:
This reduces the complexity down to setting the SpawnedComponents
GameObject to inactive, which will also disable all of the components attached to it.
Using this type of a hierarchical separation is useful in many ways (especially when you have a much more complex prefab). For more complex prefabs, you can further expand this pattern into specific categories (that is, visuals, physics, sound, etc) which will provide you with a more macrocosmic way to control enabling or disabling many different components without having to have references to all of them.
Any objects in the scene with active and spawned
NetworkObject components will get automatically replicated by Netcode. There is no need to manually spawn them when scene management is enabled in the
NetworkManager. In-scene placed
NetworkObjects should typically be used like a "static" netcode object, where the netcode object is typically spawned upon the scene being loaded on the server-side and synchronized with clients once they finish loading the same scene.
Learn more about In-Scene Placed
Generally, there are two modes that define how an in-scene placed
NetworkObject is synchronized.
- Soft Synchronization (Scene Management enabled)
- Prefab Synchronization (Scene Management disabled)
SoftSync or "Soft Synchronization" is a term you might run across if you run into any issue with in-scene placed
NetworkObjects. Soft synchronization only occurs if scene management is enabled in the
NetworkManager properties. If you receive a "soft synchronization error", then this typically means that a client can't locate the same in-scene placed
NetworkObject after loading a scene.
The benefit of using scene management is that you don't have to register every in-scene placed
NetworkObject with the
NetworkManager as a network prefab, and it handles synchronizing clients to your current game state.
PrefabSync or "Prefab Synchronization" is used if scene management is disabled in the
NetworkManager. With Prefab synchronization, every in-scene placed
NetworkObject has to be a network Prefab and must be registered with
NetworkPrefabs list. When a client starts, Netcode will destroy all existing in-scene placed
NetworkObjects and spawn its corresponding Prefab from the
NetworkPrefabs list instead. This also means that you will have to implement your own scene manager and handle how you synchronize clients when they join a network session.
PrefabSync is ONLY recommended for advanced development and/or multi project setups.