| 
 | 1 | +# Network prefab handler  | 
 | 2 | + | 
 | 3 | +The network prefab handler system provides advanced control over how network prefabs are instantiated and destroyed during runtime. This allows overriding the default Netcode for GameObjects [object spawning](../basics/object-spawning.md) behavior by implementing custom prefab handlers.  | 
 | 4 | + | 
 | 5 | +The network prefab handler system is accessible from the [NetworkManager](../components/networkmanager.md) as `NetworkManager.PrefabHandler`.  | 
 | 6 | + | 
 | 7 | +## Overview  | 
 | 8 | + | 
 | 9 | +For an overview of the default object spawning behavior, see the [object spawning](../basics/object-spawning.md) page. The default spawning behavior should cover the majority of spawning use cases, however there are scenarios where you may need more control:  | 
 | 10 | + | 
 | 11 | +- **Object pooling**: Reusing objects to reduce memory allocation and initialization costs.  | 
 | 12 | +- **Performance optimization**: Using different prefab variants on different platforms (e.g. using a simpler object for server simulation).  | 
 | 13 | +- **Custom initialization**: Setting up objects with game client specific data or configurations.  | 
 | 14 | +- **Conditional spawning**: Initializing different prefab variants based on runtime conditions.  | 
 | 15 | + | 
 | 16 | +The prefab handler system addresses these needs through a interface-based architecture. The system relies on two key methods, `Instantiate` and `Destroy`. `Instantiate` is called on non-authority clients when an [authority](../terms-concepts/authority.md) spawns a new [NetworkObject](../basics/networkobject.md) that has a registered network prefab handler. `Destroy` is called on all game clients whenever a registered [NetworkObject](../basics/networkobject.md) is destroyed.  | 
 | 17 | + | 
 | 18 | +## Creating a prefab handler  | 
 | 19 | + | 
 | 20 | +Prefab handlers are classes which implement on of the Netcode for GameObjects prefab handler descriptions. There are currently two such descriptions:  | 
 | 21 | + | 
 | 22 | +- **INetworkPrefabInstanceHandler**: This is the simplest interface for custom prefab handlers.  | 
 | 23 | +- **NetworkPrefabInstanceHandlerWithData**: This specialized handler receives custom data from the authority during spawning, enabling dynamic prefab customization.  | 
 | 24 | + | 
 | 25 | +Netcode will use the `Instantiate` and `Destroy` methods in place of default spawn handlers for the `NetworkObject` used during spawning and despawning.  Because the message to instantiate a new `NetworkObject` originates from the [authority](../terms-concepts/authority.md), not all game clients will have the Instantiate method. All non-authority clients will have the instantiate method invoked if the `INetworkPrefabInstanceHandler` implementation is registered with `NetworkPrefabHandler` (`NetworkManager.PrefabHandler`) and the authority spawns the registered/associated `NetworkObject`.  | 
 | 26 | + | 
 | 27 | +### INetworkPrefabInstanceHandler  | 
 | 28 | + | 
 | 29 | +This is the simplest prefab handler description. Use the `INetworkPrefabInstanceHandler` for situations where the prefab override behaviour is consistent and known.  | 
 | 30 | + | 
 | 31 | +```csharp  | 
 | 32 | +    public interface INetworkPrefabInstanceHandler  | 
 | 33 | +    {  | 
 | 34 | +        NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation);  | 
 | 35 | +        void Destroy(NetworkObject networkObject);  | 
 | 36 | +    }  | 
 | 37 | +```  | 
 | 38 | + | 
 | 39 | +### NetworkPrefabInstanceHandlerWithData  | 
 | 40 | + | 
 | 41 | +the `NetworkPrefabInstanceHandlerWithData` allows for sending custom data from the authority during object spawning. This extra data can then be used to change the behavior of the `Instantiate` method. An implementation of `NetworkPrefabInstanceHandlerWithData` allows for sending any custom type that is serializable using [INetworkSerializable](advanced-topics/serialization/inetworkserializable.md).  | 
 | 42 | + | 
 | 43 | +```csharp  | 
 | 44 | +public abstract class NetworkPrefabInstanceHandlerWithData<T> : INetworkPrefabInstanceHandlerWithData  | 
 | 45 | +    where T : struct, INetworkSerializable  | 
 | 46 | +{  | 
 | 47 | +    public abstract NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation, T instantiationData);  | 
 | 48 | +    public abstract void Destroy(NetworkObject networkObject);  | 
 | 49 | +}  | 
 | 50 | +```  | 
 | 51 | + | 
 | 52 | +## Prefab handler registration  | 
 | 53 | + | 
 | 54 | +Once you have created a class to be your prefab handler, you can then register the class with the network prefab handler system using `NetworkManager.PrefabHandler.AddHandler`. Prefab handlers are registered against a NetworkObject's [GlobalObjectIdHash](../basics/networkobject.md#using-networkobjects).  | 
 | 55 | + | 
 | 56 | +```csharp  | 
 | 57 | +public class GameManager : NetworkBehaviour  | 
 | 58 | +{  | 
 | 59 | +    [SerializeField] private GameObject prefabToSpawn;  | 
 | 60 | + | 
 | 61 | +    void Start()  | 
 | 62 | +    {  | 
 | 63 | +        var customHandler = new MyPrefabHandler();  | 
 | 64 | +        NetworkManager.PrefabHandler.AddHandler(prefabToSpawn, customHandler);  | 
 | 65 | +    }  | 
 | 66 | +}  | 
 | 67 | +```  | 
 | 68 | + | 
 | 69 | +Prefab handlers can be unregistered using `NetworkManager.PrefabHandler.RemoveHandler`.  | 
 | 70 | + | 
 | 71 | +## Object spawning with prefab handlers  | 
 | 72 | + | 
 | 73 | +Once a prefab handler is registered Netcode will automatically use the defined `Initialize` and `Destroy` methods to manage the object lifecycle. [Spawn the network prefab as usual](../basics/object-spawning.md#spawning-a-network-prefab-overview) and the `Initialize` method will be called on whichever handler is registered with the spawned network prefab.  | 
 | 74 | + | 
 | 75 | +Note that the `Initialize` method is only called on non-authority clients. To customize network prefab behavior on the authority, you can use [prefab overrides](../basics/object-spawning.md#taking-prefab-overrides-into-consideration).  | 
 | 76 | + | 
 | 77 | +### Object spawning with custom data  | 
 | 78 | + | 
 | 79 | +For handlers that support custom data, the data to send needs to be manually set. To do this, call `SetInstantiationData` before calling the `Spawn` method. If `SetInstantiationData` is not called, the `default` implementation will be sent to the `Instantiate` call.  | 
 | 80 | + | 
 | 81 | +```csharp  | 
 | 82 | +public struct SpawnData : INetworkSerializable  | 
 | 83 | +{  | 
 | 84 | +    public int version;  | 
 | 85 | +    public string name;  | 
 | 86 | + | 
 | 87 | +    public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter  | 
 | 88 | +    {  | 
 | 89 | +        serializer.SerializeValue(ref version);  | 
 | 90 | +        serializer.SerializeValue(ref name);  | 
 | 91 | +    }  | 
 | 92 | +}  | 
 | 93 | + | 
 | 94 | +public class CountingObject : NetworkBehaviour  | 
 | 95 | +{  | 
 | 96 | +    [SerializeField] private GameObject prefabToSpawn;  | 
 | 97 | +    public string currentName  | 
 | 98 | + | 
 | 99 | +    public void SpawnObject(int objectTypeToSpawn)  | 
 | 100 | +    {  | 
 | 101 | +        var instance = Instantiate(prefabToSpawn);  | 
 | 102 | + | 
 | 103 | +        // Set data before spawning  | 
 | 104 | +        var customSpawnData = new SpawnData { version: objectTypeToSpawn, name: currentName}  | 
 | 105 | +        NetworkManager.Singleton.PrefabHandler.SetInstantiationData(instance, customSpawnData);  | 
 | 106 | + | 
 | 107 | +        instance.Spawn();  | 
 | 108 | +    }  | 
 | 109 | +}  | 
 | 110 | +```  | 
 | 111 | + | 
 | 112 | +All non-authority clients will then receive this data when `Instantiate` is called.  | 
 | 113 | + | 
 | 114 | +```csharp  | 
 | 115 | +public class SpawnWithDataSystem : NetworkPrefabInstanceHandlerWithData<SpawnData>  | 
 | 116 | +{  | 
 | 117 | +    public override NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation, SpawnData data)  | 
 | 118 | +    {  | 
 | 119 | +        // Create the client-side prefab using the spawn data from the authority  | 
 | 120 | +        var prefabToSpawn = GetPrefabForVersion(data.version);  | 
 | 121 | +        var instance = Instantiate(prefabToSpawn);  | 
 | 122 | + | 
 | 123 | +        var obj = instance.GetComponent<CountingObject>();  | 
 | 124 | +        obj.currentName = data.name;  | 
 | 125 | + | 
 | 126 | +        return instance.GetComponent<NetworkObject>();  | 
 | 127 | +    }  | 
 | 128 | + | 
 | 129 | +        public override void Destroy(NetworkObject networkObject)  | 
 | 130 | +    {  | 
 | 131 | +        Object.DestroyImmediate(networkObject.gameObject);  | 
 | 132 | +    }  | 
 | 133 | + | 
 | 134 | +    private GameObject GetPrefabForVersion(int version)  | 
 | 135 | +    {  | 
 | 136 | +        // Here you can implement logic to return a different client-side game object  | 
 | 137 | +        // depending on the information sent from the server.  | 
 | 138 | +    }  | 
 | 139 | +}  | 
 | 140 | +```  | 
 | 141 | + | 
 | 142 | +## Further Reading  | 
 | 143 | + | 
 | 144 | +- [Object pooling](./object-pooling.md)  | 
 | 145 | +- [Authority prefab overrides](../basics/object-spawning.md#taking-prefab-overrides-into-consideration)  | 
0 commit comments