diff --git a/Assets/Mirror/Components/NetworkRoomManager.cs b/Assets/Mirror/Components/NetworkRoomManager.cs
index 4420423c0..722153bac 100644
--- a/Assets/Mirror/Components/NetworkRoomManager.cs
+++ b/Assets/Mirror/Components/NetworkRoomManager.cs
@@ -451,7 +451,7 @@ public override void OnStartClient()
if (roomPlayerPrefab == null || roomPlayerPrefab.gameObject == null)
Debug.LogError("NetworkRoomManager no RoomPlayer prefab is registered. Please add a RoomPlayer prefab.");
else
- ClientScene.RegisterPrefab(roomPlayerPrefab.gameObject);
+ NetworkClient.RegisterPrefab(roomPlayerPrefab.gameObject);
if (playerPrefab == null)
Debug.LogError("NetworkRoomManager no GamePlayer prefab is registered. Please add a GamePlayer prefab.");
diff --git a/Assets/Mirror/Runtime/ClientScene.cs b/Assets/Mirror/Runtime/ClientScene.cs
index 834eb8c92..70d86f47a 100644
--- a/Assets/Mirror/Runtime/ClientScene.cs
+++ b/Assets/Mirror/Runtime/ClientScene.cs
@@ -32,19 +32,13 @@ public static class ClientScene
public static NetworkConnection readyConnection { get; private set; }
/// Registered spawnable prefabs by assetId.
- public static readonly Dictionary prefabs =
- new Dictionary();
+ [Obsolete("ClientScene.prefabs was moved to NetworkClient.prefabs")]
+ public static Dictionary prefabs => NetworkClient.prefabs;
/// Disabled scene objects that can be spawned again, by sceneId.
internal static readonly Dictionary spawnableObjects =
new Dictionary();
- // spawn handlers
- internal static readonly Dictionary spawnHandlers =
- new Dictionary();
- internal static readonly Dictionary unspawnHandlers =
- new Dictionary();
-
// add player //////////////////////////////////////////////////////////
// called from message handler for Owner message
internal static void InternalAddPlayer(NetworkIdentity identity)
@@ -171,416 +165,48 @@ public static void PrepareToSpawnSceneObjects()
}
// spawnable prefabs ///////////////////////////////////////////////////
- /// Find the registered prefab for this asset id.
- // Useful for debuggers
- public static bool GetPrefab(Guid assetId, out GameObject prefab)
- {
- prefab = null;
- return assetId != Guid.Empty &&
- prefabs.TryGetValue(assetId, out prefab) && prefab != null;
- }
+ [Obsolete("ClientScene.GetPrefab was moved to NetworkClient.GetPrefab")]
+ public static bool GetPrefab(Guid assetId, out GameObject prefab) => NetworkClient.GetPrefab(assetId, out prefab);
- /// Validates Prefab then adds it to prefabs dictionary.
- static void RegisterPrefabIdentity(NetworkIdentity prefab)
- {
- if (prefab.assetId == Guid.Empty)
- {
- Debug.LogError($"Can not Register '{prefab.name}' because it had empty assetid. If this is a scene Object use RegisterSpawnHandler instead");
- return;
- }
+ [Obsolete("ClientScene.RegisterPrefab was moved to NetworkClient.RegisterPrefab")]
+ public static void RegisterPrefab(GameObject prefab, Guid newAssetId) => NetworkClient.RegisterPrefab(prefab, newAssetId);
- if (prefab.sceneId != 0)
- {
- Debug.LogError($"Can not Register '{prefab.name}' because it has a sceneId, make sure you are passing in the original prefab and not an instance in the scene.");
- return;
- }
+ [Obsolete("ClientScene.RegisterPrefab was moved to NetworkClient.RegisterPrefab")]
+ public static void RegisterPrefab(GameObject prefab) => NetworkClient.RegisterPrefab(prefab);
- NetworkIdentity[] identities = prefab.GetComponentsInChildren();
- if (identities.Length > 1)
- {
- Debug.LogWarning($"Prefab '{prefab.name}' has multiple NetworkIdentity components. There should only be one NetworkIdentity on a prefab, and it must be on the root object.");
- }
+ [Obsolete("ClientScene.RegisterPrefab was moved to NetworkClient.RegisterPrefab")]
+ public static void RegisterPrefab(GameObject prefab, Guid newAssetId, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler) =>
+ NetworkClient.RegisterPrefab(prefab, newAssetId, spawnHandler, unspawnHandler);
- if (prefabs.ContainsKey(prefab.assetId))
- {
- GameObject existingPrefab = prefabs[prefab.assetId];
- Debug.LogWarning($"Replacing existing prefab with assetId '{prefab.assetId}'. Old prefab '{existingPrefab.name}', New prefab '{prefab.name}'");
- }
+ [Obsolete("ClientScene.RegisterPrefab was moved to NetworkClient.RegisterPrefab")]
+ public static void RegisterPrefab(GameObject prefab, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler) =>
+ NetworkClient.RegisterPrefab(prefab, spawnHandler, unspawnHandler);
- if (spawnHandlers.ContainsKey(prefab.assetId) || unspawnHandlers.ContainsKey(prefab.assetId))
- {
- Debug.LogWarning($"Adding prefab '{prefab.name}' with assetId '{prefab.assetId}' when spawnHandlers with same assetId already exists.");
- }
+ [Obsolete("ClientScene.RegisterPrefab was moved to NetworkClient.RegisterPrefab")]
+ public static void RegisterPrefab(GameObject prefab, Guid newAssetId, SpawnHandlerDelegate spawnHandler, UnSpawnDelegate unspawnHandler) =>
+ NetworkClient.RegisterPrefab(prefab, newAssetId, spawnHandler, unspawnHandler);
- // Debug.Log($"Registering prefab '{prefab.name}' as asset:{prefab.assetId}");
+ [Obsolete("ClientScene.RegisterPrefab was moved to NetworkClient.RegisterPrefab")]
+ public static void RegisterPrefab(GameObject prefab, SpawnHandlerDelegate spawnHandler, UnSpawnDelegate unspawnHandler) =>
+ NetworkClient.RegisterPrefab(prefab, spawnHandler, unspawnHandler);
- prefabs[prefab.assetId] = prefab.gameObject;
- }
-
- /// Register spawnable prefab with custom assetId.
- // Note: newAssetId can not be set on GameObjects that already have an assetId
- // Note: registering with assetId is useful for assetbundles etc. a lot
- // of people use this.
- public static void RegisterPrefab(GameObject prefab, Guid newAssetId)
- {
- if (prefab == null)
- {
- Debug.LogError("Could not register prefab because it was null");
- return;
- }
-
- if (newAssetId == Guid.Empty)
- {
- Debug.LogError($"Could not register '{prefab.name}' with new assetId because the new assetId was empty");
- return;
- }
-
- NetworkIdentity identity = prefab.GetComponent();
- if (identity == null)
- {
- Debug.LogError($"Could not register '{prefab.name}' since it contains no NetworkIdentity component");
- return;
- }
-
- if (identity.assetId != Guid.Empty && identity.assetId != newAssetId)
- {
- Debug.LogError($"Could not register '{prefab.name}' to {newAssetId} because it already had an AssetId, Existing assetId {identity.assetId}");
- return;
- }
-
- identity.assetId = newAssetId;
-
- RegisterPrefabIdentity(identity);
- }
-
- /// Register spawnable prefab.
- public static void RegisterPrefab(GameObject prefab)
- {
- if (prefab == null)
- {
- Debug.LogError("Could not register prefab because it was null");
- return;
- }
-
- NetworkIdentity identity = prefab.GetComponent();
- if (identity == null)
- {
- Debug.LogError($"Could not register '{prefab.name}' since it contains no NetworkIdentity component");
- return;
- }
-
- RegisterPrefabIdentity(identity);
- }
-
- /// Register a spawnable prefab with custom assetId and custom spawn/unspawn handlers.
- // Note: newAssetId can not be set on GameObjects that already have an assetId
- // Note: registering with assetId is useful for assetbundles etc. a lot
- // of people use this.
- // TODO why do we have one with SpawnDelegate and one with SpawnHandlerDelegate?
- public static void RegisterPrefab(GameObject prefab, Guid newAssetId, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
- {
- // We need this check here because we don't want a null handler in the lambda expression below
- if (spawnHandler == null)
- {
- Debug.LogError($"Can not Register null SpawnHandler for {newAssetId}");
- return;
- }
-
- RegisterPrefab(prefab, newAssetId, msg => spawnHandler(msg.position, msg.assetId), unspawnHandler);
- }
-
- /// Register a spawnable prefab with custom spawn/unspawn handlers.
- // TODO why do we have one with SpawnDelegate and one with SpawnHandlerDelegate?
- public static void RegisterPrefab(GameObject prefab, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
- {
- if (prefab == null)
- {
- Debug.LogError("Could not register handler for prefab because the prefab was null");
- return;
- }
-
- NetworkIdentity identity = prefab.GetComponent();
- if (identity == null)
- {
- Debug.LogError("Could not register handler for '" + prefab.name + "' since it contains no NetworkIdentity component");
- return;
- }
-
- if (identity.sceneId != 0)
- {
- Debug.LogError($"Can not Register '{prefab.name}' because it has a sceneId, make sure you are passing in the original prefab and not an instance in the scene.");
- return;
- }
-
- Guid assetId = identity.assetId;
-
- if (assetId == Guid.Empty)
- {
- Debug.LogError($"Can not Register handler for '{prefab.name}' because it had empty assetid. If this is a scene Object use RegisterSpawnHandler instead");
- return;
- }
-
- // We need this check here because we don't want a null handler in the lambda expression below
- if (spawnHandler == null)
- {
- Debug.LogError($"Can not Register null SpawnHandler for {assetId}");
- return;
- }
-
- RegisterPrefab(prefab, msg => spawnHandler(msg.position, msg.assetId), unspawnHandler);
- }
-
- /// Register a spawnable prefab with custom assetId and custom spawn/unspawn handlers.
- // Note: newAssetId can not be set on GameObjects that already have an assetId
- // Note: registering with assetId is useful for assetbundles etc. a lot
- // of people use this.
- // TODO why do we have one with SpawnDelegate and one with SpawnHandlerDelegate?
- public static void RegisterPrefab(GameObject prefab, Guid newAssetId, SpawnHandlerDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
- {
- if (newAssetId == Guid.Empty)
- {
- Debug.LogError($"Could not register handler for '{prefab.name}' with new assetId because the new assetId was empty");
- return;
- }
-
- if (prefab == null)
- {
- Debug.LogError("Could not register handler for prefab because the prefab was null");
- return;
- }
-
- NetworkIdentity identity = prefab.GetComponent();
- if (identity == null)
- {
- Debug.LogError("Could not register handler for '" + prefab.name + "' since it contains no NetworkIdentity component");
- return;
- }
-
- if (identity.assetId != Guid.Empty && identity.assetId != newAssetId)
- {
- Debug.LogError($"Could not register Handler for '{prefab.name}' to {newAssetId} because it already had an AssetId, Existing assetId {identity.assetId}");
- return;
- }
-
- if (identity.sceneId != 0)
- {
- Debug.LogError($"Can not Register '{prefab.name}' because it has a sceneId, make sure you are passing in the original prefab and not an instance in the scene.");
- return;
- }
-
- identity.assetId = newAssetId;
- Guid assetId = identity.assetId;
-
- if (spawnHandler == null)
- {
- Debug.LogError($"Can not Register null SpawnHandler for {assetId}");
- return;
- }
-
- if (unspawnHandler == null)
- {
- Debug.LogError($"Can not Register null UnSpawnHandler for {assetId}");
- return;
- }
-
- if (spawnHandlers.ContainsKey(assetId) || unspawnHandlers.ContainsKey(assetId))
- {
- Debug.LogWarning($"Replacing existing spawnHandlers for prefab '{prefab.name}' with assetId '{assetId}'");
- }
-
- if (prefabs.ContainsKey(assetId))
- {
- // this is error because SpawnPrefab checks prefabs before handler
- Debug.LogError($"assetId '{assetId}' is already used by prefab '{prefabs[assetId].name}', unregister the prefab first before trying to add handler");
- }
-
- NetworkIdentity[] identities = prefab.GetComponentsInChildren();
- if (identities.Length > 1)
- {
- Debug.LogWarning($"Prefab '{prefab.name}' has multiple NetworkIdentity components. There should only be one NetworkIdentity on a prefab, and it must be on the root object.");
- }
-
- // Debug.Log("Registering custom prefab '" + prefab.name + "' as asset:" + assetId + " " + spawnHandler.GetMethodName() + "/" + unspawnHandler.GetMethodName());
-
- spawnHandlers[assetId] = spawnHandler;
- unspawnHandlers[assetId] = unspawnHandler;
- }
-
- /// Register a spawnable prefab with custom spawn/unspawn handlers.
- // TODO why do we have one with SpawnDelegate and one with SpawnHandlerDelegate?
- public static void RegisterPrefab(GameObject prefab, SpawnHandlerDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
- {
- if (prefab == null)
- {
- Debug.LogError("Could not register handler for prefab because the prefab was null");
- return;
- }
-
- NetworkIdentity identity = prefab.GetComponent();
- if (identity == null)
- {
- Debug.LogError("Could not register handler for '" + prefab.name + "' since it contains no NetworkIdentity component");
- return;
- }
-
- if (identity.sceneId != 0)
- {
- Debug.LogError($"Can not Register '{prefab.name}' because it has a sceneId, make sure you are passing in the original prefab and not an instance in the scene.");
- return;
- }
-
- Guid assetId = identity.assetId;
-
- if (assetId == Guid.Empty)
- {
- Debug.LogError($"Can not Register handler for '{prefab.name}' because it had empty assetid. If this is a scene Object use RegisterSpawnHandler instead");
- return;
- }
-
- if (spawnHandler == null)
- {
- Debug.LogError($"Can not Register null SpawnHandler for {assetId}");
- return;
- }
-
- if (unspawnHandler == null)
- {
- Debug.LogError($"Can not Register null UnSpawnHandler for {assetId}");
- return;
- }
-
- if (spawnHandlers.ContainsKey(assetId) || unspawnHandlers.ContainsKey(assetId))
- {
- Debug.LogWarning($"Replacing existing spawnHandlers for prefab '{prefab.name}' with assetId '{assetId}'");
- }
-
- if (prefabs.ContainsKey(assetId))
- {
- // this is error because SpawnPrefab checks prefabs before handler
- Debug.LogError($"assetId '{assetId}' is already used by prefab '{prefabs[assetId].name}', unregister the prefab first before trying to add handler");
- }
-
- NetworkIdentity[] identities = prefab.GetComponentsInChildren();
- if (identities.Length > 1)
- {
- Debug.LogWarning($"Prefab '{prefab.name}' has multiple NetworkIdentity components. There should only be one NetworkIdentity on a prefab, and it must be on the root object.");
- }
-
- // Debug.Log("Registering custom prefab '" + prefab.name + "' as asset:" + assetId + " " + spawnHandler.GetMethodName() + "/" + unspawnHandler.GetMethodName());
-
- spawnHandlers[assetId] = spawnHandler;
- unspawnHandlers[assetId] = unspawnHandler;
- }
-
- /// Removes a registered spawn prefab that was setup with ClientScene.RegisterPrefab.
- public static void UnregisterPrefab(GameObject prefab)
- {
- if (prefab == null)
- {
- Debug.LogError("Could not unregister prefab because it was null");
- return;
- }
-
- NetworkIdentity identity = prefab.GetComponent();
- if (identity == null)
- {
- Debug.LogError("Could not unregister '" + prefab.name + "' since it contains no NetworkIdentity component");
- return;
- }
-
- Guid assetId = identity.assetId;
-
- prefabs.Remove(assetId);
- spawnHandlers.Remove(assetId);
- unspawnHandlers.Remove(assetId);
- }
+ [Obsolete("ClientScene.UnregisterPrefab was moved to NetworkClient.UnregisterPrefab")]
+ public static void UnregisterPrefab(GameObject prefab) => NetworkClient.UnregisterPrefab(prefab);
// spawn handlers //////////////////////////////////////////////////////
- /// This is an advanced spawning function that registers a custom assetId with the spawning system.
- // This can be used to register custom spawning methods for an assetId -
- // instead of the usual method of registering spawning methods for a
- // prefab. This should be used when no prefab exists for the spawned
- // objects - such as when they are constructed dynamically at runtime
- // from configuration data.
- public static void RegisterSpawnHandler(Guid assetId, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
- {
- // We need this check here because we don't want a null handler in the lambda expression below
- if (spawnHandler == null)
- {
- Debug.LogError($"Can not Register null SpawnHandler for {assetId}");
- return;
- }
+ [Obsolete("ClientScene.RegisterSpawnHandler was moved to NetworkClient.RegisterSpawnHandler")]
+ public static void RegisterSpawnHandler(Guid assetId, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler) =>
+ NetworkClient.RegisterSpawnHandler(assetId, spawnHandler, unspawnHandler);
- RegisterSpawnHandler(assetId, msg => spawnHandler(msg.position, msg.assetId), unspawnHandler);
- }
+ [Obsolete("ClientScene.RegisterSpawnHandler was moved to NetworkClient.RegisterSpawnHandler")]
+ public static void RegisterSpawnHandler(Guid assetId, SpawnHandlerDelegate spawnHandler, UnSpawnDelegate unspawnHandler) =>
+ NetworkClient.RegisterSpawnHandler(assetId, spawnHandler, unspawnHandler);
- /// This is an advanced spawning function that registers a custom assetId with the spawning system.
- // This can be used to register custom spawning methods for an assetId -
- // instead of the usual method of registering spawning methods for a
- // prefab. This should be used when no prefab exists for the spawned
- // objects - such as when they are constructed dynamically at runtime
- // from configuration data.
- public static void RegisterSpawnHandler(Guid assetId, SpawnHandlerDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
- {
- if (spawnHandler == null)
- {
- Debug.LogError($"Can not Register null SpawnHandler for {assetId}");
- return;
- }
+ [Obsolete("ClientScene.UnregisterSpawnHandler was moved to NetworkClient.UnregisterSpawnHandler")]
+ public static void UnregisterSpawnHandler(Guid assetId) => NetworkClient.UnregisterSpawnHandler(assetId);
- if (unspawnHandler == null)
- {
- Debug.LogError($"Can not Register null UnSpawnHandler for {assetId}");
- return;
- }
-
- if (assetId == Guid.Empty)
- {
- Debug.LogError("Can not Register SpawnHandler for empty Guid");
- return;
- }
-
- if (spawnHandlers.ContainsKey(assetId) || unspawnHandlers.ContainsKey(assetId))
- {
- Debug.LogWarning($"Replacing existing spawnHandlers for {assetId}");
- }
-
- if (prefabs.ContainsKey(assetId))
- {
- // this is error because SpawnPrefab checks prefabs before handler
- Debug.LogError($"assetId '{assetId}' is already used by prefab '{prefabs[assetId].name}'");
- }
-
- // Debug.Log("RegisterSpawnHandler asset '" + assetId + "' " + spawnHandler.GetMethodName() + "/" + unspawnHandler.GetMethodName());
-
- spawnHandlers[assetId] = spawnHandler;
- unspawnHandlers[assetId] = unspawnHandler;
- }
-
- /// Removes a registered spawn handler function that was registered with ClientScene.RegisterHandler().
- public static void UnregisterSpawnHandler(Guid assetId)
- {
- spawnHandlers.Remove(assetId);
- unspawnHandlers.Remove(assetId);
- }
-
- /// This clears the registered spawn prefabs and spawn handler functions for this client.
- public static void ClearSpawners()
- {
- prefabs.Clear();
- spawnHandlers.Clear();
- unspawnHandlers.Clear();
- }
-
- static bool InvokeUnSpawnHandler(Guid assetId, GameObject obj)
- {
- if (unspawnHandlers.TryGetValue(assetId, out UnSpawnDelegate handler) && handler != null)
- {
- handler(obj);
- return true;
- }
- return false;
- }
+ [Obsolete("ClientScene.ClearSpawners was moved to NetworkClient.ClearSpawners")]
+ public static void ClearSpawners() => NetworkClient.ClearSpawners();
// spawning ////////////////////////////////////////////////////////////
internal static void ApplySpawnPayload(NetworkIdentity identity, SpawnMessage message)
@@ -676,7 +302,7 @@ static NetworkIdentity SpawnPrefab(SpawnMessage msg)
//Debug.Log("Client spawn handler instantiating [netId:" + msg.netId + " asset ID:" + msg.assetId + " pos:" + msg.position + " rotation: " + msg.rotation + "]");
return obj.GetComponent();
}
- if (spawnHandlers.TryGetValue(msg.assetId, out SpawnHandlerDelegate handler))
+ if (NetworkClient.spawnHandlers.TryGetValue(msg.assetId, out SpawnHandlerDelegate handler))
{
GameObject obj = handler(msg);
if (obj == null)
@@ -782,7 +408,7 @@ static void DestroyObject(uint netId)
localObject.OnStopClient();
// user handling
- if (InvokeUnSpawnHandler(localObject.assetId, localObject.gameObject))
+ if (NetworkClient.InvokeUnSpawnHandler(localObject.assetId, localObject.gameObject))
{
// reset object after user's handler
localObject.Reset();
@@ -822,7 +448,7 @@ public static void DestroyAllClientObjects()
if (identity != null && identity.gameObject != null)
{
identity.OnStopClient();
- bool wasUnspawned = InvokeUnSpawnHandler(identity.assetId, identity.gameObject);
+ bool wasUnspawned = NetworkClient.InvokeUnSpawnHandler(identity.assetId, identity.gameObject);
if (!wasUnspawned)
{
// scene objects are reset and disabled.
diff --git a/Assets/Mirror/Runtime/NetworkClient.cs b/Assets/Mirror/Runtime/NetworkClient.cs
index 515bc48ed..043e9d5ed 100644
--- a/Assets/Mirror/Runtime/NetworkClient.cs
+++ b/Assets/Mirror/Runtime/NetworkClient.cs
@@ -50,6 +50,16 @@ public static class NetworkClient
internal static Action OnConnectedEvent;
internal static Action OnDisconnectedEvent;
+ /// Registered spawnable prefabs by assetId.
+ public static readonly Dictionary prefabs =
+ new Dictionary();
+
+ // spawn handlers
+ internal static readonly Dictionary spawnHandlers =
+ new Dictionary();
+ internal static readonly Dictionary unspawnHandlers =
+ new Dictionary();
+
// initialization //////////////////////////////////////////////////////
static void AddTransportHandlers()
{
@@ -311,6 +321,418 @@ public static bool UnregisterHandler()
return handlers.Remove(msgType);
}
+ // spawnable prefabs ///////////////////////////////////////////////////
+ /// Find the registered prefab for this asset id.
+ // Useful for debuggers
+ public static bool GetPrefab(Guid assetId, out GameObject prefab)
+ {
+ prefab = null;
+ return assetId != Guid.Empty &&
+ prefabs.TryGetValue(assetId, out prefab) && prefab != null;
+ }
+
+ /// Validates Prefab then adds it to prefabs dictionary.
+ static void RegisterPrefabIdentity(NetworkIdentity prefab)
+ {
+ if (prefab.assetId == Guid.Empty)
+ {
+ Debug.LogError($"Can not Register '{prefab.name}' because it had empty assetid. If this is a scene Object use RegisterSpawnHandler instead");
+ return;
+ }
+
+ if (prefab.sceneId != 0)
+ {
+ Debug.LogError($"Can not Register '{prefab.name}' because it has a sceneId, make sure you are passing in the original prefab and not an instance in the scene.");
+ return;
+ }
+
+ NetworkIdentity[] identities = prefab.GetComponentsInChildren();
+ if (identities.Length > 1)
+ {
+ Debug.LogWarning($"Prefab '{prefab.name}' has multiple NetworkIdentity components. There should only be one NetworkIdentity on a prefab, and it must be on the root object.");
+ }
+
+ if (prefabs.ContainsKey(prefab.assetId))
+ {
+ GameObject existingPrefab = prefabs[prefab.assetId];
+ Debug.LogWarning($"Replacing existing prefab with assetId '{prefab.assetId}'. Old prefab '{existingPrefab.name}', New prefab '{prefab.name}'");
+ }
+
+ if (spawnHandlers.ContainsKey(prefab.assetId) || unspawnHandlers.ContainsKey(prefab.assetId))
+ {
+ Debug.LogWarning($"Adding prefab '{prefab.name}' with assetId '{prefab.assetId}' when spawnHandlers with same assetId already exists.");
+ }
+
+ // Debug.Log($"Registering prefab '{prefab.name}' as asset:{prefab.assetId}");
+
+ prefabs[prefab.assetId] = prefab.gameObject;
+ }
+
+ /// Register spawnable prefab with custom assetId.
+ // Note: newAssetId can not be set on GameObjects that already have an assetId
+ // Note: registering with assetId is useful for assetbundles etc. a lot
+ // of people use this.
+ public static void RegisterPrefab(GameObject prefab, Guid newAssetId)
+ {
+ if (prefab == null)
+ {
+ Debug.LogError("Could not register prefab because it was null");
+ return;
+ }
+
+ if (newAssetId == Guid.Empty)
+ {
+ Debug.LogError($"Could not register '{prefab.name}' with new assetId because the new assetId was empty");
+ return;
+ }
+
+ NetworkIdentity identity = prefab.GetComponent();
+ if (identity == null)
+ {
+ Debug.LogError($"Could not register '{prefab.name}' since it contains no NetworkIdentity component");
+ return;
+ }
+
+ if (identity.assetId != Guid.Empty && identity.assetId != newAssetId)
+ {
+ Debug.LogError($"Could not register '{prefab.name}' to {newAssetId} because it already had an AssetId, Existing assetId {identity.assetId}");
+ return;
+ }
+
+ identity.assetId = newAssetId;
+
+ RegisterPrefabIdentity(identity);
+ }
+
+ /// Register spawnable prefab.
+ public static void RegisterPrefab(GameObject prefab)
+ {
+ if (prefab == null)
+ {
+ Debug.LogError("Could not register prefab because it was null");
+ return;
+ }
+
+ NetworkIdentity identity = prefab.GetComponent();
+ if (identity == null)
+ {
+ Debug.LogError($"Could not register '{prefab.name}' since it contains no NetworkIdentity component");
+ return;
+ }
+
+ RegisterPrefabIdentity(identity);
+ }
+
+ /// Register a spawnable prefab with custom assetId and custom spawn/unspawn handlers.
+ // Note: newAssetId can not be set on GameObjects that already have an assetId
+ // Note: registering with assetId is useful for assetbundles etc. a lot
+ // of people use this.
+ // TODO why do we have one with SpawnDelegate and one with SpawnHandlerDelegate?
+ public static void RegisterPrefab(GameObject prefab, Guid newAssetId, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
+ {
+ // We need this check here because we don't want a null handler in the lambda expression below
+ if (spawnHandler == null)
+ {
+ Debug.LogError($"Can not Register null SpawnHandler for {newAssetId}");
+ return;
+ }
+
+ RegisterPrefab(prefab, newAssetId, msg => spawnHandler(msg.position, msg.assetId), unspawnHandler);
+ }
+
+ /// Register a spawnable prefab with custom spawn/unspawn handlers.
+ // TODO why do we have one with SpawnDelegate and one with SpawnHandlerDelegate?
+ public static void RegisterPrefab(GameObject prefab, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
+ {
+ if (prefab == null)
+ {
+ Debug.LogError("Could not register handler for prefab because the prefab was null");
+ return;
+ }
+
+ NetworkIdentity identity = prefab.GetComponent();
+ if (identity == null)
+ {
+ Debug.LogError("Could not register handler for '" + prefab.name + "' since it contains no NetworkIdentity component");
+ return;
+ }
+
+ if (identity.sceneId != 0)
+ {
+ Debug.LogError($"Can not Register '{prefab.name}' because it has a sceneId, make sure you are passing in the original prefab and not an instance in the scene.");
+ return;
+ }
+
+ Guid assetId = identity.assetId;
+
+ if (assetId == Guid.Empty)
+ {
+ Debug.LogError($"Can not Register handler for '{prefab.name}' because it had empty assetid. If this is a scene Object use RegisterSpawnHandler instead");
+ return;
+ }
+
+ // We need this check here because we don't want a null handler in the lambda expression below
+ if (spawnHandler == null)
+ {
+ Debug.LogError($"Can not Register null SpawnHandler for {assetId}");
+ return;
+ }
+
+ RegisterPrefab(prefab, msg => spawnHandler(msg.position, msg.assetId), unspawnHandler);
+ }
+
+ /// Register a spawnable prefab with custom assetId and custom spawn/unspawn handlers.
+ // Note: newAssetId can not be set on GameObjects that already have an assetId
+ // Note: registering with assetId is useful for assetbundles etc. a lot
+ // of people use this.
+ // TODO why do we have one with SpawnDelegate and one with SpawnHandlerDelegate?
+ public static void RegisterPrefab(GameObject prefab, Guid newAssetId, SpawnHandlerDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
+ {
+ if (newAssetId == Guid.Empty)
+ {
+ Debug.LogError($"Could not register handler for '{prefab.name}' with new assetId because the new assetId was empty");
+ return;
+ }
+
+ if (prefab == null)
+ {
+ Debug.LogError("Could not register handler for prefab because the prefab was null");
+ return;
+ }
+
+ NetworkIdentity identity = prefab.GetComponent();
+ if (identity == null)
+ {
+ Debug.LogError("Could not register handler for '" + prefab.name + "' since it contains no NetworkIdentity component");
+ return;
+ }
+
+ if (identity.assetId != Guid.Empty && identity.assetId != newAssetId)
+ {
+ Debug.LogError($"Could not register Handler for '{prefab.name}' to {newAssetId} because it already had an AssetId, Existing assetId {identity.assetId}");
+ return;
+ }
+
+ if (identity.sceneId != 0)
+ {
+ Debug.LogError($"Can not Register '{prefab.name}' because it has a sceneId, make sure you are passing in the original prefab and not an instance in the scene.");
+ return;
+ }
+
+ identity.assetId = newAssetId;
+ Guid assetId = identity.assetId;
+
+ if (spawnHandler == null)
+ {
+ Debug.LogError($"Can not Register null SpawnHandler for {assetId}");
+ return;
+ }
+
+ if (unspawnHandler == null)
+ {
+ Debug.LogError($"Can not Register null UnSpawnHandler for {assetId}");
+ return;
+ }
+
+ if (spawnHandlers.ContainsKey(assetId) || unspawnHandlers.ContainsKey(assetId))
+ {
+ Debug.LogWarning($"Replacing existing spawnHandlers for prefab '{prefab.name}' with assetId '{assetId}'");
+ }
+
+ if (prefabs.ContainsKey(assetId))
+ {
+ // this is error because SpawnPrefab checks prefabs before handler
+ Debug.LogError($"assetId '{assetId}' is already used by prefab '{prefabs[assetId].name}', unregister the prefab first before trying to add handler");
+ }
+
+ NetworkIdentity[] identities = prefab.GetComponentsInChildren();
+ if (identities.Length > 1)
+ {
+ Debug.LogWarning($"Prefab '{prefab.name}' has multiple NetworkIdentity components. There should only be one NetworkIdentity on a prefab, and it must be on the root object.");
+ }
+
+ // Debug.Log("Registering custom prefab '" + prefab.name + "' as asset:" + assetId + " " + spawnHandler.GetMethodName() + "/" + unspawnHandler.GetMethodName());
+
+ spawnHandlers[assetId] = spawnHandler;
+ unspawnHandlers[assetId] = unspawnHandler;
+ }
+
+ /// Register a spawnable prefab with custom spawn/unspawn handlers.
+ // TODO why do we have one with SpawnDelegate and one with SpawnHandlerDelegate?
+ public static void RegisterPrefab(GameObject prefab, SpawnHandlerDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
+ {
+ if (prefab == null)
+ {
+ Debug.LogError("Could not register handler for prefab because the prefab was null");
+ return;
+ }
+
+ NetworkIdentity identity = prefab.GetComponent();
+ if (identity == null)
+ {
+ Debug.LogError("Could not register handler for '" + prefab.name + "' since it contains no NetworkIdentity component");
+ return;
+ }
+
+ if (identity.sceneId != 0)
+ {
+ Debug.LogError($"Can not Register '{prefab.name}' because it has a sceneId, make sure you are passing in the original prefab and not an instance in the scene.");
+ return;
+ }
+
+ Guid assetId = identity.assetId;
+
+ if (assetId == Guid.Empty)
+ {
+ Debug.LogError($"Can not Register handler for '{prefab.name}' because it had empty assetid. If this is a scene Object use RegisterSpawnHandler instead");
+ return;
+ }
+
+ if (spawnHandler == null)
+ {
+ Debug.LogError($"Can not Register null SpawnHandler for {assetId}");
+ return;
+ }
+
+ if (unspawnHandler == null)
+ {
+ Debug.LogError($"Can not Register null UnSpawnHandler for {assetId}");
+ return;
+ }
+
+ if (spawnHandlers.ContainsKey(assetId) || unspawnHandlers.ContainsKey(assetId))
+ {
+ Debug.LogWarning($"Replacing existing spawnHandlers for prefab '{prefab.name}' with assetId '{assetId}'");
+ }
+
+ if (prefabs.ContainsKey(assetId))
+ {
+ // this is error because SpawnPrefab checks prefabs before handler
+ Debug.LogError($"assetId '{assetId}' is already used by prefab '{prefabs[assetId].name}', unregister the prefab first before trying to add handler");
+ }
+
+ NetworkIdentity[] identities = prefab.GetComponentsInChildren();
+ if (identities.Length > 1)
+ {
+ Debug.LogWarning($"Prefab '{prefab.name}' has multiple NetworkIdentity components. There should only be one NetworkIdentity on a prefab, and it must be on the root object.");
+ }
+
+ // Debug.Log("Registering custom prefab '" + prefab.name + "' as asset:" + assetId + " " + spawnHandler.GetMethodName() + "/" + unspawnHandler.GetMethodName());
+
+ spawnHandlers[assetId] = spawnHandler;
+ unspawnHandlers[assetId] = unspawnHandler;
+ }
+
+ /// Removes a registered spawn prefab that was setup with ClientScene.RegisterPrefab.
+ public static void UnregisterPrefab(GameObject prefab)
+ {
+ if (prefab == null)
+ {
+ Debug.LogError("Could not unregister prefab because it was null");
+ return;
+ }
+
+ NetworkIdentity identity = prefab.GetComponent();
+ if (identity == null)
+ {
+ Debug.LogError("Could not unregister '" + prefab.name + "' since it contains no NetworkIdentity component");
+ return;
+ }
+
+ Guid assetId = identity.assetId;
+
+ prefabs.Remove(assetId);
+ spawnHandlers.Remove(assetId);
+ unspawnHandlers.Remove(assetId);
+ }
+
+ // spawn handlers //////////////////////////////////////////////////////
+ /// This is an advanced spawning function that registers a custom assetId with the spawning system.
+ // This can be used to register custom spawning methods for an assetId -
+ // instead of the usual method of registering spawning methods for a
+ // prefab. This should be used when no prefab exists for the spawned
+ // objects - such as when they are constructed dynamically at runtime
+ // from configuration data.
+ public static void RegisterSpawnHandler(Guid assetId, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
+ {
+ // We need this check here because we don't want a null handler in the lambda expression below
+ if (spawnHandler == null)
+ {
+ Debug.LogError($"Can not Register null SpawnHandler for {assetId}");
+ return;
+ }
+
+ RegisterSpawnHandler(assetId, msg => spawnHandler(msg.position, msg.assetId), unspawnHandler);
+ }
+
+ /// This is an advanced spawning function that registers a custom assetId with the spawning system.
+ // This can be used to register custom spawning methods for an assetId -
+ // instead of the usual method of registering spawning methods for a
+ // prefab. This should be used when no prefab exists for the spawned
+ // objects - such as when they are constructed dynamically at runtime
+ // from configuration data.
+ public static void RegisterSpawnHandler(Guid assetId, SpawnHandlerDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
+ {
+ if (spawnHandler == null)
+ {
+ Debug.LogError($"Can not Register null SpawnHandler for {assetId}");
+ return;
+ }
+
+ if (unspawnHandler == null)
+ {
+ Debug.LogError($"Can not Register null UnSpawnHandler for {assetId}");
+ return;
+ }
+
+ if (assetId == Guid.Empty)
+ {
+ Debug.LogError("Can not Register SpawnHandler for empty Guid");
+ return;
+ }
+
+ if (spawnHandlers.ContainsKey(assetId) || unspawnHandlers.ContainsKey(assetId))
+ {
+ Debug.LogWarning($"Replacing existing spawnHandlers for {assetId}");
+ }
+
+ if (prefabs.ContainsKey(assetId))
+ {
+ // this is error because SpawnPrefab checks prefabs before handler
+ Debug.LogError($"assetId '{assetId}' is already used by prefab '{prefabs[assetId].name}'");
+ }
+
+ // Debug.Log("RegisterSpawnHandler asset '" + assetId + "' " + spawnHandler.GetMethodName() + "/" + unspawnHandler.GetMethodName());
+
+ spawnHandlers[assetId] = spawnHandler;
+ unspawnHandlers[assetId] = unspawnHandler;
+ }
+
+ /// Removes a registered spawn handler function that was registered with ClientScene.RegisterHandler().
+ public static void UnregisterSpawnHandler(Guid assetId)
+ {
+ spawnHandlers.Remove(assetId);
+ unspawnHandlers.Remove(assetId);
+ }
+
+ /// This clears the registered spawn prefabs and spawn handler functions for this client.
+ public static void ClearSpawners()
+ {
+ prefabs.Clear();
+ spawnHandlers.Clear();
+ unspawnHandlers.Clear();
+ }
+
+ internal static bool InvokeUnSpawnHandler(Guid assetId, GameObject obj)
+ {
+ if (unspawnHandlers.TryGetValue(assetId, out UnSpawnDelegate handler) && handler != null)
+ {
+ handler(obj);
+ return true;
+ }
+ return false;
+ }
+
// update //////////////////////////////////////////////////////////////
// NetworkEarlyUpdate called before any Update/FixedUpdate
// (we add this to the UnityEngine in NetworkLoop)
diff --git a/Assets/Mirror/Runtime/NetworkManager.cs b/Assets/Mirror/Runtime/NetworkManager.cs
index 6cde4f4f4..c952bf338 100644
--- a/Assets/Mirror/Runtime/NetworkManager.cs
+++ b/Assets/Mirror/Runtime/NetworkManager.cs
@@ -807,10 +807,10 @@ void RegisterClientMessages()
NetworkClient.RegisterHandler(OnClientSceneInternal, false);
if (playerPrefab != null)
- ClientScene.RegisterPrefab(playerPrefab);
+ NetworkClient.RegisterPrefab(playerPrefab);
foreach (GameObject prefab in spawnPrefabs.Where(t => t != null))
- ClientScene.RegisterPrefab(prefab);
+ NetworkClient.RegisterPrefab(prefab);
}
///
diff --git a/Assets/Mirror/Tests/Common/ClientSceneTestsBase.cs b/Assets/Mirror/Tests/Common/ClientSceneTestsBase.cs
index a03ee0a25..c882024a6 100644
--- a/Assets/Mirror/Tests/Common/ClientSceneTestsBase.cs
+++ b/Assets/Mirror/Tests/Common/ClientSceneTestsBase.cs
@@ -29,9 +29,9 @@ public abstract class ClientSceneTestsBase
protected readonly List _createdObjects = new List();
- protected Dictionary prefabs => ClientScene.prefabs;
- protected Dictionary spawnHandlers => ClientScene.spawnHandlers;
- protected Dictionary unspawnHandlers => ClientScene.unspawnHandlers;
+ protected Dictionary prefabs => NetworkClient.prefabs;
+ protected Dictionary spawnHandlers => NetworkClient.spawnHandlers;
+ protected Dictionary unspawnHandlers => NetworkClient.unspawnHandlers;
protected Dictionary spawnableObjects => ClientScene.spawnableObjects;
diff --git a/Assets/Mirror/Tests/Runtime/ClientSceneTests_DestroyAllClientObjects.cs b/Assets/Mirror/Tests/Runtime/ClientSceneTests_DestroyAllClientObjects.cs
index 84a7610f4..1417296eb 100644
--- a/Assets/Mirror/Tests/Runtime/ClientSceneTests_DestroyAllClientObjects.cs
+++ b/Assets/Mirror/Tests/Runtime/ClientSceneTests_DestroyAllClientObjects.cs
@@ -49,7 +49,7 @@ public class ClientSceneTests_DestroyAllClientObjects
{
public static readonly List _createdObjects = new List();
Dictionary spawned => NetworkIdentity.spawned;
- Dictionary unspawnHandlers => ClientScene.unspawnHandlers;
+ Dictionary unspawnHandlers => NetworkClient.unspawnHandlers;
[TearDown]
public void TearDown()