From 311875b41c6039c5d48bd0885d7efade97fbed41 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity <73188597+NoelStephensUnity@users.noreply.github.com> Date: Fri, 23 Jul 2021 15:07:55 -0500 Subject: [PATCH 01/11] refactor and style Renamed the two methods within INetworkPrefabInstanceHandler to better reflect what their function was and to avoid user confusion. Improved comments and added additional XML Documentation for the NetworkPrefabHandler and associated INetworkPrefabInstanceHandler --- .../Runtime/Spawning/NetworkPrefabHandler.cs | 81 ++++++++++++------- .../Runtime/NetworkPrefabHandlerTests.cs | 4 +- .../Tests/Manual/Scripts/NetworkPrefabPool.cs | 4 +- .../CustomPrefabSpawnerForPerformanceTests.cs | 4 +- 4 files changed, 58 insertions(+), 35 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkPrefabHandler.cs b/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkPrefabHandler.cs index 1ebd632673..a504750560 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkPrefabHandler.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkPrefabHandler.cs @@ -4,13 +4,36 @@ namespace MLAPI.Spawning { /// - /// Interface for customizing asset spawn and destroy handlers - /// NOTE: Custom spawn and destroy handlers are only invoked on clients + /// Interface for customizing, overriding, spawning, and destroying Network Prefabs + /// Used by /// public interface INetworkPrefabInstanceHandler { - NetworkObject HandleNetworkPrefabSpawn(ulong ownerClientId, Vector3 position, Quaternion rotation); - void HandleNetworkPrefabDestroy(NetworkObject networkObject); + /// + /// Client Side Only + /// Once an implementation is registered with the , this method will be called every time + /// a Network Prefab associated is spawned on clients (excluding host since it is the server). + /// + /// Note on Pooling: If you are using a NetworkObject pool, don't forget to make the NetworkObject active + /// via the method. + /// + /// the owner of this NetworkObject + /// the initial/default position for this NetworkObject + /// the initial/default rotation for this NetworkObject + /// + NetworkObject ClientInstantiateOverride(ulong ownerClientId, Vector3 position, Quaternion rotation); + + /// + /// Client and Server + /// Once an implementation is registered with the , this method will be called every time + /// a Network Prefab associated is destroyed. + /// If is invoked with the default destroy parameter (i.e. false) then this method will not be invoked. + /// + /// Note on Pooling: When invoked, you do not need to despawn or destroy the NetworkObject as long as you want your pool to persist. + /// The most common approach is to make the inactive by calling . + /// + /// The NetworkObject being destroyed (see notes on + void DestroyOverride(NetworkObject networkObject); } /// @@ -30,21 +53,21 @@ public class NetworkPrefabHandler private readonly Dictionary m_PrefabInstanceToPrefabAsset = new Dictionary(); /// - /// Use a GameObject to add a INetworkPrefabInstanceHandler derived class + /// Use a to register a class that implements the interface with the /// - /// - /// - /// + /// the of the network prefab asset to be overridden + /// class that implements the interface to be registered + /// true (registered) false (failed to register) public bool AddHandler(GameObject networkPrefabAsset, INetworkPrefabInstanceHandler instanceHandler) { return AddHandler(networkPrefabAsset.GetComponent().GlobalObjectIdHash, instanceHandler); } /// - /// Use a NetworkObject to add a INetworkPrefabInstanceHandler derived class + /// Use a to register a class that implements the interface with the /// - /// - /// + /// the of the network prefab asset to be overridden + /// the class that implements the interface to be registered /// public bool AddHandler(NetworkObject prefabAssetNetworkObject, INetworkPrefabInstanceHandler instanceHandler) { @@ -52,16 +75,16 @@ public bool AddHandler(NetworkObject prefabAssetNetworkObject, INetworkPrefabIns } /// - /// Use a networkPrefabHash(GlobalObjectIdHash) to add a INetworkPrefabInstanceHandler derived class + /// Use a to register a class that implements the interface with the /// - /// - /// + /// the value of the network prefab asset being overridden + /// a class that implements the interface /// - public bool AddHandler(uint networkPrefabHash, INetworkPrefabInstanceHandler instanceHandler) + public bool AddHandler(uint globalObjectIdHash, INetworkPrefabInstanceHandler instanceHandler) { - if (!m_PrefabAssetToPrefabHandler.ContainsKey(networkPrefabHash)) + if (!m_PrefabAssetToPrefabHandler.ContainsKey(globalObjectIdHash)) { - m_PrefabAssetToPrefabHandler.Add(networkPrefabHash, instanceHandler); + m_PrefabAssetToPrefabHandler.Add(globalObjectIdHash, instanceHandler); return true; } @@ -69,9 +92,9 @@ public bool AddHandler(uint networkPrefabHash, INetworkPrefabInstanceHandler ins } /// - /// Use the GameObject of the network prefab asset to remove a INetworkPrefabInstanceHandler derived class + /// Use the of the overridden network prefab asset to remove a registered class that implements the interface. /// - /// + /// of the network prefab asset that was being overridden /// true or false public bool RemoveHandler(GameObject networkPrefabAsset) { @@ -79,7 +102,7 @@ public bool RemoveHandler(GameObject networkPrefabAsset) } /// - /// Use the NetworkObject of the network prefab asset to remove a INetworkPrefabInstanceHandler derived class + /// Use the of the overridden network prefab asset to remove a registered class that implements the interface. /// /// /// true or false @@ -89,18 +112,18 @@ public bool RemoveHandler(NetworkObject networkObject) } /// - /// Use the networkPrefabHash(GlobalObjectIdHash) of the network prefab asset to remove a INetworkPrefabInstanceHandler derived class + /// Use the of the overridden network prefab asset to remove a registered class that implements the interface. /// /// /// true or false - public bool RemoveHandler(uint networkPrefabHash) + public bool RemoveHandler(uint globalObjectIdHash) { - if (m_PrefabInstanceToPrefabAsset.ContainsValue(networkPrefabHash)) + if (m_PrefabInstanceToPrefabAsset.ContainsValue(globalObjectIdHash)) { uint networkPrefabHashKey = 0; foreach (var kvp in m_PrefabInstanceToPrefabAsset) { - if (kvp.Value == networkPrefabHash) + if (kvp.Value == globalObjectIdHash) { networkPrefabHashKey = kvp.Key; break; @@ -109,7 +132,7 @@ public bool RemoveHandler(uint networkPrefabHash) m_PrefabInstanceToPrefabAsset.Remove(networkPrefabHashKey); } - return m_PrefabAssetToPrefabHandler.Remove(networkPrefabHash); + return m_PrefabAssetToPrefabHandler.Remove(globalObjectIdHash); } /// @@ -155,7 +178,7 @@ internal NetworkObject HandleNetworkPrefabSpawn(uint networkPrefabAssetHash, ulo { if (m_PrefabAssetToPrefabHandler.ContainsKey(networkPrefabAssetHash)) { - var networkObjectInstance = m_PrefabAssetToPrefabHandler[networkPrefabAssetHash].HandleNetworkPrefabSpawn(ownerClientId, position, rotation); + var networkObjectInstance = m_PrefabAssetToPrefabHandler[networkPrefabAssetHash].ClientInstantiateOverride(ownerClientId, position, rotation); //Now we must make sure this alternate PrefabAsset spawned in place of the prefab asset with the networkPrefabAssetHash (GlobalObjectIdHash) //is registered and linked to the networkPrefabAssetHash so during the HandleNetworkPrefabDestroy process we can identify the alternate prefab asset. @@ -172,8 +195,8 @@ internal NetworkObject HandleNetworkPrefabSpawn(uint networkPrefabAssetHash, ulo /// /// Will invoke the NetworkPrefabInstanceHandler derived class HandleNetworkPrefabDestroy method - /// Note: On the client, when a custom NetworkObject is instantiated in place of the original PrefabAsset - /// the newly generated NetworkObject will + /// Note [both the client and server]: A NetworkObject that was instantiated via a INetworkPrefabInstanceHandler implementation + /// will have this called in place of being destroyed. /// /// internal void HandleNetworkPrefabDestroy(NetworkObject networkObjectInstance) @@ -184,7 +207,7 @@ internal void HandleNetworkPrefabDestroy(NetworkObject networkObjectInstance) var networkPrefabAssetHash = m_PrefabInstanceToPrefabAsset[networkObjectInstanceHash]; if (m_PrefabAssetToPrefabHandler.ContainsKey(networkPrefabAssetHash)) { - m_PrefabAssetToPrefabHandler[networkPrefabAssetHash].HandleNetworkPrefabDestroy(networkObjectInstance); + m_PrefabAssetToPrefabHandler[networkPrefabAssetHash].DestroyOverride(networkObjectInstance); } } } diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkPrefabHandlerTests.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkPrefabHandlerTests.cs index 1cd61bc301..68e213e332 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkPrefabHandlerTests.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkPrefabHandlerTests.cs @@ -164,7 +164,7 @@ public class NetworkPrefaInstanceHandler : INetworkPrefabInstanceHandler private List m_Instances; - public NetworkObject HandleNetworkPrefabSpawn(ulong ownerClientId, Vector3 position, Quaternion rotation) + public NetworkObject ClientInstantiateOverride(ulong ownerClientId, Vector3 position, Quaternion rotation) { var networkObjectInstance = UnityEngine.Object.Instantiate(m_NetworkObject.gameObject).GetComponent(); networkObjectInstance.transform.position = position; @@ -173,7 +173,7 @@ public NetworkObject HandleNetworkPrefabSpawn(ulong ownerClientId, Vector3 posit return networkObjectInstance; } - public void HandleNetworkPrefabDestroy(NetworkObject networkObject) + public void DestroyOverride(NetworkObject networkObject) { var instancesContainsNetworkObject = m_Instances.Contains(networkObject); Assert.True(instancesContainsNetworkObject); diff --git a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs index ac792f8760..f04bc4807f 100644 --- a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs +++ b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs @@ -337,14 +337,14 @@ private IEnumerator SpawnObjects() public class MyCustomPrefabSpawnHandler : INetworkPrefabInstanceHandler { private NetworkPrefabPool m_PrefabPool; - public NetworkObject HandleNetworkPrefabSpawn(ulong ownerClientId, Vector3 position, Quaternion rotation) + public NetworkObject ClientInstantiateOverride(ulong ownerClientId, Vector3 position, Quaternion rotation) { var obj = m_PrefabPool.GetObject(); obj.transform.position = position; obj.transform.rotation = rotation; return obj.GetComponent(); } - public void HandleNetworkPrefabDestroy(NetworkObject networkObject) + public void DestroyOverride(NetworkObject networkObject) { networkObject.transform.position = Vector3.zero; networkObject.gameObject.SetActive(false); diff --git a/testproject/Assets/Tests/Runtime/MultiprocessRuntime/Helpers/CustomPrefabSpawnerForPerformanceTests.cs b/testproject/Assets/Tests/Runtime/MultiprocessRuntime/Helpers/CustomPrefabSpawnerForPerformanceTests.cs index d3a343f0a4..586f9558f7 100644 --- a/testproject/Assets/Tests/Runtime/MultiprocessRuntime/Helpers/CustomPrefabSpawnerForPerformanceTests.cs +++ b/testproject/Assets/Tests/Runtime/MultiprocessRuntime/Helpers/CustomPrefabSpawnerForPerformanceTests.cs @@ -18,7 +18,7 @@ public CustomPrefabSpawnerForPerformanceTests(T prefabToSpawn, int maxObjectsToS m_OnRelease = onRelease; } - public NetworkObject HandleNetworkPrefabSpawn(ulong ownerClientId, Vector3 position, Quaternion rotation) + public NetworkObject ClientInstantiateOverride(ulong ownerClientId, Vector3 position, Quaternion rotation) { var netBehaviour = m_ObjectPool.Get(); var networkObject = netBehaviour.NetworkObject; @@ -29,7 +29,7 @@ public NetworkObject HandleNetworkPrefabSpawn(ulong ownerClientId, Vector3 posit return networkObject; } - public void HandleNetworkPrefabDestroy(NetworkObject networkObject) + public void DestroyOverride(NetworkObject networkObject) { var behaviour = networkObject.gameObject.GetComponent(); // todo expensive, only used in teardown for now, should optimize eventually m_OnRelease(behaviour); From e0f6143a94a49bdeeaa063fc248cb6491ce93139 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity <73188597+NoelStephensUnity@users.noreply.github.com> Date: Fri, 23 Jul 2021 15:12:51 -0500 Subject: [PATCH 02/11] style Minor updates on the ClientInstantiateOverride parameter names --- .../Runtime/Spawning/NetworkPrefabHandler.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkPrefabHandler.cs b/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkPrefabHandler.cs index a504750560..10b0899730 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkPrefabHandler.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkPrefabHandler.cs @@ -17,9 +17,9 @@ public interface INetworkPrefabInstanceHandler /// Note on Pooling: If you are using a NetworkObject pool, don't forget to make the NetworkObject active /// via the method. /// - /// the owner of this NetworkObject - /// the initial/default position for this NetworkObject - /// the initial/default rotation for this NetworkObject + /// the owner for the to be instantiated + /// the initial/default position for the to be instantiated + /// the initial/default rotation for the to be instantiated /// NetworkObject ClientInstantiateOverride(ulong ownerClientId, Vector3 position, Quaternion rotation); @@ -32,7 +32,7 @@ public interface INetworkPrefabInstanceHandler /// Note on Pooling: When invoked, you do not need to despawn or destroy the NetworkObject as long as you want your pool to persist. /// The most common approach is to make the inactive by calling . /// - /// The NetworkObject being destroyed (see notes on + /// The being destroyed void DestroyOverride(NetworkObject networkObject); } From 36e8405d3342312995d0f544feaa6350243f28b2 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity <73188597+NoelStephensUnity@users.noreply.github.com> Date: Wed, 28 Jul 2021 14:56:34 -0500 Subject: [PATCH 03/11] refactor and style Renamed the interface methods. Updated comments. Refactored NetworkPrefabHandler to handle GitHub Issue 990 as well as made adjustments to be able to send the appropriate GlobalObjectIdHash as a host. This also includes a public facing method in the NetworkManager to be able to lookup a NetworkManager defined NetworkPrefab Override for some associated cases relating to Host mode and NetworkPrefabHandlers and NetworkPrefab Overrides. Made adjustments to the SceneTransitioning test and associated scenes and assets. --- .../Runtime/Core/NetworkManager.cs | 33 ++++- .../Runtime/Core/NetworkObject.cs | 19 ++- .../Runtime/Spawning/NetworkPrefabHandler.cs | 139 ++++++++++++++---- .../Runtime/Spawning/NetworkSpawnManager.cs | 2 +- .../Runtime/NetworkPrefabHandlerTests.cs | 4 +- testproject/Assets/Prefabs/Player.prefab | 17 +-- .../SceneTransitioningTest.unity | 10 +- .../Scripts/GenericNetworkObjectBehaviour.cs | 3 +- .../Tests/Manual/Scripts/NetworkPrefabPool.cs | 60 ++++++-- .../CustomPrefabSpawnerForPerformanceTests.cs | 4 +- .../Support/SpawnRpcDespawnInstanceHandler.cs | 10 +- 11 files changed, 229 insertions(+), 72 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs index 3ab86256c7..e708751939 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs @@ -60,7 +60,7 @@ public class NetworkManager : MonoBehaviour, INetworkUpdateSystem, IProfilableTr internal static bool UseSnapshot = false; private const double k_TimeSyncFrequency = 1.0d; // sync every second, TODO will be removed once timesync is done via snapshots - + internal MessageQueueContainer MessageQueueContainer { get; private set; } @@ -82,6 +82,37 @@ public NetworkPrefabHandler PrefabHandler } } + /// + /// Returns the to use as the override as could be defined within the NetworkPrefab list + /// Note: This should be used to create pools (with components) + /// under the scenario where you are using the Host model as it spawns everything locally. As such, the override + /// will not be applied when spawning locally on a Host. + /// Related Classes and Interfaces: + /// + /// + /// + /// the to be checked for a defined NetworkPrefab override + /// a that is either the override or if no overrides exist it returns the same as the one passed in as a parameter + public GameObject GetNetworkPrefabOverride(GameObject gameObject) + { + var networkObject = gameObject.GetComponent(); + if (networkObject != null) + { + if (NetworkConfig.NetworkPrefabOverrideLinks.ContainsKey(networkObject.GlobalObjectIdHash)) + { + switch (NetworkConfig.NetworkPrefabOverrideLinks[networkObject.GlobalObjectIdHash].Override) + { + case NetworkPrefabOverride.Hash: + case NetworkPrefabOverride.Prefab: + { + return NetworkConfig.NetworkPrefabOverrideLinks[networkObject.GlobalObjectIdHash].OverridingTargetPrefab; + } + } + } + } + return gameObject; + } + public NetworkTimeSystem NetworkTimeSystem { get; private set; } public NetworkTickSystem NetworkTickSystem { get; private set; } diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs index c3a0c16c91..165ef0999f 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs @@ -456,7 +456,7 @@ private void SpawnInternal(Stream spawnPayload, bool destroyWithScene, ulong? ow /// Spawns this GameObject across the network. Can only be called from the Server /// /// The writer containing the spawn payload - /// Should the object be destroyd when the scene is changed + /// Should the object be destroyed when the scene is changed public void Spawn(Stream spawnPayload = null, bool destroyWithScene = false) { SpawnInternal(spawnPayload, destroyWithScene, null, false); @@ -915,7 +915,7 @@ internal void SerializeSceneObject(NetworkWriter writer, ulong targetClientId) writer.WriteBool(IsSceneObject ?? true); // Write the hash for this NetworkObject - writer.WriteUInt32Packed(GlobalObjectIdHash); + writer.WriteUInt32Packed(HostCheckForGlobalObjectIdHashOverride()); if (IncludeTransformWhenSpawning == null || IncludeTransformWhenSpawning(OwnerClientId)) { @@ -1054,5 +1054,20 @@ internal static NetworkObject DeserializeSceneObject(NetworkBuffer objectStream, return networkObject; } + + /// + /// Only applies to Host mode. + /// Will return the registered source NetworkPrefab's GlobalObjectIdHash if one exists. + /// Server and Clients will always return the NetworkObject's GlobalObjectIdHash. + /// + /// + internal uint HostCheckForGlobalObjectIdHashOverride() + { + if (NetworkManager.IsHost && NetworkManager.PrefabHandler.ContainsHandler(this)) + { + return NetworkManager.PrefabHandler.GetSourceGlobalObjectIdHash(GlobalObjectIdHash); + } + return GlobalObjectIdHash; + } } } diff --git a/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkPrefabHandler.cs b/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkPrefabHandler.cs index 10b0899730..4f41a37683 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkPrefabHandler.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkPrefabHandler.cs @@ -12,7 +12,10 @@ public interface INetworkPrefabInstanceHandler /// /// Client Side Only /// Once an implementation is registered with the , this method will be called every time - /// a Network Prefab associated is spawned on clients (excluding host since it is the server). + /// a Network Prefab associated is spawned on clients + /// + /// Note On Hosts: Use the + /// method to register all targeted NetworkPrefab overrides manually since the host will be acting as both a server and client. /// /// Note on Pooling: If you are using a NetworkObject pool, don't forget to make the NetworkObject active /// via the method. @@ -21,23 +24,28 @@ public interface INetworkPrefabInstanceHandler /// the initial/default position for the to be instantiated /// the initial/default rotation for the to be instantiated /// - NetworkObject ClientInstantiateOverride(ulong ownerClientId, Vector3 position, Quaternion rotation); + NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation); /// - /// Client and Server - /// Once an implementation is registered with the , this method will be called every time - /// a Network Prefab associated is destroyed. - /// If is invoked with the default destroy parameter (i.e. false) then this method will not be invoked. + /// Invoked on Client and Server + /// Once an implementation is registered with the , this method will be called when + /// a Network Prefab associated is: + /// + /// Server Side: destroyed or despawned with the destroy parameter equal to true + /// If is invoked with the default destroy parameter (i.e. false) then this method will NOT be invoked! /// - /// Note on Pooling: When invoked, you do not need to despawn or destroy the NetworkObject as long as you want your pool to persist. + /// Client Side: destroyed when the client receives a destroy object message from the server or host. + /// + /// Note on Pooling: When this method is invoked, you do not need to destroy the NetworkObject as long as you want your pool to persist. /// The most common approach is to make the inactive by calling . /// /// The being destroyed - void DestroyOverride(NetworkObject networkObject); + void Destroy(NetworkObject networkObject); } /// /// Primary handler to add or remove customized spawn and destroy handlers for a network prefab (i.e. a prefab with a NetworkObject component) + /// Register custom prefab handlers by implementing the interface. /// public class NetworkPrefabHandler { @@ -91,11 +99,65 @@ public bool AddHandler(uint globalObjectIdHash, INetworkPrefabInstanceHandler in return false; } + /// + /// HOST ONLY! + /// Since a host is unique and is considered both a client and a server, for each source NetworkPrefab you must manually + /// register all potential target overrides that have the component. + /// + /// source NetworkPrefab to be overridden + /// one or more NetworkPrefabs could be used to override the source NetworkPrefab + public void RegisterHostGlobalObjectIdHashValues(GameObject sourceNetworkPrefab, List networkPrefabOverrides) + { + if(NetworkManager.Singleton.IsListening) + { + if (NetworkManager.Singleton.IsHost) + { + var sourceNetworkObject = sourceNetworkPrefab.GetComponent(); + if (sourceNetworkPrefab != null) + { + var sourceGlobalObjectIdHash = sourceNetworkObject.GlobalObjectIdHash; + // Now we register all + foreach (var gameObject in networkPrefabOverrides) + { + var targetNetworkObject = gameObject.GetComponent(); + if(targetNetworkObject != null) + { + if (!m_PrefabInstanceToPrefabAsset.ContainsKey(targetNetworkObject.GlobalObjectIdHash)) + { + m_PrefabInstanceToPrefabAsset.Add(targetNetworkObject.GlobalObjectIdHash, sourceGlobalObjectIdHash); + } + else + { + Debug.LogWarning($"{targetNetworkObject.name} appears to be a duplicate entry!"); + } + } + else + { + throw new System.Exception($"{targetNetworkObject.name} does not have a {nameof(NetworkObject)} component!"); + } + } + } + else + { + throw new System.Exception($"{sourceNetworkPrefab.name} does not have a {nameof(NetworkObject)} component!"); + } + } + else + { + throw new System.Exception($"You should only call {nameof(RegisterHostGlobalObjectIdHashValues)} as a Host!"); + } + } + else + { + throw new System.Exception($"You can only call {nameof(RegisterHostGlobalObjectIdHashValues)} once NetworkManager is listening!"); + } + } + /// /// Use the of the overridden network prefab asset to remove a registered class that implements the interface. /// /// of the network prefab asset that was being overridden - /// true or false + /// true (success) or false (failure) public bool RemoveHandler(GameObject networkPrefabAsset) { return RemoveHandler(networkPrefabAsset.GetComponent().GlobalObjectIdHash); @@ -104,8 +166,8 @@ public bool RemoveHandler(GameObject networkPrefabAsset) /// /// Use the of the overridden network prefab asset to remove a registered class that implements the interface. /// - /// - /// true or false + /// of the source NetworkPrefab that was being overridden + /// true (success) or false (failure) public bool RemoveHandler(NetworkObject networkObject) { return RemoveHandler(networkObject.GlobalObjectIdHash); @@ -114,8 +176,8 @@ public bool RemoveHandler(NetworkObject networkObject) /// /// Use the of the overridden network prefab asset to remove a registered class that implements the interface. /// - /// - /// true or false + /// of the source NetworkPrefab that was being overridden + /// true (success) or false (failure) public bool RemoveHandler(uint globalObjectIdHash) { if (m_PrefabInstanceToPrefabAsset.ContainsValue(globalObjectIdHash)) @@ -136,7 +198,7 @@ public bool RemoveHandler(uint globalObjectIdHash) } /// - /// Check to see if a GameObject with a NetworkObject component has an INetworkPrefabInstanceHandler derived class associated with it + /// Check to see if a with a is registered to an implementation /// /// /// true or false @@ -146,7 +208,7 @@ internal bool ContainsHandler(GameObject networkPrefab) } /// - /// Check to see if a NetworkObject component has an INetworkPrefabInstanceHandler derived class associated with it + /// Check to see if a is registered to an implementation /// /// /// true or false @@ -156,7 +218,7 @@ internal bool ContainsHandler(NetworkObject networkObject) } /// - /// Check to see if a networkPrefabHash(GlobalObjectIdHash) component has an INetworkPrefabInstanceHandler derived class associated with it + /// Check to see if a is registered to an implementation /// /// /// true or false @@ -166,8 +228,27 @@ internal bool ContainsHandler(uint networkPrefabHash) } /// - /// Will return back a NetworkObject generated via the INetworkPrefabInstanceHandler derived class associated with the networkPrefabAssetHash - /// Invoked only on the client side and called within NetworkSpawnManager.CreateLocalNetworkObject + /// Returns the source NetworkPrefab's + /// + /// + /// + internal uint GetSourceGlobalObjectIdHash(uint networkPrefabHash) + { + if(m_PrefabAssetToPrefabHandler.ContainsKey(networkPrefabHash)) + { + return networkPrefabHash; + } + else if(m_PrefabInstanceToPrefabAsset.ContainsKey(networkPrefabHash)) + { + return m_PrefabInstanceToPrefabAsset[networkPrefabHash]; + } + + return 0; + } + + /// + /// Will return back a generated via an implementation + /// Note: Invoked only on the client side and called within NetworkSpawnManager.CreateLocalNetworkObject /// /// typically the "server-side" asset's prefab hash /// @@ -178,7 +259,7 @@ internal NetworkObject HandleNetworkPrefabSpawn(uint networkPrefabAssetHash, ulo { if (m_PrefabAssetToPrefabHandler.ContainsKey(networkPrefabAssetHash)) { - var networkObjectInstance = m_PrefabAssetToPrefabHandler[networkPrefabAssetHash].ClientInstantiateOverride(ownerClientId, position, rotation); + var networkObjectInstance = m_PrefabAssetToPrefabHandler[networkPrefabAssetHash].Instantiate(ownerClientId, position, rotation); //Now we must make sure this alternate PrefabAsset spawned in place of the prefab asset with the networkPrefabAssetHash (GlobalObjectIdHash) //is registered and linked to the networkPrefabAssetHash so during the HandleNetworkPrefabDestroy process we can identify the alternate prefab asset. @@ -194,22 +275,28 @@ internal NetworkObject HandleNetworkPrefabSpawn(uint networkPrefabAssetHash, ulo } /// - /// Will invoke the NetworkPrefabInstanceHandler derived class HandleNetworkPrefabDestroy method - /// Note [both the client and server]: A NetworkObject that was instantiated via a INetworkPrefabInstanceHandler implementation - /// will have this called in place of being destroyed. + /// Will invoke the implementation's Destroy method /// /// internal void HandleNetworkPrefabDestroy(NetworkObject networkObjectInstance) { var networkObjectInstanceHash = networkObjectInstance.GlobalObjectIdHash; - if (m_PrefabInstanceToPrefabAsset.ContainsKey(networkObjectInstanceHash)) + if (networkObjectInstance.NetworkManager.IsClient) { - var networkPrefabAssetHash = m_PrefabInstanceToPrefabAsset[networkObjectInstanceHash]; - if (m_PrefabAssetToPrefabHandler.ContainsKey(networkPrefabAssetHash)) + if (m_PrefabInstanceToPrefabAsset.ContainsKey(networkObjectInstanceHash)) { - m_PrefabAssetToPrefabHandler[networkPrefabAssetHash].DestroyOverride(networkObjectInstance); + var networkPrefabAssetHash = m_PrefabInstanceToPrefabAsset[networkObjectInstanceHash]; + if (m_PrefabAssetToPrefabHandler.ContainsKey(networkPrefabAssetHash)) + { + m_PrefabAssetToPrefabHandler[networkPrefabAssetHash].Destroy(networkObjectInstance); + } } } + else // Otherwise for server only (i.e. not host) the NetworkObject is the source NetworkPrefab + if (m_PrefabAssetToPrefabHandler.ContainsKey(networkObjectInstanceHash)) + { + m_PrefabAssetToPrefabHandler[networkObjectInstanceHash].Destroy(networkObjectInstance); + } } } } diff --git a/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs b/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs index a1030bb508..a976af0e1d 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs @@ -416,7 +416,7 @@ internal void WriteSpawnCallForObject(PooledNetworkWriter writer, ulong clientId } writer.WriteBool(networkObject.IsSceneObject ?? true); - writer.WriteUInt32Packed(networkObject.GlobalObjectIdHash); + writer.WriteUInt32Packed(networkObject.HostCheckForGlobalObjectIdHashOverride()); if (networkObject.IncludeTransformWhenSpawning == null || networkObject.IncludeTransformWhenSpawning(clientId)) { diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkPrefabHandlerTests.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkPrefabHandlerTests.cs index 68e213e332..79e093c8ec 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkPrefabHandlerTests.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkPrefabHandlerTests.cs @@ -164,7 +164,7 @@ public class NetworkPrefaInstanceHandler : INetworkPrefabInstanceHandler private List m_Instances; - public NetworkObject ClientInstantiateOverride(ulong ownerClientId, Vector3 position, Quaternion rotation) + public NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation) { var networkObjectInstance = UnityEngine.Object.Instantiate(m_NetworkObject.gameObject).GetComponent(); networkObjectInstance.transform.position = position; @@ -173,7 +173,7 @@ public NetworkObject ClientInstantiateOverride(ulong ownerClientId, Vector3 posi return networkObjectInstance; } - public void DestroyOverride(NetworkObject networkObject) + public void Destroy(NetworkObject networkObject) { var instancesContainsNetworkObject = m_Instances.Contains(networkObject); Assert.True(instancesContainsNetworkObject); diff --git a/testproject/Assets/Prefabs/Player.prefab b/testproject/Assets/Prefabs/Player.prefab index b9f7e6b43b..f6f20de9ab 100644 --- a/testproject/Assets/Prefabs/Player.prefab +++ b/testproject/Assets/Prefabs/Player.prefab @@ -51,17 +51,10 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: e96cb6065543e43c4a752faaa1468eb1, type: 3} m_Name: m_EditorClassIdentifier: - TransformAuthority: 1 - FixedSendsPerSecond: 15 - InterpolatePosition: 1 - SnapDistance: 10 - InterpolateServer: 1 - MinMeters: 0.15 - MinDegrees: 1.5 - MinSize: 0.15 - Channel: 2 - m_UseLocal: - m_InternalValue: 0 + Authority: 1 + Channel: 0 + InLocalSpace: 0 + FixedSendsPerSecond: 5 --- !u!114 &-3775814466963834669 MonoBehaviour: m_ObjectHideFlags: 0 @@ -75,9 +68,9 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: GlobalObjectIdHash: 951099334 - m_MarkedAsSceneObject: 0 AlwaysReplicateAsRoot: 0 DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!33 &4079352819444256610 MeshFilter: m_ObjectHideFlags: 0 diff --git a/testproject/Assets/Tests/Manual/SceneTransitioning/SceneTransitioningTest.unity b/testproject/Assets/Tests/Manual/SceneTransitioning/SceneTransitioningTest.unity index de97ee675c..77971458c5 100644 --- a/testproject/Assets/Tests/Manual/SceneTransitioning/SceneTransitioningTest.unity +++ b/testproject/Assets/Tests/Manual/SceneTransitioning/SceneTransitioningTest.unity @@ -1024,10 +1024,7 @@ MonoBehaviour: SourceHashToOverride: 0 OverridingTargetPrefab: {fileID: 8059323910720821982, guid: d143db9172e1f234e99d450286b77695, type: 3} - ReceiveTickrate: 64 - NetworkTickIntervalSec: 0.05 - MaxReceiveEventsPerTickRate: 500 - EventTickrate: 64 + TickRate: 30 ClientConnectionBufferTimeout: 10 ConnectionApproval: 0 ConnectionData: @@ -1041,7 +1038,6 @@ MonoBehaviour: NetworkIdRecycleDelay: 120 RpcHashSize: 0 LoadSceneTimeOut: 120 - EnableMessageBuffering: 1 MessageBufferTimeout: 20 EnableNetworkLogs: 1 --- !u!114 &1024114719 @@ -1118,7 +1114,7 @@ MonoBehaviour: SpawnsPerSecond: 5 PoolSize: 128 ObjectSpeed: 8 - EnableHandler: 0 + EnableHandler: 1 RegisterUsingNetworkObject: 0 ServerObjectToPool: {fileID: 771575417923360811, guid: c0a45bdb516f341498d933b7a7ed4fc1, type: 3} @@ -1155,6 +1151,7 @@ MonoBehaviour: GlobalObjectIdHash: 2782806529 AlwaysReplicateAsRoot: 0 DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!1 &1332123091 GameObject: m_ObjectHideFlags: 0 @@ -2553,6 +2550,7 @@ MonoBehaviour: GlobalObjectIdHash: 2267100048 AlwaysReplicateAsRoot: 0 DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!1001 &2848221156282925290 PrefabInstance: m_ObjectHideFlags: 0 diff --git a/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs b/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs index 5ae42e1a36..646b5849e0 100644 --- a/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs +++ b/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs @@ -86,8 +86,7 @@ private void OnTriggerEnter(Collider other) } else { - NetworkObject.Despawn(); - NetworkObject.gameObject.SetActive(false); + NetworkObject.Despawn(true); } } } diff --git a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs index f04bc4807f..a0148553c8 100644 --- a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs +++ b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs @@ -53,9 +53,6 @@ private void OnEnable() { SpawnSlider.gameObject.SetActive(false); } - - //This registers early under the condition of a scene transition - RegisterCustomPrefabHandler(); } /// @@ -85,6 +82,21 @@ private void RegisterCustomPrefabHandler() } } + + private void DeRegisterCustomPrefabHandler() + { + if (EnableHandler && NetworkManager && NetworkManager.PrefabHandler != null && m_MyCustomPrefabSpawnHandler != null) + { + NetworkManager.PrefabHandler.RemoveHandler(ServerObjectToPool); + if (IsClient && m_ObjectToSpawn != null) + { + NetworkManager.PrefabHandler.RemoveHandler(m_ObjectToSpawn); + } + } + } + + + /// /// When disabled, stop spawning objects /// @@ -97,6 +109,8 @@ private void OnDisable() NetworkManager.Singleton.PrefabHandler.RemoveHandler(no); m_MyCustomPrefabSpawnHandler = null; } + + } /// @@ -123,10 +137,6 @@ private void Start() { SwitchScene.OnSceneSwitchBegin += OnSceneSwitchBegin; } - - //Call this again in case we didn't have access to the NetworkManager already (i.e. first scene loaded) - RegisterCustomPrefabHandler(); - } /// @@ -135,6 +145,7 @@ private void Start() /// private void OnSceneSwitchBegin() { + DeRegisterCustomPrefabHandler(); if (IsServer) { StopCoroutine(SpawnObjects()); @@ -146,7 +157,7 @@ private void OnSceneSwitchBegin() var networkObject = obj.GetComponent(); if (networkObject.IsSpawned) { - networkObject.Despawn(); + networkObject.Despawn(true); } Destroy(obj); } @@ -180,11 +191,30 @@ public override void OnNetworkSpawn() /// public void InitializeObjectPool() { + // Base construction and registration of the custom prefab handler. + RegisterCustomPrefabHandler(); + // Default to the server side object m_ObjectToSpawn = ServerObjectToPool; - if (!IsServer && EnableHandler) + + // Host and Client need to do an extra step + if (IsClient) { - m_ObjectToSpawn = ClientObjectToPool; + if (EnableHandler && ClientObjectToPool != null) + { + m_ObjectToSpawn = ClientObjectToPool; + } + else + { + m_ObjectToSpawn = NetworkManager.GetNetworkPrefabOverride(ServerObjectToPool); + } + + // Since the host should spawn the override, we need to register the host to link it to the originally registered ServerObjectToPool + if (IsHost) + { + // While this seems redundant, we could theoretically have several objects that we could potentially be spawning + NetworkManager.PrefabHandler.RegisterHostGlobalObjectIdHashValues(ServerObjectToPool, new List() { m_ObjectToSpawn }); + } } m_ObjectPool = new List(PoolSize); @@ -258,7 +288,7 @@ public void UpdateSpawnsPerSecond() SpawnSliderValueText.text = SpawnsPerSecond.ToString(); // Handle case where the initial value is set to zero and so coroutine needs to be started - if(SpawnsPerSecond > 0 && !m_IsSpawningObjects) + if (SpawnsPerSecond > 0 && !m_IsSpawningObjects) { StartSpawningBoxes(); } @@ -271,6 +301,8 @@ public void UpdateSpawnsPerSecond() } } + private bool m_HasHostRegistered; + /// /// Coroutine to spawn boxes /// @@ -289,6 +321,8 @@ private IEnumerator SpawnObjects() } m_IsSpawningObjects = true; + + while (m_IsSpawningObjects) { //Start spawning if auto spawn is enabled @@ -337,14 +371,14 @@ private IEnumerator SpawnObjects() public class MyCustomPrefabSpawnHandler : INetworkPrefabInstanceHandler { private NetworkPrefabPool m_PrefabPool; - public NetworkObject ClientInstantiateOverride(ulong ownerClientId, Vector3 position, Quaternion rotation) + public NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation) { var obj = m_PrefabPool.GetObject(); obj.transform.position = position; obj.transform.rotation = rotation; return obj.GetComponent(); } - public void DestroyOverride(NetworkObject networkObject) + public void Destroy(NetworkObject networkObject) { networkObject.transform.position = Vector3.zero; networkObject.gameObject.SetActive(false); diff --git a/testproject/Assets/Tests/Runtime/MultiprocessRuntime/Helpers/CustomPrefabSpawnerForPerformanceTests.cs b/testproject/Assets/Tests/Runtime/MultiprocessRuntime/Helpers/CustomPrefabSpawnerForPerformanceTests.cs index 586f9558f7..4d66cfe308 100644 --- a/testproject/Assets/Tests/Runtime/MultiprocessRuntime/Helpers/CustomPrefabSpawnerForPerformanceTests.cs +++ b/testproject/Assets/Tests/Runtime/MultiprocessRuntime/Helpers/CustomPrefabSpawnerForPerformanceTests.cs @@ -18,7 +18,7 @@ public CustomPrefabSpawnerForPerformanceTests(T prefabToSpawn, int maxObjectsToS m_OnRelease = onRelease; } - public NetworkObject ClientInstantiateOverride(ulong ownerClientId, Vector3 position, Quaternion rotation) + public NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation) { var netBehaviour = m_ObjectPool.Get(); var networkObject = netBehaviour.NetworkObject; @@ -29,7 +29,7 @@ public NetworkObject ClientInstantiateOverride(ulong ownerClientId, Vector3 posi return networkObject; } - public void DestroyOverride(NetworkObject networkObject) + public void Destroy(NetworkObject networkObject) { var behaviour = networkObject.gameObject.GetComponent(); // todo expensive, only used in teardown for now, should optimize eventually m_OnRelease(behaviour); diff --git a/testproject/Assets/Tests/Runtime/Support/SpawnRpcDespawnInstanceHandler.cs b/testproject/Assets/Tests/Runtime/Support/SpawnRpcDespawnInstanceHandler.cs index 882c6cbce5..e884ba4085 100644 --- a/testproject/Assets/Tests/Runtime/Support/SpawnRpcDespawnInstanceHandler.cs +++ b/testproject/Assets/Tests/Runtime/Support/SpawnRpcDespawnInstanceHandler.cs @@ -1,4 +1,4 @@ -using MLAPI; +using MLAPI; using MLAPI.Configuration; using MLAPI.Logging; using MLAPI.Spawning; @@ -19,7 +19,7 @@ public SpawnRpcDespawnInstanceHandler(uint prefabHash) m_PrefabHash = prefabHash; } - public NetworkObject HandleNetworkPrefabSpawn(ulong ownerClientId, Vector3 position, Quaternion rotation) + public NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation) { WasSpawned = true; Assert.AreEqual(SpawnRpcDespawn.TestStage, NetworkUpdateLoop.UpdateStage); @@ -53,12 +53,12 @@ public NetworkObject HandleNetworkPrefabSpawn(ulong ownerClientId, Vector3 posit } // Otherwise, instantiate an instance of the NetworkPrefab linked to the prefabHash - var networkObject = UnityEngine.Object.Instantiate(networkPrefabReference, position, rotation).GetComponent(); + var networkObject = Object.Instantiate(networkPrefabReference, position, rotation).GetComponent(); return networkObject; } - public void HandleNetworkPrefabDestroy(NetworkObject networkObject) + public void Destroy(NetworkObject networkObject) { WasDestroyed = true; if (networkObject.NetworkManager.IsClient) @@ -66,7 +66,7 @@ public void HandleNetworkPrefabDestroy(NetworkObject networkObject) Assert.AreEqual(NetworkUpdateStage.PostLateUpdate, NetworkUpdateLoop.UpdateStage); } - GameObject.Destroy(networkObject.gameObject); + Object.Destroy(networkObject.gameObject); } } } From 6a940ceb1a71f557729ea58bc65c502eb9deb50f Mon Sep 17 00:00:00 2001 From: NoelStephensUnity <73188597+NoelStephensUnity@users.noreply.github.com> Date: Wed, 28 Jul 2021 15:53:21 -0500 Subject: [PATCH 04/11] refactor and style Added the case where no prefab handler override is registered but there is still a host. Added a lookup table to quickly get the proper source GlobalObjectIdHash value for the NetworkPrefab that has an override in the NetworkManager. The first scene in the SceneTransitioningTest uses a NetworkManager defined prefab override, in host mode the host will pool while clients will not pool (no need since there is no way to override the instantiation) and the host will always send the source NetworkPrefab's GlobalObjectIdHash value as opposed to the target override's GlobalObjectIdHash. Fixed Fatih's super-nit-pick :) --- .../Runtime/Configuration/NetworkConfig.cs | 3 +++ .../Runtime/Core/NetworkManager.cs | 19 ++++++++++++++----- .../Runtime/Core/NetworkObject.cs | 13 +++++++++++-- .../SceneTransitioningTest.unity | 2 +- .../Scripts/GenericNetworkObjectBehaviour.cs | 10 +++++++++- .../Tests/Manual/Scripts/NetworkPrefabPool.cs | 18 +++++++++++------- 6 files changed, 49 insertions(+), 16 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Runtime/Configuration/NetworkConfig.cs b/com.unity.multiplayer.mlapi/Runtime/Configuration/NetworkConfig.cs index 31cbf16644..c8b40519fd 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Configuration/NetworkConfig.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Configuration/NetworkConfig.cs @@ -60,6 +60,9 @@ public class NetworkConfig /// internal Dictionary NetworkPrefabOverrideLinks = new Dictionary(); + internal Dictionary OverrideToNetworkPrefab = new Dictionary(); + + /// /// The tickrate of network ticks. This value controls how often MLAPI runs user code and sends out data. /// diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs index e708751939..86030d972f 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs @@ -523,13 +523,22 @@ private void Initialize(bool server) NetworkConfig.NetworkPrefabs[i]); break; case NetworkPrefabOverride.Prefab: - NetworkConfig.NetworkPrefabOverrideLinks.Add( - NetworkConfig.NetworkPrefabs[i].SourcePrefabToOverride.GetComponent() - .GlobalObjectIdHash, NetworkConfig.NetworkPrefabs[i]); + { + var sourcePrefabGlobalObjectIdHash = NetworkConfig.NetworkPrefabs[i].SourcePrefabToOverride.GetComponent().GlobalObjectIdHash; + NetworkConfig.NetworkPrefabOverrideLinks.Add(sourcePrefabGlobalObjectIdHash, NetworkConfig.NetworkPrefabs[i]); + + var targetPrefabGlobalObjectIdHash = NetworkConfig.NetworkPrefabs[i].OverridingTargetPrefab.GetComponent().GlobalObjectIdHash; + NetworkConfig.OverrideToNetworkPrefab.Add(targetPrefabGlobalObjectIdHash, sourcePrefabGlobalObjectIdHash); + } break; case NetworkPrefabOverride.Hash: - NetworkConfig.NetworkPrefabOverrideLinks.Add( - NetworkConfig.NetworkPrefabs[i].SourceHashToOverride, NetworkConfig.NetworkPrefabs[i]); + { + var sourcePrefabGlobalObjectIdHash = NetworkConfig.NetworkPrefabs[i].SourceHashToOverride; + NetworkConfig.NetworkPrefabOverrideLinks.Add(sourcePrefabGlobalObjectIdHash, NetworkConfig.NetworkPrefabs[i]); + + var targetPrefabGlobalObjectIdHash = NetworkConfig.NetworkPrefabs[i].OverridingTargetPrefab.GetComponent().GlobalObjectIdHash; + NetworkConfig.OverrideToNetworkPrefab.Add(targetPrefabGlobalObjectIdHash, sourcePrefabGlobalObjectIdHash); + } break; } } diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs index 165ef0999f..95a256b561 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs @@ -1063,10 +1063,19 @@ internal static NetworkObject DeserializeSceneObject(NetworkBuffer objectStream, /// internal uint HostCheckForGlobalObjectIdHashOverride() { - if (NetworkManager.IsHost && NetworkManager.PrefabHandler.ContainsHandler(this)) + if (NetworkManager.IsHost) { - return NetworkManager.PrefabHandler.GetSourceGlobalObjectIdHash(GlobalObjectIdHash); + if (NetworkManager.PrefabHandler.ContainsHandler(this)) + { + return NetworkManager.PrefabHandler.GetSourceGlobalObjectIdHash(GlobalObjectIdHash); + } + else + if (NetworkManager.NetworkConfig.OverrideToNetworkPrefab.ContainsKey(GlobalObjectIdHash)) + { + return NetworkManager.NetworkConfig.OverrideToNetworkPrefab[GlobalObjectIdHash]; + } } + return GlobalObjectIdHash; } } diff --git a/testproject/Assets/Tests/Manual/SceneTransitioning/SceneTransitioningTest.unity b/testproject/Assets/Tests/Manual/SceneTransitioning/SceneTransitioningTest.unity index 77971458c5..7d5577ff10 100644 --- a/testproject/Assets/Tests/Manual/SceneTransitioning/SceneTransitioningTest.unity +++ b/testproject/Assets/Tests/Manual/SceneTransitioning/SceneTransitioningTest.unity @@ -1114,7 +1114,7 @@ MonoBehaviour: SpawnsPerSecond: 5 PoolSize: 128 ObjectSpeed: 8 - EnableHandler: 1 + EnableHandler: 0 RegisterUsingNetworkObject: 0 ServerObjectToPool: {fileID: 771575417923360811, guid: c0a45bdb516f341498d933b7a7ed4fc1, type: 3} diff --git a/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs b/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs index 646b5849e0..61d06dd369 100644 --- a/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs +++ b/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs @@ -75,6 +75,10 @@ private void FixedUpdate() } } + [HideInInspector] + public bool HasHandler; + + private void OnTriggerEnter(Collider other) { @@ -86,7 +90,11 @@ private void OnTriggerEnter(Collider other) } else { - NetworkObject.Despawn(true); + NetworkObject.Despawn(HasHandler); + if (!HasHandler) + { + NetworkObject.gameObject.SetActive(false); + } } } } diff --git a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs index a0148553c8..13888be999 100644 --- a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs +++ b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs @@ -83,7 +83,7 @@ private void RegisterCustomPrefabHandler() } - private void DeRegisterCustomPrefabHandler() + private void DeregisterCustomPrefabHandler() { if (EnableHandler && NetworkManager && NetworkManager.PrefabHandler != null && m_MyCustomPrefabSpawnHandler != null) { @@ -210,18 +210,21 @@ public void InitializeObjectPool() } // Since the host should spawn the override, we need to register the host to link it to the originally registered ServerObjectToPool - if (IsHost) + if (IsHost && EnableHandler) { // While this seems redundant, we could theoretically have several objects that we could potentially be spawning NetworkManager.PrefabHandler.RegisterHostGlobalObjectIdHashValues(ServerObjectToPool, new List() { m_ObjectToSpawn }); } } - m_ObjectPool = new List(PoolSize); - - for (int i = 0; i < PoolSize; i++) + if (EnableHandler || IsServer) { - AddNewInstance(); + m_ObjectPool = new List(PoolSize); + + for (int i = 0; i < PoolSize; i++) + { + AddNewInstance(); + } } } @@ -255,7 +258,8 @@ public GameObject GetObject() private GameObject AddNewInstance() { var obj = Instantiate(m_ObjectToSpawn); - var no = obj.GetComponent(); + var genericNetworkObjectBehaviour = obj.GetComponent(); + genericNetworkObjectBehaviour.HasHandler = EnableHandler; obj.SetActive(false); m_ObjectPool.Add(obj); return obj; From 68fb3bdff0059c6311a3d53ec997b971790bf60a Mon Sep 17 00:00:00 2001 From: NoelStephensUnity <73188597+NoelStephensUnity@users.noreply.github.com> Date: Wed, 28 Jul 2021 15:54:55 -0500 Subject: [PATCH 05/11] fix Removing an artifact property from a previous merge. --- .../Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs b/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs index 61d06dd369..9369216a29 100644 --- a/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs +++ b/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs @@ -13,8 +13,6 @@ public class GenericNetworkObjectBehaviour : NetworkBehaviour [Tooltip("This will make the spawned objects move around randomly. !Caution! You can generate a lot of objects this way!")] private bool m_MoveRandomly = true; - public Text txtComponent; - private Rigidbody m_RigidBody; private Vector3 m_Direction; private float m_Velocity; @@ -42,11 +40,6 @@ public void SetDirectionAndVelocity(Vector3 direction, float velocity) /// private void FixedUpdate() { - if (txtComponent) - { - txtComponent.text = NetworkObjectId.ToString(); - } - if (NetworkManager != null && NetworkManager.IsListening) { if (IsOwner) From 8a9f273a135dea157a60228c65e6f2752413db29 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity <73188597+NoelStephensUnity@users.noreply.github.com> Date: Wed, 28 Jul 2021 16:17:28 -0500 Subject: [PATCH 06/11] fix Fixing missing change to deregister and issue with despawning during fixed update. --- .../Scripts/GenericNetworkObjectBehaviour.cs | 24 +++++++++++++------ .../Tests/Manual/Scripts/NetworkPrefabPool.cs | 2 +- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs b/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs index 9369216a29..50c72e4c70 100644 --- a/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs +++ b/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs @@ -68,14 +68,28 @@ private void FixedUpdate() } } + + private void Update() + { + if(IsOwner && m_ShouldDespawn) + { + m_ShouldDespawn = false; + NetworkObject.Despawn(HasHandler); + if (!HasHandler) + { + NetworkObject.gameObject.SetActive(false); + } + } + } + [HideInInspector] public bool HasHandler; - + private bool m_ShouldDespawn; private void OnTriggerEnter(Collider other) { - if (IsOwner) + if (IsOwner && gameObject.activeInHierarchy) { if (other.CompareTag("GenericObject") || other.CompareTag("Floor")) { @@ -83,11 +97,7 @@ private void OnTriggerEnter(Collider other) } else { - NetworkObject.Despawn(HasHandler); - if (!HasHandler) - { - NetworkObject.gameObject.SetActive(false); - } + m_ShouldDespawn = true; } } } diff --git a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs index 13888be999..df5efc09d9 100644 --- a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs +++ b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs @@ -145,7 +145,7 @@ private void Start() /// private void OnSceneSwitchBegin() { - DeRegisterCustomPrefabHandler(); + DeregisterCustomPrefabHandler(); if (IsServer) { StopCoroutine(SpawnObjects()); From aa97122e9228b3d73b0bed3f93734b6ef67fb461 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity <73188597+NoelStephensUnity@users.noreply.github.com> Date: Wed, 28 Jul 2021 16:23:24 -0500 Subject: [PATCH 07/11] fix Need to reset the position for the object when no handler exists otherwise the trigger will fire immediately and cause it to despawn immediately. --- .../Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs b/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs index 50c72e4c70..8d2ad287b5 100644 --- a/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs +++ b/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs @@ -77,6 +77,7 @@ private void Update() NetworkObject.Despawn(HasHandler); if (!HasHandler) { + NetworkObject.gameObject.transform.position = Vector3.zero; NetworkObject.gameObject.SetActive(false); } } From ec3e7c14e6fb6e39924492672fd67b33ea118a00 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity <73188597+NoelStephensUnity@users.noreply.github.com> Date: Wed, 28 Jul 2021 18:19:50 -0500 Subject: [PATCH 08/11] refactor and fix Removing despawn replication and from places where they are no longer needed either due to the now proper message ordering. Updated the GenericNetowrkObjectBehaviour such that clients disable the MeshRenderer component and then have a delayed re-enabling of it upon being spawned in order to avoid the latent update in the transform's position (removes the flickering of NetworkObjects on the client). Added the ability to make the SwitchSceneHandler have a delayed "auto switch" in order to run cycled long burn runs to assure everything is working "as expected". Fixed an access violation in StatsDisplay ( minor thing that was bugging me). --- .../Runtime/Core/NetworkManager.cs | 2 - .../Runtime/Spawning/NetworkSpawnManager.cs | 10 +-- .../Scripts/GenericNetworkObjectBehaviour.cs | 61 ++++++++++++++++++- .../Tests/Manual/Scripts/NetworkPrefabPool.cs | 11 ++-- .../Tests/Manual/Scripts/StatsDisplay.cs | 10 +-- .../Manual/Scripts/SwitchSceneHandler.cs | 36 ++++++++--- 6 files changed, 99 insertions(+), 31 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs index 86030d972f..ccd00f68f7 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs @@ -1316,7 +1316,6 @@ internal void OnClientDisconnectFromServer(ulong clientId) if (PrefabHandler.ContainsHandler(ConnectedClients[clientId].PlayerObject.GlobalObjectIdHash)) { PrefabHandler.HandleNetworkPrefabDestroy(ConnectedClients[clientId].PlayerObject); - SpawnManager.OnDespawnObject(ConnectedClients[clientId].PlayerObject, false); } else { @@ -1335,7 +1334,6 @@ internal void OnClientDisconnectFromServer(ulong clientId) .GlobalObjectIdHash)) { PrefabHandler.HandleNetworkPrefabDestroy(ConnectedClients[clientId].OwnedObjects[i]); - SpawnManager.OnDespawnObject(ConnectedClients[clientId].OwnedObjects[i], false); } else { diff --git a/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs b/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs index a976af0e1d..cb39f09192 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs @@ -504,14 +504,14 @@ internal void ServerDestroySpawnedSceneObjects() // This **needs** to be here until we overhaul NetworkSceneManager due to dependencies // that occur shortly after NetworkSceneManager invokes ServerDestroySpawnedSceneObjects // within the NetworkSceneManager.SwitchScene method. - SpawnedObjectsList.Remove(sobj); + if (NetworkManager.PrefabHandler != null && NetworkManager.PrefabHandler.ContainsHandler(sobj)) { NetworkManager.PrefabHandler.HandleNetworkPrefabDestroy(sobj); - OnDespawnObject(sobj, false); } else { + SpawnedObjectsList.Remove(sobj); UnityEngine.Object.Destroy(sobj.gameObject); } } @@ -559,7 +559,10 @@ internal void DestroySceneObjects() if (NetworkManager.PrefabHandler.ContainsHandler(networkObjects[i])) { NetworkManager.PrefabHandler.HandleNetworkPrefabDestroy(networkObjects[i]); - OnDespawnObject(networkObjects[i], false); + if (SpawnedObjects.ContainsKey(networkObjects[i].NetworkObjectId)) + { + OnDespawnObject(networkObjects[i], false); + } } else { @@ -681,7 +684,6 @@ internal void OnDespawnObject(NetworkObject networkObject, bool destroyGameObjec if (NetworkManager.PrefabHandler.ContainsHandler(networkObject)) { NetworkManager.PrefabHandler.HandleNetworkPrefabDestroy(networkObject); - OnDespawnObject(networkObject, false); } else { diff --git a/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs b/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs index 8d2ad287b5..8451f85bfb 100644 --- a/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs +++ b/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs @@ -14,12 +14,54 @@ public class GenericNetworkObjectBehaviour : NetworkBehaviour private bool m_MoveRandomly = true; private Rigidbody m_RigidBody; + private MeshRenderer m_MeshRenderer; private Vector3 m_Direction; private float m_Velocity; private void Start() { m_RigidBody = GetComponent(); + m_MeshRenderer = GetComponent(); + } + + /// + /// Handles disabling the MeshRenderer when the client despawns a NetworkObject + /// + public override void OnNetworkDespawn() + { + if (!IsServer) + { + if (m_MeshRenderer == null) + { + m_MeshRenderer = GetComponent(); + } + + if (m_MeshRenderer != null) + { + NetworkObject.gameObject.transform.position = Vector3.zero; + m_MeshRenderer.enabled = false; + } + } + base.OnNetworkDespawn(); + } + + private float m_VisibilitySpawn; + /// + /// Handles setting a delay before the newly spawned object is visible + /// Note: this might get removed once the snapshot system is synchronizing + /// NetworkObjects' spawn and despawn. + /// + public override void OnNetworkSpawn() + { + if (!IsServer) + { + if (m_MeshRenderer == null) + { + m_MeshRenderer = GetComponent(); + } + m_VisibilitySpawn = Time.realtimeSinceStartup + 0.1f; + } + base.OnNetworkSpawn(); } /// @@ -71,16 +113,31 @@ private void FixedUpdate() private void Update() { - if(IsOwner && m_ShouldDespawn) + if(IsOwner && m_ShouldDespawn && NetworkObject != null) { m_ShouldDespawn = false; + NetworkObject.Despawn(HasHandler); if (!HasHandler) { - NetworkObject.gameObject.transform.position = Vector3.zero; NetworkObject.gameObject.SetActive(false); + NetworkObject.gameObject.transform.position = Vector3.zero; + } + } + else if (!IsServer) + { + // This is here to handle any short term latency between the time + // an object becomes spawned to the time it takes to update its first + // position. + if (m_MeshRenderer != null && !m_MeshRenderer.enabled) + { + if (m_VisibilitySpawn < Time.realtimeSinceStartup) + { + m_MeshRenderer.enabled = true; + } } } + } [HideInInspector] diff --git a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs index df5efc09d9..50a9f6b610 100644 --- a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs +++ b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs @@ -223,7 +223,8 @@ public void InitializeObjectPool() for (int i = 0; i < PoolSize; i++) { - AddNewInstance(); + var gameObject = AddNewInstance(); + gameObject.SetActive(false); } } } @@ -238,14 +239,13 @@ public GameObject GetObject() { foreach (var obj in m_ObjectPool) { - if (!obj.activeInHierarchy) + if (obj != null && !obj.activeInHierarchy) { obj.SetActive(true); return obj; } } var newObj = AddNewInstance(); - newObj.SetActive(true); return newObj; } return null; @@ -260,7 +260,6 @@ private GameObject AddNewInstance() var obj = Instantiate(m_ObjectToSpawn); var genericNetworkObjectBehaviour = obj.GetComponent(); genericNetworkObjectBehaviour.HasHandler = EnableHandler; - obj.SetActive(false); m_ObjectPool.Add(obj); return obj; } @@ -305,8 +304,6 @@ public void UpdateSpawnsPerSecond() } } - private bool m_HasHostRegistered; - /// /// Coroutine to spawn boxes /// @@ -384,7 +381,7 @@ public NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaterni } public void Destroy(NetworkObject networkObject) { - networkObject.transform.position = Vector3.zero; + networkObject.transform.position = new Vector3(0, -1000, 0); networkObject.gameObject.SetActive(false); } diff --git a/testproject/Assets/Tests/Manual/Scripts/StatsDisplay.cs b/testproject/Assets/Tests/Manual/Scripts/StatsDisplay.cs index 55236ef71a..bba8730868 100644 --- a/testproject/Assets/Tests/Manual/Scripts/StatsDisplay.cs +++ b/testproject/Assets/Tests/Manual/Scripts/StatsDisplay.cs @@ -71,20 +71,12 @@ private void OnClientConnectedCallback(ulong clientId) } } - /// - /// Remove our OnClientConnectedCallback registration when we are destroyed - /// - private void OnDestroy() - { - NetworkManager.OnClientConnectedCallback -= OnClientConnectedCallback; - } - /// /// Used by UI Button click event /// public void ToggleClientSever() { - if (NetworkManager.Singleton.IsClient) + if (NetworkManager.Singleton != null && NetworkManager.Singleton.IsClient) { m_ClientMode = !m_ClientMode; GetStatsServerRPC(NetworkManager.Singleton.LocalClientId); diff --git a/testproject/Assets/Tests/Manual/Scripts/SwitchSceneHandler.cs b/testproject/Assets/Tests/Manual/Scripts/SwitchSceneHandler.cs index a51418472f..d755eace55 100644 --- a/testproject/Assets/Tests/Manual/Scripts/SwitchSceneHandler.cs +++ b/testproject/Assets/Tests/Manual/Scripts/SwitchSceneHandler.cs @@ -15,6 +15,15 @@ public class SwitchSceneHandler : NetworkBehaviour [SerializeField] private string m_SceneToSwitchTo; + [Tooltip("If enabled, this will automatically switch the scene after the Auto Switch TimeOut period has elapsed.")] + [SerializeField] + private bool m_EnableAutoSwitch; + + [Tooltip("Period in seconds until it will automatically switch to the next scene.")] + [SerializeField] + private float m_AutoSwitchTimeOut = 60; + + private void Awake() { ExitingNow = false; @@ -24,8 +33,11 @@ private void Start() { m_SwitchSceneButtonObject.SetActive(false); StartCoroutine(CheckForVisibility()); + } + + private bool m_ExitingScene; private void OnDestroy() { @@ -37,18 +49,20 @@ private IEnumerator CheckForVisibility() { while (!m_ExitingScene) { - if (NetworkManager.Singleton && NetworkManager.Singleton.IsListening && NetworkManager.Singleton.IsServer) + if (NetworkManager.Singleton && NetworkManager.Singleton.IsListening) { if (m_SwitchSceneButtonObject) { - m_SwitchSceneButtonObject.SetActive(true); + m_SwitchSceneButtonObject.SetActive(NetworkManager.Singleton.IsServer); } - } - else - { - m_SwitchSceneButtonObject.SetActive(false); - } + if (m_EnableAutoSwitch && NetworkManager.Singleton.IsServer) + { + StartCoroutine(AutoSwitch()); + } + + yield return null; + } yield return new WaitForSeconds(0.5f); } @@ -71,6 +85,14 @@ public override void OnNetworkSpawn() base.OnNetworkSpawn(); } + private IEnumerator AutoSwitch() + { + yield return new WaitForSeconds(m_AutoSwitchTimeOut); + + OnSwitchScene(); + + } + private SceneSwitchProgress m_CurrentSceneSwitchProgress; public delegate void OnSceneSwitchBeginDelegateHandler(); From 410f16c4837678d4026ab45c45fae6dcc9f93e08 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity <73188597+NoelStephensUnity@users.noreply.github.com> Date: Wed, 28 Jul 2021 20:22:19 -0500 Subject: [PATCH 09/11] fix and refactor Refactored a better client side "no blinking when spawning" solution. Fixed an issue where everyone was sending destroy messages to everyone else. --- .../Manual/Scripts/GenericNetworkObjectBehaviour.cs | 9 +++++++-- .../Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs b/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs index 8451f85bfb..509e8d0e9c 100644 --- a/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs +++ b/testproject/Assets/Tests/Manual/Scripts/GenericNetworkObjectBehaviour.cs @@ -38,7 +38,6 @@ public override void OnNetworkDespawn() if (m_MeshRenderer != null) { - NetworkObject.gameObject.transform.position = Vector3.zero; m_MeshRenderer.enabled = false; } } @@ -59,7 +58,12 @@ public override void OnNetworkSpawn() { m_MeshRenderer = GetComponent(); } - m_VisibilitySpawn = Time.realtimeSinceStartup + 0.1f; + m_MeshRenderer.enabled = false; + m_VisibilitySpawn = Time.realtimeSinceStartup + 0.12f; + if(NetworkObject.NetworkObjectId == 0) + { + Debug.Log("Spawning NetworkObjectId 0!"); + } } base.OnNetworkSpawn(); } @@ -105,6 +109,7 @@ private void FixedUpdate() if (NetworkObject != null && !NetworkObject.IsSpawned) { Debug.LogWarning($"{nameof(GenericNetworkObjectBehaviour)} id {NetworkObject.NetworkObjectId} is not spawned but still active and enabled"); + gameObject.SetActive(false); } } } diff --git a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs index 50a9f6b610..ea20d02b8b 100644 --- a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs +++ b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs @@ -381,7 +381,7 @@ public NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaterni } public void Destroy(NetworkObject networkObject) { - networkObject.transform.position = new Vector3(0, -1000, 0); + networkObject.transform.position = new Vector3(0, 0, 0); networkObject.gameObject.SetActive(false); } From 08398185e71658d8cf81aca58561d9cc4ed237be Mon Sep 17 00:00:00 2001 From: NoelStephensUnity <73188597+NoelStephensUnity@users.noreply.github.com> Date: Thu, 29 Jul 2021 11:48:44 -0500 Subject: [PATCH 10/11] refactor Added a more simplified example that uses a INetworkPrefabInstanceHandler implementation as a 1:1 NetworkObject pool. --- .../Runtime/Core/NetworkObject.cs | 3 +- .../Runtime/Spawning/NetworkPrefabHandler.cs | 15 +- .../Assets/References/Scene/PrefabPool.asset | 19 + .../References/Scene/PrefabPool.asset.meta | 8 + .../Assets/Tests/Manual/ManualTestsMenu.unity | 1 + .../Assets/Tests/Manual/PrefabPool.meta | 8 + .../Manual/PrefabPool/PrefabPoolExample.unity | 2412 +++++++++++++++++ .../PrefabPool/PrefabPoolExample.unity.meta | 7 + .../SceneTransitioningTest.unity | 8 +- .../SecondSceneToLoad.unity | 4 + .../SceneTransitioning/ThirdSceneToLoad.unity | 4 + .../Tests/Manual/Scripts/NetworkPrefabPool.cs | 6 +- .../ProjectSettings/EditorBuildSettings.asset | 3 + 13 files changed, 2483 insertions(+), 15 deletions(-) create mode 100644 testproject/Assets/References/Scene/PrefabPool.asset create mode 100644 testproject/Assets/References/Scene/PrefabPool.asset.meta create mode 100644 testproject/Assets/Tests/Manual/PrefabPool.meta create mode 100644 testproject/Assets/Tests/Manual/PrefabPool/PrefabPoolExample.unity create mode 100644 testproject/Assets/Tests/Manual/PrefabPool/PrefabPoolExample.unity.meta diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs index 95a256b561..b1d946c2be 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs @@ -1067,7 +1067,8 @@ internal uint HostCheckForGlobalObjectIdHashOverride() { if (NetworkManager.PrefabHandler.ContainsHandler(this)) { - return NetworkManager.PrefabHandler.GetSourceGlobalObjectIdHash(GlobalObjectIdHash); + var globalObjectIdHash = NetworkManager.PrefabHandler.GetSourceGlobalObjectIdHash(GlobalObjectIdHash); + return globalObjectIdHash == 0 ? GlobalObjectIdHash : globalObjectIdHash; } else if (NetworkManager.NetworkConfig.OverrideToNetworkPrefab.ContainsKey(GlobalObjectIdHash)) diff --git a/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkPrefabHandler.cs b/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkPrefabHandler.cs index 4f41a37683..0b81ad4dd5 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkPrefabHandler.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkPrefabHandler.cs @@ -281,18 +281,17 @@ internal NetworkObject HandleNetworkPrefabSpawn(uint networkPrefabAssetHash, ulo internal void HandleNetworkPrefabDestroy(NetworkObject networkObjectInstance) { var networkObjectInstanceHash = networkObjectInstance.GlobalObjectIdHash; - if (networkObjectInstance.NetworkManager.IsClient) + + // Do we have custom overrides registered? + if (m_PrefabInstanceToPrefabAsset.ContainsKey(networkObjectInstanceHash)) { - if (m_PrefabInstanceToPrefabAsset.ContainsKey(networkObjectInstanceHash)) + var networkPrefabAssetHash = m_PrefabInstanceToPrefabAsset[networkObjectInstanceHash]; + if (m_PrefabAssetToPrefabHandler.ContainsKey(networkPrefabAssetHash)) { - var networkPrefabAssetHash = m_PrefabInstanceToPrefabAsset[networkObjectInstanceHash]; - if (m_PrefabAssetToPrefabHandler.ContainsKey(networkPrefabAssetHash)) - { - m_PrefabAssetToPrefabHandler[networkPrefabAssetHash].Destroy(networkObjectInstance); - } + m_PrefabAssetToPrefabHandler[networkPrefabAssetHash].Destroy(networkObjectInstance); } } - else // Otherwise for server only (i.e. not host) the NetworkObject is the source NetworkPrefab + else // Otherwise the NetworkObject is the source NetworkPrefab if (m_PrefabAssetToPrefabHandler.ContainsKey(networkObjectInstanceHash)) { m_PrefabAssetToPrefabHandler[networkObjectInstanceHash].Destroy(networkObjectInstance); diff --git a/testproject/Assets/References/Scene/PrefabPool.asset b/testproject/Assets/References/Scene/PrefabPool.asset new file mode 100644 index 0000000000..433c9ac628 --- /dev/null +++ b/testproject/Assets/References/Scene/PrefabPool.asset @@ -0,0 +1,19 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 39a16938ffb5cd846a9f6df7a686a9c4, type: 3} + m_Name: PrefabPool + m_EditorClassIdentifier: + SceneToReference: {fileID: 102900000, guid: e4732b28c18f52c4dbe06c8a37f7997f, type: 3} + m_IncludedScenes: [] + m_DisplayName: Prefab Pool + m_ReferencedScenes: + - PrefabPoolExample diff --git a/testproject/Assets/References/Scene/PrefabPool.asset.meta b/testproject/Assets/References/Scene/PrefabPool.asset.meta new file mode 100644 index 0000000000..75b2f13b2d --- /dev/null +++ b/testproject/Assets/References/Scene/PrefabPool.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 660535b6e155b5b4bbede52313fcb32e +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/testproject/Assets/Tests/Manual/ManualTestsMenu.unity b/testproject/Assets/Tests/Manual/ManualTestsMenu.unity index cfa371e60d..c81d1c4367 100644 --- a/testproject/Assets/Tests/Manual/ManualTestsMenu.unity +++ b/testproject/Assets/Tests/Manual/ManualTestsMenu.unity @@ -914,6 +914,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_SceneMenus: + - {fileID: 11400000, guid: 660535b6e155b5b4bbede52313fcb32e, type: 2} - {fileID: 11400000, guid: d8c6d81e6a2574f4aa66a10aeb02f946, type: 2} - {fileID: 11400000, guid: 50c51a066c0971b49ab65929d5ba9630, type: 2} - {fileID: 11400000, guid: eb84694ca0950574981c9544bf99a552, type: 2} diff --git a/testproject/Assets/Tests/Manual/PrefabPool.meta b/testproject/Assets/Tests/Manual/PrefabPool.meta new file mode 100644 index 0000000000..518c4799b4 --- /dev/null +++ b/testproject/Assets/Tests/Manual/PrefabPool.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c6dc42b5fabac7444bfc80472a1a6f64 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/testproject/Assets/Tests/Manual/PrefabPool/PrefabPoolExample.unity b/testproject/Assets/Tests/Manual/PrefabPool/PrefabPoolExample.unity new file mode 100644 index 0000000000..1a986b15ca --- /dev/null +++ b/testproject/Assets/Tests/Manual/PrefabPool/PrefabPoolExample.unity @@ -0,0 +1,2412 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 903034822} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &37242881 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 37242883} + - component: {fileID: 37242882} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &37242882 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 37242881} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &37242883 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 37242881} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!224 &42803802 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + m_PrefabInstance: {fileID: 2848221156282925290} + m_PrefabAsset: {fileID: 0} +--- !u!1 &57392470 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 57392474} + - component: {fileID: 57392473} + - component: {fileID: 57392472} + - component: {fileID: 57392471} + m_Layer: 0 + m_Name: Side + m_TagString: Boundary + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!65 &57392471 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 57392470} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &57392472 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 57392470} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 00cf8ac777c8c42e8967157f70fbfcbf, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &57392473 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 57392470} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &57392474 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 57392470} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -30.5, y: 0.49999994, z: 0} + m_LocalScale: {x: 1, y: 3, z: 62} + m_Children: [] + m_Father: {fileID: 1332123092} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &167044830 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 167044834} + - component: {fileID: 167044833} + - component: {fileID: 167044832} + - component: {fileID: 167044831} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &167044831 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 167044830} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &167044832 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 167044830} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 0 +--- !u!223 &167044833 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 167044830} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &167044834 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 167044830} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 1865409449} + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!1 &290861168 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 290861172} + - component: {fileID: 290861171} + - component: {fileID: 290861170} + - component: {fileID: 290861169} + m_Layer: 5 + m_Name: UI + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &290861169 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 290861168} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &290861170 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 290861168} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 1 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 1024, y: 768} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0.5 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 0 +--- !u!223 &290861171 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 290861168} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 575203309} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &290861172 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 290861168} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 1588117328} + - {fileID: 42803802} + - {fileID: 1834318148} + - {fileID: 2058276876} + - {fileID: 1383741138} + m_Father: {fileID: 0} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!1 &336568645 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 336568649} + - component: {fileID: 336568648} + - component: {fileID: 336568647} + - component: {fileID: 336568646} + m_Layer: 0 + m_Name: Floor + m_TagString: Floor + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!65 &336568646 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 336568645} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &336568647 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 336568645} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 00cf8ac777c8c42e8967157f70fbfcbf, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &336568648 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 336568645} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &336568649 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 336568645} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: -0.50000006, z: 0} + m_LocalScale: {x: 60, y: 1, z: 60} + m_Children: [] + m_Father: {fileID: 1332123092} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &562991978 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 562991979} + - component: {fileID: 562991981} + - component: {fileID: 562991980} + m_Layer: 5 + m_Name: BoxGeneratorCount + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &562991979 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 562991978} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2058276876} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 3, y: 20} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &562991980 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 562991978} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.9811321, g: 0.9811321, b: 0.9811321, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 18 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 0 +--- !u!222 &562991981 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 562991978} + m_CullTransparentMesh: 1 +--- !u!1 &575203307 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 575203310} + - component: {fileID: 575203309} + - component: {fileID: 575203308} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &575203308 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 575203307} + m_Enabled: 1 +--- !u!20 &575203309 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 575203307} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &575203310 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 575203307} + m_LocalRotation: {x: 0.41890106, y: -0, z: -0, w: 0.9080319} + m_LocalPosition: {x: 0, y: 42, z: -46} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 49.530003, y: 0, z: 0} +--- !u!1 &599972120 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 599972121} + - component: {fileID: 599972123} + - component: {fileID: 599972122} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &599972121 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 599972120} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1588117328} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &599972122 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 599972120} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 0.5058824, b: 0.003921569, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Show Server Stats +--- !u!222 &599972123 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 599972120} + m_CullTransparentMesh: 1 +--- !u!850595691 &903034822 +LightingSettings: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: + serializedVersion: 3 + m_GIWorkflowMode: 1 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_RealtimeEnvironmentLighting: 1 + m_BounceScale: 1 + m_AlbedoBoost: 1 + m_IndirectOutputScale: 1 + m_UsingShadowmask: 1 + m_BakeBackend: 1 + m_LightmapMaxSize: 1024 + m_BakeResolution: 40 + m_Padding: 2 + m_TextureCompression: 1 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAO: 0 + m_MixedBakeMode: 2 + m_LightmapsBakeMode: 1 + m_FilterMode: 1 + m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0} + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_RealtimeResolution: 2 + m_ForceWhiteAlbedo: 0 + m_ForceUpdates: 0 + m_FinalGather: 0 + m_FinalGatherRayCount: 256 + m_FinalGatherFiltering: 1 + m_PVRCulling: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_LightProbeSampleCountMultiplier: 4 + m_PVRBounces: 2 + m_PVRMinBounces: 1 + m_PVREnvironmentMIS: 1 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 +--- !u!1 &1024114717 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1024114720} + - component: {fileID: 1024114719} + - component: {fileID: 1024114718} + m_Layer: 0 + m_Name: NetworkManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1024114718 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1024114717} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 593a2fe42fa9d37498c96f9a383b6521, type: 3} + m_Name: + m_EditorClassIdentifier: + DontDestroy: 1 + RunInBackground: 1 + LogLevel: 1 + NetworkConfig: + ProtocolVersion: 0 + NetworkTransport: {fileID: 1024114719} + RegisteredScenes: + - PrefabPoolExample + AllowRuntimeSceneChanges: 0 + PlayerPrefab: {fileID: 4079352819444256614, guid: c16f03336b6104576a565ef79ad643c0, + type: 3} + NetworkPrefabs: + - Override: 0 + Prefab: {fileID: 771575417923360811, guid: c0a45bdb516f341498d933b7a7ed4fc1, + type: 3} + SourcePrefabToOverride: {fileID: 771575417923360811, guid: c0a45bdb516f341498d933b7a7ed4fc1, + type: 3} + SourceHashToOverride: 0 + OverridingTargetPrefab: {fileID: 8059323910720821982, guid: d143db9172e1f234e99d450286b77695, + type: 3} + TickRate: 30 + ClientConnectionBufferTimeout: 10 + ConnectionApproval: 0 + ConnectionData: + EnableTimeResync: 0 + TimeResyncInterval: 30 + EnableNetworkVariable: 1 + EnsureNetworkVariableLengthSafety: 0 + EnableSceneManagement: 1 + ForceSamePrefabs: 1 + RecycleNetworkIds: 1 + NetworkIdRecycleDelay: 120 + RpcHashSize: 0 + LoadSceneTimeOut: 120 + MessageBufferTimeout: 20 + EnableNetworkLogs: 1 +--- !u!114 &1024114719 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1024114717} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b84c2d8dfe509a34fb59e2b81f8e1319, type: 3} + m_Name: + m_EditorClassIdentifier: + MessageBufferSize: 65535 + MaxConnections: 100 + MaxSentMessageQueueSize: 512 + ConnectAddress: 127.0.0.1 + ConnectPort: 7777 + ServerListenPort: 7777 + ServerWebsocketListenPort: 8887 + SupportWebsocket: 0 + Channels: [] + UseMLAPIRelay: 0 + MLAPIRelayAddress: 184.72.104.138 + MLAPIRelayPort: 8888 + MessageSendMode: 0 +--- !u!4 &1024114720 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1024114717} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.000061035156, y: 0.000015258789, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1113539278 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1113539280} + - component: {fileID: 1113539281} + - component: {fileID: 1113539279} + m_Layer: 0 + m_Name: PooledPrefabSpawnHandler + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1113539279 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1113539278} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8c48ea35c67e64f7fac22a3f6831ca88, type: 3} + m_Name: + m_EditorClassIdentifier: + AutoSpawnEnable: 1 + InitialSpawnDelay: 0.2 + SpawnsPerSecond: 2 + PoolSize: 10 + ObjectSpeed: 8 + EnableHandler: 1 + RegisterUsingNetworkObject: 0 + ServerObjectToPool: {fileID: 771575417923360811, guid: c0a45bdb516f341498d933b7a7ed4fc1, + type: 3} + ClientObjectToPool: {fileID: 0} + SwitchScene: {fileID: 0} + SpawnSlider: {fileID: 2058276877} + SpawnSliderValueText: {fileID: 562991980} +--- !u!4 &1113539280 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1113539278} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0.5, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1113539281 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1113539278} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 3000067655 + AlwaysReplicateAsRoot: 0 + DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 +--- !u!1 &1332123091 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1332123092} + m_Layer: 0 + m_Name: Level + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1332123092 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1332123091} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0.000000059604645, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 336568649} + - {fileID: 2028091272} + - {fileID: 1857685347} + - {fileID: 57392474} + - {fileID: 1336081255} + m_Father: {fileID: 0} + m_RootOrder: 6 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1336081251 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1336081255} + - component: {fileID: 1336081254} + - component: {fileID: 1336081253} + - component: {fileID: 1336081252} + m_Layer: 0 + m_Name: Side + m_TagString: Boundary + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!65 &1336081252 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1336081251} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1336081253 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1336081251} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 00cf8ac777c8c42e8967157f70fbfcbf, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1336081254 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1336081251} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1336081255 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1336081251} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 30.5, y: 0.49999994, z: 0} + m_LocalScale: {x: 1, y: 3, z: 62} + m_Children: [] + m_Father: {fileID: 1332123092} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1383741137 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1383741138} + - component: {fileID: 1383741140} + - component: {fileID: 1383741139} + m_Layer: 5 + m_Name: SceneName + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1383741138 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1383741137} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 290861172} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: -139.70001, y: 45.59999} + m_SizeDelta: {x: 250, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1383741139 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1383741137} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.990566, g: 0.990566, b: 0.990566, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 18 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Prefab Pool Example +--- !u!222 &1383741140 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1383741137} + m_CullTransparentMesh: 0 +--- !u!1 &1387688804 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1387688805} + m_Layer: 5 + m_Name: Handle Slide Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1387688805 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1387688804} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1523424137} + m_Father: {fileID: 2058276876} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -20, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1523424136 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1523424137} + - component: {fileID: 1523424139} + - component: {fileID: 1523424138} + m_Layer: 5 + m_Name: Handle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1523424137 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1523424136} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1387688805} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1523424138 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1523424136} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10913, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1523424139 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1523424136} + m_CullTransparentMesh: 1 +--- !u!1 &1549858058 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1549858059} + - component: {fileID: 1549858061} + - component: {fileID: 1549858060} + m_Layer: 5 + m_Name: Fill + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1549858059 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1549858058} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1889006547} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 10, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1549858060 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1549858058} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1549858061 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1549858058} + m_CullTransparentMesh: 1 +--- !u!1 &1588117327 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1588117328} + - component: {fileID: 1588117331} + - component: {fileID: 1588117330} + - component: {fileID: 1588117329} + m_Layer: 5 + m_Name: ToggleClientServerStats + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1588117328 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1588117327} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 599972121} + m_Father: {fileID: 290861172} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 130, y: 51} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1588117329 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1588117327} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1588117330} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 2107482022} + m_TargetAssemblyTypeName: StatsDisplay, Assembly-CSharp + m_MethodName: ToggleClientSever + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &1588117330 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1588117327} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.1981132, g: 0.1981132, b: 0.1981132, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1588117331 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1588117327} + m_CullTransparentMesh: 1 +--- !u!1 &1834318145 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1834318148} + - component: {fileID: 1834318147} + - component: {fileID: 1834318146} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1834318146 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1834318145} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1834318147 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1834318145} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!4 &1834318148 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1834318145} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -431, y: -242.5, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 290861172} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1857685343 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1857685347} + - component: {fileID: 1857685346} + - component: {fileID: 1857685345} + - component: {fileID: 1857685344} + m_Layer: 0 + m_Name: Side + m_TagString: Boundary + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!65 &1857685344 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1857685343} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1857685345 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1857685343} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 00cf8ac777c8c42e8967157f70fbfcbf, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1857685346 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1857685343} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1857685347 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1857685343} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.49999994, z: -30.5} + m_LocalScale: {x: 60, y: 3, z: 1} + m_Children: [] + m_Father: {fileID: 1332123092} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1001 &1865409448 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 167044834} + m_Modifications: + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_RootOrder + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_AnchorMax.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_SizeDelta.x + value: -952 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_SizeDelta.y + value: -344 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6963777608485144162, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_Name + value: ConnectionModeButtons + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: d725b5588e1b956458798319e6541d84, type: 3} +--- !u!224 &1865409449 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, + type: 3} + m_PrefabInstance: {fileID: 1865409448} + m_PrefabAsset: {fileID: 0} +--- !u!1 &1889006546 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1889006547} + m_Layer: 5 + m_Name: Fill Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1889006547 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1889006546} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1549858059} + m_Father: {fileID: 2058276876} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.25} + m_AnchorMax: {x: 1, y: 0.75} + m_AnchoredPosition: {x: -5, y: 0} + m_SizeDelta: {x: -20, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &2021718438 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2021718439} + - component: {fileID: 2021718441} + - component: {fileID: 2021718440} + m_Layer: 5 + m_Name: Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2021718439 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2021718438} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2058276876} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.25} + m_AnchorMax: {x: 1, y: 0.75} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2021718440 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2021718438} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &2021718441 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2021718438} + m_CullTransparentMesh: 1 +--- !u!1 &2028091268 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2028091272} + - component: {fileID: 2028091271} + - component: {fileID: 2028091270} + - component: {fileID: 2028091269} + m_Layer: 0 + m_Name: Side + m_TagString: Boundary + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!65 &2028091269 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2028091268} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &2028091270 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2028091268} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 00cf8ac777c8c42e8967157f70fbfcbf, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &2028091271 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2028091268} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &2028091272 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2028091268} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.49999994, z: 30.5} + m_LocalScale: {x: 60, y: 3, z: 1} + m_Children: [] + m_Father: {fileID: 1332123092} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &2058276875 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2058276876} + - component: {fileID: 2058276877} + m_Layer: 5 + m_Name: BoxGeneratorSlider + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2058276876 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2058276875} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 2021718439} + - {fileID: 1889006547} + - {fileID: 1387688805} + - {fileID: 562991979} + m_Father: {fileID: 290861172} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 1} + m_AnchorMax: {x: 0.5, y: 1} + m_AnchoredPosition: {x: 0.99993896, y: -63.99997} + m_SizeDelta: {x: 400, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2058276877 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2058276875} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 67db9e8f0e2ae9c40bc1e2b64352a6b4, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1523424138} + m_FillRect: {fileID: 1549858059} + m_HandleRect: {fileID: 1523424137} + m_Direction: 0 + m_MinValue: 0 + m_MaxValue: 550 + m_WholeNumbers: 1 + m_Value: 2 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1113539279} + m_TargetAssemblyTypeName: ServerBoxGenerator, Core + m_MethodName: UpdateSpawnsPerSecond + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 +--- !u!1 &2107482020 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2107482021} + - component: {fileID: 2107482022} + - component: {fileID: 2107482023} + m_Layer: 0 + m_Name: Stats + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2107482021 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2107482020} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 318.45444, y: 110.697815, z: 216.79077} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 7 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2107482022 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2107482020} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: cb5f3e55f5dd247129d8a4979b80ebbb, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ClientServerToggle: {fileID: 1588117327} +--- !u!114 &2107482023 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2107482020} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 2806511234 + AlwaysReplicateAsRoot: 0 + DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 +--- !u!1001 &2848221156282925290 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 290861172} + m_Modifications: + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_RootOrder + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_AnchorMax.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_AnchorMin.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_SizeDelta.x + value: 20 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_SizeDelta.y + value: 25 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_AnchoredPosition.x + value: -23.40039 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -23.800293 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247792, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2848221156307247795, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_Name + value: ExitButton + objectReference: {fileID: 0} + - target: {fileID: 5266522511616468950, guid: 3200770c16e3b2b4ebe7f604154faac7, + type: 3} + propertyPath: m_SceneMenuToLoad + value: + objectReference: {fileID: 11400000, guid: 4a3cdce12e998384f8aca207b5a2c700, + type: 2} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 3200770c16e3b2b4ebe7f604154faac7, type: 3} diff --git a/testproject/Assets/Tests/Manual/PrefabPool/PrefabPoolExample.unity.meta b/testproject/Assets/Tests/Manual/PrefabPool/PrefabPoolExample.unity.meta new file mode 100644 index 0000000000..cf3d9e8de7 --- /dev/null +++ b/testproject/Assets/Tests/Manual/PrefabPool/PrefabPoolExample.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e4732b28c18f52c4dbe06c8a37f7997f +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/testproject/Assets/Tests/Manual/SceneTransitioning/SceneTransitioningTest.unity b/testproject/Assets/Tests/Manual/SceneTransitioning/SceneTransitioningTest.unity index 7d5577ff10..b49ad92b44 100644 --- a/testproject/Assets/Tests/Manual/SceneTransitioning/SceneTransitioningTest.unity +++ b/testproject/Assets/Tests/Manual/SceneTransitioning/SceneTransitioningTest.unity @@ -174,6 +174,8 @@ MonoBehaviour: m_EditorClassIdentifier: m_SwitchSceneButtonObject: {fileID: 1347823141} m_SceneToSwitchTo: SecondSceneToLoad + m_EnableAutoSwitch: 1 + m_AutoSwitchTimeOut: 300 --- !u!1 &37242881 GameObject: m_ObjectHideFlags: 0 @@ -1111,8 +1113,8 @@ MonoBehaviour: m_EditorClassIdentifier: AutoSpawnEnable: 1 InitialSpawnDelay: 0.2 - SpawnsPerSecond: 5 - PoolSize: 128 + SpawnsPerSecond: 2 + PoolSize: 10 ObjectSpeed: 8 EnableHandler: 0 RegisterUsingNetworkObject: 0 @@ -2474,7 +2476,7 @@ MonoBehaviour: m_MinValue: 0 m_MaxValue: 550 m_WholeNumbers: 1 - m_Value: 6 + m_Value: 2 m_OnValueChanged: m_PersistentCalls: m_Calls: diff --git a/testproject/Assets/Tests/Manual/SceneTransitioning/SecondSceneToLoad.unity b/testproject/Assets/Tests/Manual/SceneTransitioning/SecondSceneToLoad.unity index ecfeb581c5..5dd66443c9 100644 --- a/testproject/Assets/Tests/Manual/SceneTransitioning/SecondSceneToLoad.unity +++ b/testproject/Assets/Tests/Manual/SceneTransitioning/SecondSceneToLoad.unity @@ -1021,6 +1021,7 @@ MonoBehaviour: GlobalObjectIdHash: 2807568818 AlwaysReplicateAsRoot: 0 DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!1 &1332123091 GameObject: m_ObjectHideFlags: 0 @@ -1968,6 +1969,8 @@ MonoBehaviour: m_EditorClassIdentifier: m_SwitchSceneButtonObject: {fileID: 519083277} m_SceneToSwitchTo: ThirdSceneToLoad + m_EnableAutoSwitch: 1 + m_AutoSwitchTimeOut: 300 --- !u!1 &2058276875 GameObject: m_ObjectHideFlags: 0 @@ -2131,6 +2134,7 @@ MonoBehaviour: GlobalObjectIdHash: 4086995543 AlwaysReplicateAsRoot: 0 DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!1 &2126410740 GameObject: m_ObjectHideFlags: 0 diff --git a/testproject/Assets/Tests/Manual/SceneTransitioning/ThirdSceneToLoad.unity b/testproject/Assets/Tests/Manual/SceneTransitioning/ThirdSceneToLoad.unity index 34708fb82a..13cadd2162 100644 --- a/testproject/Assets/Tests/Manual/SceneTransitioning/ThirdSceneToLoad.unity +++ b/testproject/Assets/Tests/Manual/SceneTransitioning/ThirdSceneToLoad.unity @@ -1152,6 +1152,7 @@ MonoBehaviour: GlobalObjectIdHash: 3309811467 AlwaysReplicateAsRoot: 0 DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!1 &1332123091 GameObject: m_ObjectHideFlags: 0 @@ -1968,6 +1969,8 @@ MonoBehaviour: m_EditorClassIdentifier: m_SwitchSceneButtonObject: {fileID: 519083277} m_SceneToSwitchTo: SceneTransitioningTest + m_EnableAutoSwitch: 1 + m_AutoSwitchTimeOut: 300 --- !u!1 &2058276875 GameObject: m_ObjectHideFlags: 0 @@ -2131,6 +2134,7 @@ MonoBehaviour: GlobalObjectIdHash: 1463456178 AlwaysReplicateAsRoot: 0 DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!1 &2126410740 GameObject: m_ObjectHideFlags: 0 diff --git a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs index ea20d02b8b..fd1d7263e9 100644 --- a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs +++ b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs @@ -202,15 +202,15 @@ public void InitializeObjectPool() { if (EnableHandler && ClientObjectToPool != null) { - m_ObjectToSpawn = ClientObjectToPool; + m_ObjectToSpawn = NetworkManager.GetNetworkPrefabOverride(ClientObjectToPool); } else { - m_ObjectToSpawn = NetworkManager.GetNetworkPrefabOverride(ServerObjectToPool); + m_ObjectToSpawn = NetworkManager.GetNetworkPrefabOverride(m_ObjectToSpawn); } // Since the host should spawn the override, we need to register the host to link it to the originally registered ServerObjectToPool - if (IsHost && EnableHandler) + if (IsHost && EnableHandler && ServerObjectToPool != m_ObjectToSpawn) { // While this seems redundant, we could theoretically have several objects that we could potentially be spawning NetworkManager.PrefabHandler.RegisterHostGlobalObjectIdHashValues(ServerObjectToPool, new List() { m_ObjectToSpawn }); diff --git a/testproject/ProjectSettings/EditorBuildSettings.asset b/testproject/ProjectSettings/EditorBuildSettings.asset index f4245315f9..2c568d76ed 100644 --- a/testproject/ProjectSettings/EditorBuildSettings.asset +++ b/testproject/ProjectSettings/EditorBuildSettings.asset @@ -50,4 +50,7 @@ EditorBuildSettings: - enabled: 1 path: Assets/Scenes/EmptyScene.unity guid: a2545a872c007404fbb6b0393ab74974 + - enabled: 1 + path: Assets/Tests/Manual/PrefabPool/PrefabPoolExample.unity + guid: e4732b28c18f52c4dbe06c8a37f7997f m_configObjects: {} From 204743989870ac4b21793a3832bb5cfc1475fd6a Mon Sep 17 00:00:00 2001 From: NoelStephensUnity <73188597+NoelStephensUnity@users.noreply.github.com> Date: Thu, 29 Jul 2021 13:43:28 -0500 Subject: [PATCH 11/11] fix Fixed issue with spawning: - Sending to every client for each client within the observers list - Making the client ownership equal to the client it was sending to This fixes the issue with connecting more than 1 client to a host or server. --- com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs | 6 +++--- .../Runtime/Spawning/NetworkSpawnManager.cs | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs index b1d946c2be..06c4a2d6bf 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs @@ -245,7 +245,7 @@ public void NetworkShow(ulong clientId, Stream payload = null) Observers.Add(clientId); - NetworkManager.SpawnManager.SendSpawnCallForObject(clientId, this, payload); + NetworkManager.SpawnManager.SendSpawnCallForObject(clientId, OwnerClientId, this, payload); } /// @@ -442,12 +442,12 @@ private void SpawnInternal(Stream spawnPayload, bool destroyWithScene, ulong? ow } NetworkManager.SpawnManager.SpawnNetworkObjectLocally(this, NetworkManager.SpawnManager.GetNetworkObjectId(), false, playerObject, ownerClientId, spawnPayload, spawnPayload != null, spawnPayload == null ? 0 : (int)spawnPayload.Length, false, destroyWithScene); - + ulong ownerId = ownerClientId != null ? ownerClientId.Value : NetworkManager.ServerClientId; for (int i = 0; i < NetworkManager.ConnectedClientsList.Count; i++) { if (Observers.Contains(NetworkManager.ConnectedClientsList[i].ClientId)) { - NetworkManager.SpawnManager.SendSpawnCallForObject(NetworkManager.ConnectedClientsList[i].ClientId, this, spawnPayload); + NetworkManager.SpawnManager.SendSpawnCallForObject(NetworkManager.ConnectedClientsList[i].ClientId, ownerId, this, spawnPayload); } } } diff --git a/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs b/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs index cb39f09192..635c540221 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs @@ -367,7 +367,7 @@ internal void SpawnNetworkObjectLocally(NetworkObject networkObject, ulong netwo } } - internal void SendSpawnCallForObject(ulong clientId, NetworkObject networkObject, Stream payload) + internal void SendSpawnCallForObject(ulong clientId, ulong ownerClientId, NetworkObject networkObject, Stream payload) { //Currently, if this is called and the clientId (destination) is the server's client Id, this case //will be checked within the below Send function. To avoid unwarranted allocation of a PooledNetworkBuffer @@ -379,15 +379,14 @@ internal void SendSpawnCallForObject(ulong clientId, NetworkObject networkObject var messageQueueContainer = NetworkManager.MessageQueueContainer; - ulong[] clientIds = NetworkManager.ConnectedClientsIds; var context = messageQueueContainer.EnterInternalCommandContext( MessageQueueContainer.MessageType.CreateObject, NetworkChannel.Internal, - clientIds, NetworkUpdateLoop.UpdateStage); + new ulong[] { clientId }, NetworkUpdateLoop.UpdateStage); if (context != null) { using (var nonNullContext = (InternalCommandContext) context) { - WriteSpawnCallForObject(nonNullContext.NetworkWriter, clientId, networkObject, payload); + WriteSpawnCallForObject(nonNullContext.NetworkWriter, ownerClientId, networkObject, payload); } } }