diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index ba73356e80..ff9f37f6a8 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -22,12 +22,14 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Fixed -- Fixed AnticipatedNetworkTransform not respecting the InLocalSpace flag (#3995) +- Issue where scene migration in a distributed authority session would throw an exception on clients migrating their owned `NetworkObject` instances to a different scene.(#4086) +- Issue where migrating a dynamically spawned or in-scene placed `NetworkObject` into a different scene during awake could result in that spawned instance to not be synchronized. (#4086) - Issue where a NullReferenceException was thrown when a non-authority failed to spawn a NetworkObject. (#4067) - Issue where the active scene was not being serialized as the 1st scene which could result in various errors including a soft synchronization error if, on the client-side, other synchronized scenes had already been loaded prior to the active scene, which is always loaded as `LoadSceneMode.SingleMode` when client synchronization is set to `LoadSceneMode.SingleMode`, resulting in the previously loaded scene(s) to be unloaded. (#4065) - Issue when FastBufferReader is attempting to read a string and all or a portion of the character count has already been read by user script, it could read a character length that results in a negative byte length which could result in an editor crash. (#4052) - Issue where NetworkRigidbodyBase was not applying rotation correctly when using Rigidbody2D. (#4012) - Issue where NetworkRigidbodyBase was always checking the 3D rigid body's interpolation mode when determining if it is kinematic and needs to put the rigid body to sleep and then switch to interpolation. (#4012) +- Fixed AnticipatedNetworkTransform not respecting the InLocalSpace flag. (#3995) ### Security diff --git a/com.unity.netcode.gameobjects/Editor/NetworkManagerHelper.cs b/com.unity.netcode.gameobjects/Editor/NetworkManagerHelper.cs index a3224e6471..66ddb2b6f0 100644 --- a/com.unity.netcode.gameobjects/Editor/NetworkManagerHelper.cs +++ b/com.unity.netcode.gameobjects/Editor/NetworkManagerHelper.cs @@ -195,11 +195,11 @@ public bool NotifyUserOfNestedNetworkManager(NetworkManager networkManager, bool { return isParented; } - else // If we are no longer a child, then we can remove ourself from this list - if (transform.root == gameObject.transform) - { - s_LastKnownNetworkManagerParents.Remove(networkManager); - } + else if (transform.root == gameObject.transform) + { + // If we are no longer a child, then we can remove ourself from this list + s_LastKnownNetworkManagerParents.Remove(networkManager); + } } if (!EditorApplication.isUpdating && isParented) { diff --git a/com.unity.netcode.gameobjects/Runtime/Components/Interpolator/BufferedLinearInterpolator.cs b/com.unity.netcode.gameobjects/Runtime/Components/Interpolator/BufferedLinearInterpolator.cs index 294cd9989f..8ee288b02f 100644 --- a/com.unity.netcode.gameobjects/Runtime/Components/Interpolator/BufferedLinearInterpolator.cs +++ b/com.unity.netcode.gameobjects/Runtime/Components/Interpolator/BufferedLinearInterpolator.cs @@ -467,20 +467,20 @@ internal T Update(float deltaTime, double tickLatencyAsTime, double minDeltaTime InterpolateState.CurrentValue = InterpolateState.NextValue; } } - else // If the target is reached and we have no more state updates, we want to check to see if we need to reset. - if (m_BufferQueue.Count == 0) + // If the target is reached and we have no more state updates, we want to check to see if we need to reset. + else if (m_BufferQueue.Count == 0) + { + // When the delta between the time sent and the current tick latency time-window is greater than the max delta time + // plus the minimum delta time (a rough estimate of time to wait before we consider rate of change equal to zero), + // we will want to reset the interpolator with the current known value. This prevents the next received state update's + // time to be calculated against the last calculated time which if there is an extended period of time between the two + // it would cause a large delta time period between the two states (i.e. it stops moving for a second or two and then + // starts moving again). + if ((tickLatencyAsTime - InterpolateState.Target.Value.TimeSent) > InterpolateState.MaxDeltaTime + minDeltaTime) { - // When the delta between the time sent and the current tick latency time-window is greater than the max delta time - // plus the minimum delta time (a rough estimate of time to wait before we consider rate of change equal to zero), - // we will want to reset the interpolator with the current known value. This prevents the next received state update's - // time to be calculated against the last calculated time which if there is an extended period of time between the two - // it would cause a large delta time period between the two states (i.e. it stops moving for a second or two and then - // starts moving again). - if ((tickLatencyAsTime - InterpolateState.Target.Value.TimeSent) > InterpolateState.MaxDeltaTime + minDeltaTime) - { - InterpolateState.Reset(InterpolateState.CurrentValue); - } + InterpolateState.Reset(InterpolateState.CurrentValue); } + } } m_NbItemsReceivedThisFrame = 0; return InterpolateState.CurrentValue; @@ -593,20 +593,20 @@ public T Update(float deltaTime, double renderTime, double serverTime) // Determine if we have reached our target InterpolateState.TargetReached = IsApproximately(InterpolateState.CurrentValue, InterpolateState.Target.Value.Item, GetPrecision()); } - else // If the target is reached and we have no more state updates, we want to check to see if we need to reset. - if (InterpolateState.TargetReached && m_BufferQueue.Count == 0) + // If the target is reached and we have no more state updates, we want to check to see if we need to reset. + else if (InterpolateState.TargetReached && m_BufferQueue.Count == 0) + { + // When the delta between the time sent and the current tick latency time-window is greater than the max delta time + // plus the minimum delta time (a rough estimate of time to wait before we consider rate of change equal to zero), + // we will want to reset the interpolator with the current known value. This prevents the next received state update's + // time to be calculated against the last calculated time which if there is an extended period of time between the two + // it would cause a large delta time period between the two states (i.e. it stops moving for a second or two and then + // starts moving again). + if ((renderTime - InterpolateState.Target.Value.TimeSent) > 0.3f) // If we haven't recevied anything within 300ms, assume we stopped motion. { - // When the delta between the time sent and the current tick latency time-window is greater than the max delta time - // plus the minimum delta time (a rough estimate of time to wait before we consider rate of change equal to zero), - // we will want to reset the interpolator with the current known value. This prevents the next received state update's - // time to be calculated against the last calculated time which if there is an extended period of time between the two - // it would cause a large delta time period between the two states (i.e. it stops moving for a second or two and then - // starts moving again). - if ((renderTime - InterpolateState.Target.Value.TimeSent) > 0.3f) // If we haven't recevied anything within 300ms, assume we stopped motion. - { - InterpolateState.Reset(InterpolateState.CurrentValue); - } + InterpolateState.Reset(InterpolateState.CurrentValue); } + } m_NbItemsReceivedThisFrame = 0; return InterpolateState.CurrentValue; } diff --git a/com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs b/com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs index f87eee73ab..cdb25aa598 100644 --- a/com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs +++ b/com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs @@ -1180,26 +1180,25 @@ internal void CheckForAnimatorChanges() { SendAnimStateRpc(m_AnimationMessage); } + else if (!IsServer && IsOwner) + { + SendServerAnimStateRpc(m_AnimationMessage); + } else - if (!IsServer && IsOwner) - { - SendServerAnimStateRpc(m_AnimationMessage); - } - else + { + // Just notify all remote clients and not the local server + m_TargetGroup.Clear(); + foreach (var clientId in LocalNetworkManager.ConnectionManager.ConnectedClientIds) { - // Just notify all remote clients and not the local server - m_TargetGroup.Clear(); - foreach (var clientId in LocalNetworkManager.ConnectionManager.ConnectedClientIds) + if (clientId == LocalNetworkManager.LocalClientId || !NetworkObject.Observers.Contains(clientId)) { - if (clientId == LocalNetworkManager.LocalClientId || !NetworkObject.Observers.Contains(clientId)) - { - continue; - } - m_TargetGroup.Add(clientId); + continue; } - m_RpcParams.Send.Target = m_TargetGroup.Target; - SendClientAnimStateRpc(m_AnimationMessage, m_RpcParams); + m_TargetGroup.Add(clientId); } + m_RpcParams.Send.Target = m_TargetGroup.Target; + SendClientAnimStateRpc(m_AnimationMessage, m_RpcParams); + } } } @@ -1346,25 +1345,24 @@ private unsafe void WriteParameters(ref FastBufferWriter writer) BytePacker.WriteValuePacked(writer, (uint)valueInt); } } - else - if (cacheValue.Type == AnimationParamEnumWrapper.AnimatorControllerParameterBool) + else if (cacheValue.Type == AnimationParamEnumWrapper.AnimatorControllerParameterBool) + { + var valueBool = m_Animator.GetBool(hash); + fixed (void* value = cacheValue.Value) { - var valueBool = m_Animator.GetBool(hash); - fixed (void* value = cacheValue.Value) - { - UnsafeUtility.WriteArrayElement(value, 0, valueBool); - BytePacker.WriteValuePacked(writer, valueBool); - } + UnsafeUtility.WriteArrayElement(value, 0, valueBool); + BytePacker.WriteValuePacked(writer, valueBool); } - else if (cacheValue.Type == AnimationParamEnumWrapper.AnimatorControllerParameterFloat) + } + else if (cacheValue.Type == AnimationParamEnumWrapper.AnimatorControllerParameterFloat) + { + var valueFloat = m_Animator.GetFloat(hash); + fixed (void* value = cacheValue.Value) { - var valueFloat = m_Animator.GetFloat(hash); - fixed (void* value = cacheValue.Value) - { - UnsafeUtility.WriteArrayElement(value, 0, valueFloat); - BytePacker.WriteValuePacked(writer, valueFloat); - } + UnsafeUtility.WriteArrayElement(value, 0, valueFloat); + BytePacker.WriteValuePacked(writer, valueFloat); } + } } } diff --git a/com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs b/com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs index 63b43544bd..152cea793b 100644 --- a/com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs +++ b/com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs @@ -2515,24 +2515,24 @@ private bool CheckForStateChange(ref NetworkTransformState networkState, bool is } } } - else // Just apply the full local scale when synchronizing - if (SynchronizeScale) + // Just apply the full local scale when synchronizing + else if (SynchronizeScale) + { + var localScale = CachedTransform.localScale; + if (!UseHalfFloatPrecision) { - var localScale = CachedTransform.localScale; - if (!UseHalfFloatPrecision) - { - networkState.ScaleX = localScale.x; - networkState.ScaleY = localScale.y; - networkState.ScaleZ = localScale.z; - } - else - { - networkState.Scale = localScale; - } - flagStates.MarkChanged(AxialType.Scale, true); - isScaleDirty = true; + networkState.ScaleX = localScale.x; + networkState.ScaleY = localScale.y; + networkState.ScaleZ = localScale.z; } + else + { + networkState.Scale = localScale; + } + flagStates.MarkChanged(AxialType.Scale, true); + isScaleDirty = true; + } isDirty |= isPositionDirty || isRotationDirty || isScaleDirty; if (isDirty) @@ -3488,12 +3488,12 @@ private void NonAuthorityFinalizeSynchronization() child.InternalInitialization(); } } - else // Otherwise, just run through standard synchronization of this instance - if (!CanCommitToTransform) - { - ApplySynchronization(); - InternalInitialization(); - } + // Otherwise, just run through standard synchronization of this instance + else if (!CanCommitToTransform) + { + ApplySynchronization(); + InternalInitialization(); + } } } diff --git a/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs b/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs index dd22801412..3ff131131f 100644 --- a/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs @@ -967,19 +967,18 @@ internal void ProcessClientsToDisconnect() { return (true, playerPrefabHash.Value); } - else - if (NetworkManager.NetworkConfig.PlayerPrefab != null) + else if (NetworkManager.NetworkConfig.PlayerPrefab != null) + { + var networkObject = NetworkManager.NetworkConfig.PlayerPrefab.GetComponent(); + if (networkObject != null) { - var networkObject = NetworkManager.NetworkConfig.PlayerPrefab.GetComponent(); - if (networkObject != null) - { - return (true, networkObject.GlobalObjectIdHash); - } - else - { - NetworkManager.Log.Error(new Logging.Context(LogLevel.Error, $"Player prefab {NetworkManager.NetworkConfig.PlayerPrefab.name} has no {nameof(NetworkObject)}!")); - } + return (true, networkObject.GlobalObjectIdHash); } + else + { + NetworkManager.Log.Error(new Logging.Context(LogLevel.Error, $"Player prefab {NetworkManager.NetworkConfig.PlayerPrefab.name} has no {nameof(NetworkObject)}!")); + } + } return (false, 0); } diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs index 7f19f8349f..52e4dad4f1 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs @@ -9,11 +9,7 @@ using Unity.Netcode.Runtime; #if UNITY_EDITOR using UnityEditor; -#if UNITY_2021_2_OR_NEWER using UnityEditor.SceneManagement; -#else -using UnityEditor.Experimental.SceneManagement; -#endif #endif using UnityEngine; using UnityEngine.SceneManagement; @@ -133,9 +129,6 @@ public uint PrefabIdHash // The InContext or InIsolation edit mode network prefab scene instance of the prefab asset (s_PrefabAsset). private static NetworkObject s_PrefabInstance; - private static bool s_DebugPrefabIdGeneration; - - [ContextMenu("Refresh In-Scene Prefab Instances")] internal void RefreshAllPrefabInstances() { @@ -332,7 +325,7 @@ internal void OnValidate() /// private void CheckForInScenePlaced() { - if (gameObject.scene.IsValid() && gameObject.scene.isLoaded && gameObject.scene.buildIndex >= 0) + if (gameObject.scene.IsValid() && gameObject.scene.buildIndex >= 0) { if (PrefabUtility.IsPartOfAnyPrefab(this)) { @@ -352,6 +345,9 @@ private void CheckForInScenePlaced() SetSceneObjectStatus(true); #pragma warning restore CS0618 // Type or member is obsolete + // We go ahead and set this for "typical in-scene placed" usage patterns so this is serialized + InScenePlaced = true; + // Default scene migration synchronization to false for in-scene placed NetworkObjects SceneMigrationSynchronization = false; } @@ -1232,15 +1228,35 @@ public bool HasOwnershipStatus(OwnershipStatus status) /// /// Gets if the object is a SceneObject. /// + /// + /// This method is marked for deprecation.
+ /// Use instead. + ///
[Obsolete("Use InScenePlaced instead")] public bool? IsSceneObject { get; internal set; } + /// - /// True if this object is placed in a scene; false otherwise. + /// The serialized value. /// [field: HideInInspector] [field: SerializeField] - public bool InScenePlaced { get; internal set; } + private bool m_InScenePlaced; + + /// + /// True if this object is placed in a scene; false otherwise. + /// + public bool InScenePlaced + { + get + { + return m_InScenePlaced; + } + internal set + { + m_InScenePlaced = value; + } + } /// /// Sets whether this NetworkObject was instantiated as part of a scene @@ -2695,26 +2711,26 @@ internal bool ApplyNetworkParenting(bool removeParent = false, bool ignoreNotSpa m_CachedWorldPositionStays = false; return true; } - else // If the parent still isn't spawned add this to the orphaned children and return false - if (!parentNetworkObject.IsSpawned) - { - OrphanChildren.Add(this); - return false; - } - else - { - // If we made it this far, go ahead and set the network parenting values - // with the WorldPoisitonSays value set to false - // Note: Since in-scene placed NetworkObjects are parented in the scene - // the default "assumption" is that children are parenting local space - // relative. - SetNetworkParenting(parentNetworkObject.NetworkObjectId, false); + // If the parent still isn't spawned add this to the orphaned children and return false + else if (!parentNetworkObject.IsSpawned) + { + OrphanChildren.Add(this); + return false; + } + else + { + // If we made it this far, go ahead and set the network parenting values + // with the WorldPoisitonSays value set to false + // Note: Since in-scene placed NetworkObjects are parented in the scene + // the default "assumption" is that children are parenting local space + // relative. + SetNetworkParenting(parentNetworkObject.NetworkObjectId, false); - // Set the cached parent - SetCachedParent(parentNetworkObject.transform); + // Set the cached parent + SetCachedParent(parentNetworkObject.transform); - return true; - } + return true; + } } // If we are removing the parent or our latest parent is not set, then remove the parent. @@ -3639,6 +3655,7 @@ internal void SceneChangedUpdate(Scene scene, bool notify = false) return; } + // Don't create notification if there is a scene event in progress. if (NetworkManagerOwner.SceneManager.IsSceneEventInProgress()) { return; diff --git a/com.unity.netcode.gameobjects/Runtime/SceneManagement/DefaultSceneManagerHandler.cs b/com.unity.netcode.gameobjects/Runtime/SceneManagement/DefaultSceneManagerHandler.cs index dba918a679..f7ce87d521 100644 --- a/com.unity.netcode.gameobjects/Runtime/SceneManagement/DefaultSceneManagerHandler.cs +++ b/com.unity.netcode.gameobjects/Runtime/SceneManagement/DefaultSceneManagerHandler.cs @@ -359,14 +359,14 @@ public void SetClientSynchronizationMode(ref NetworkManager networkManager, Load } return; } - else // Warn users if they are changing this after there are clients already connected and synchronized - if (!networkManager.DistributedAuthorityMode && networkManager.ConnectedClientsIds.Count > (networkManager.IsHost ? 1 : 0) && sceneManager.ClientSynchronizationMode != mode) + // Warn users if they are changing this after there are clients already connected and synchronized + else if (!networkManager.DistributedAuthorityMode && networkManager.ConnectedClientsIds.Count > (networkManager.IsHost ? 1 : 0) && sceneManager.ClientSynchronizationMode != mode) + { + if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { - if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) - { - NetworkLog.LogWarning("Server is changing client synchronization mode after clients have been synchronized! It is recommended to do this before clients are connected!"); - } + NetworkLog.LogWarning("Server is changing client synchronization mode after clients have been synchronized! It is recommended to do this before clients are connected!"); } + } // For additive client synchronization, we take into consideration scenes // already loaded. diff --git a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs index c0d4b44aee..e3a5d2cfe4 100644 --- a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs @@ -1034,7 +1034,7 @@ internal void SetTheSceneBeingSynchronized(NetworkSceneHandle serverSceneHandle) // Most common scenario for DontDestroyOnLoad is when NetworkManager is set to not be destroyed if (serverSceneHandle == DontDestroyOnLoadScene.handle) { - SceneBeingSynchronized = NetworkManager.gameObject.scene; + SceneBeingSynchronized = DontDestroyOnLoadScene; return; } else @@ -2260,8 +2260,6 @@ private void SynchronizeNetworkObjectScene() { networkObject.SceneOriginHandle = ServerSceneHandleToClientSceneHandle[networkObject.NetworkSceneHandle]; - - // If the NetworkObject does not have a parent and is not in the same scene as it is on the server side, then find the right scene // and move it to that scene. if (networkObject.gameObject.scene.handle != networkObject.SceneOriginHandle && networkObject.transform.parent == null) @@ -2269,11 +2267,6 @@ private void SynchronizeNetworkObjectScene() if (ScenesLoaded.ContainsKey(networkObject.SceneOriginHandle)) { var scene = ScenesLoaded[networkObject.SceneOriginHandle]; - if (scene == DontDestroyOnLoadScene) - { - Debug.Log($"{networkObject.gameObject.name} migrating into DDOL!"); - } - SceneManager.MoveGameObjectToScene(networkObject.gameObject, scene); } else if (NetworkManager.LogLevel <= LogLevel.Normal) @@ -2897,6 +2890,12 @@ internal bool IsSceneUnloading(NetworkObject networkObject) /// internal void NotifyNetworkObjectSceneChanged(NetworkObject networkObject) { + if (networkObject.NetworkManagerOwner != NetworkManager) + { + Debug.Log($"!!!!!!!!!!!!! Integration test is registering for scene migration for instances outside of the bounds of this NetworkManager context !!!!!!!!!!!!!"); + return; + } + // Really, this should never happen but in case it does if (!networkObject.HasAuthority) { @@ -2920,7 +2919,7 @@ internal void NotifyNetworkObjectSceneChanged(NetworkObject networkObject) // Ignore if the scene is the currently active scene and the NetworkObject is auto synchronizing/migrating // to the currently active scene. - if (networkObject.gameObject.scene == SceneManager.GetActiveScene() && networkObject.ActiveSceneSynchronization) + if (networkObject.gameObject.scene.name == SceneManager.GetActiveScene().name && networkObject.ActiveSceneSynchronization) { return; } @@ -2929,6 +2928,13 @@ internal void NotifyNetworkObjectSceneChanged(NetworkObject networkObject) // Note: This does not apply to SceneEventType.Synchronize since synchronization isn't a global connected client event. if (IsSceneEventInProgress()) { + Debug.Log($"{networkObject.name} scene event in progress -- ignoring!"); + return; + } + + if (IsSceneUnloading(networkObject)) + { + Debug.Log($"{networkObject.name} scene unloading in progress -- ignoring!"); return; } @@ -3053,7 +3059,15 @@ internal void CheckForAndSendNetworkObjectSceneChanged() // Some NetworkObjects still exist, send the message var sceneEvent = BeginSceneEvent(); sceneEvent.SceneEventType = SceneEventType.ObjectSceneChanged; - SendSceneEventData(sceneEvent.SceneEventId, NetworkManager.ConnectedClientsIds.Where(c => c != NetworkManager.LocalClientId).ToArray()); + // SendSceneEventData can throw an exception. We need to wrap this and recover from the exception gracefully. + try + { + SendSceneEventData(sceneEvent.SceneEventId, NetworkManager.ConnectedClientsIds.Where(c => c != NetworkManager.LocalClientId).ToArray()); + } + catch (Exception ex) + { + Debug.LogException(ex); + } ObjectsMigratedIntoNewScene.Clear(); EndSceneEvent(sceneEvent.SceneEventId); } diff --git a/com.unity.netcode.gameobjects/Runtime/SceneManagement/SceneEventData.cs b/com.unity.netcode.gameobjects/Runtime/SceneManagement/SceneEventData.cs index 2575bd6bfd..6195fa2335 100644 --- a/com.unity.netcode.gameobjects/Runtime/SceneManagement/SceneEventData.cs +++ b/com.unity.netcode.gameobjects/Runtime/SceneManagement/SceneEventData.cs @@ -1204,31 +1204,51 @@ private void ReadSceneEventProgressDone(FastBufferReader reader) private void SerializeObjectsMovedIntoNewScene(FastBufferWriter writer) { var sceneManager = m_NetworkManager.SceneManager; - var ownerId = m_NetworkManager.LocalClientId; + var networkManagerClientId = m_NetworkManager.LocalClientId; if (IsForwarding) { - ownerId = m_OwnerId; + networkManagerClientId = m_OwnerId; } // Write the owner identifier - writer.WriteValueSafe(ownerId); + writer.WriteValueSafe(networkManagerClientId); - // Write the number of scene handles - writer.WriteValueSafe(sceneManager.ObjectsMigratedIntoNewScene.Count); + // Create a place holder for the number of entries written. + // Distributed authority this could end up being just a single entry for + // one of several scenes loaded. As such, we need to count how many entries + // are actually written. + var countPosition = writer.Position; + writer.WriteValueSafe(0); + var entriesWritten = 0; foreach (var sceneHandleObjects in sceneManager.ObjectsMigratedIntoNewScene) { - if (!sceneHandleObjects.Value.ContainsKey(ownerId)) + // Since these are separated by scene then owner, there could be scenes that have + // no changes. + if (!sceneHandleObjects.Value.ContainsKey(networkManagerClientId)) { - throw new Exception($"Trying to send object scene migration for Client-{ownerId} but the client has no entries to send!"); + continue; } // Write the scene handle writer.WriteValueSafe(sceneHandleObjects.Key); // Write the number of NetworkObjectIds to expect - writer.WriteValueSafe(sceneHandleObjects.Value[ownerId].Count); - foreach (var networkObject in sceneHandleObjects.Value[ownerId]) + writer.WriteValueSafe(sceneHandleObjects.Value[networkManagerClientId].Count); + foreach (var networkObject in sceneHandleObjects.Value[networkManagerClientId]) { writer.WriteValueSafe(networkObject.NetworkObjectId); } + entriesWritten++; + } + if (entriesWritten == 0) + { + throw new Exception($"Trying to send object scene migration for Client-{networkManagerClientId} but the client has no entries to send!"); + } + else + { + // Write the number of entries written + var endPosition = writer.Position; + writer.Seek(countPosition); + writer.WriteValueSafe(entriesWritten); + writer.Seek(endPosition); } } diff --git a/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkPrefabHandler.cs b/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkPrefabHandler.cs index ece7561161..19444a4ddb 100644 --- a/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkPrefabHandler.cs +++ b/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkPrefabHandler.cs @@ -341,11 +341,11 @@ internal void HandleNetworkPrefabDestroy(NetworkObject networkObjectInstance) prefabInstanceHandler.Destroy(networkObjectInstance); } } - else // Otherwise the NetworkObject is the source NetworkPrefab - if (m_PrefabAssetToPrefabHandler.TryGetValue(networkObjectInstanceHash, out var prefabInstanceHandler)) - { - prefabInstanceHandler.Destroy(networkObjectInstance); - } + // Otherwise the NetworkObject is the source NetworkPrefab + else if (m_PrefabAssetToPrefabHandler.TryGetValue(networkObjectInstanceHash, out var prefabInstanceHandler)) + { + prefabInstanceHandler.Destroy(networkObjectInstance); + } } /// diff --git a/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs b/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs index 3cdf35b20c..74d0ee121e 100644 --- a/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs @@ -1448,7 +1448,9 @@ internal void ServerResetShutdownStateForSceneObjects() var networkObjects = FindObjects.ByType(orderByIdentifier: true, includeInactive: true); foreach (var obj in networkObjects) { - if (obj.HasBeenSpawned && obj.InScenePlaced) { + // Only reset things that have been spawned are in-scene placed, and is assigned to the relative NetworkManager (for integration testing purposes) + if (obj.HasBeenSpawned && obj.InScenePlaced && obj.NetworkManagerOwner == NetworkManager) + { obj.ResetOnShutdown(); } } @@ -1714,11 +1716,10 @@ internal void OnDespawnObject([NotNull] NetworkObject networkObject, bool destro NetworkLog.LogError($"{nameof(NetworkObject)} #{spawnedNetObj.NetworkObjectId} could not be moved to the root when its parent {nameof(NetworkObject)} #{networkObject.NetworkObjectId} was being destroyed"); } } - else - if (NetworkLog.CurrentLogLevel <= LogLevel.Developer) - { - NetworkLog.LogWarning($"{nameof(NetworkObject)} #{spawnedNetObj.NetworkObjectId} moved to the root because its parent {nameof(NetworkObject)} #{networkObject.NetworkObjectId} is destroyed"); - } + else if (NetworkLog.CurrentLogLevel <= LogLevel.Developer) + { + NetworkLog.LogWarning($"{nameof(NetworkObject)} #{spawnedNetObj.NetworkObjectId} moved to the root because its parent {nameof(NetworkObject)} #{networkObject.NetworkObjectId} is destroyed"); + } } } diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/NetworkClientAndPlayerObjectTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/NetworkClientAndPlayerObjectTests.cs index 461d85a757..929592a9b0 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/NetworkClientAndPlayerObjectTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/NetworkClientAndPlayerObjectTests.cs @@ -246,12 +246,11 @@ private bool ValidateAllPlayerObjects() m_ErrorLogLevel1.AppendLine($"[Client-{client.LocalClientId}] Local {nameof(NetworkClient.PlayerObject)} is null!"); success = false; } - else - if (!client.SpawnManager.PlayerObjects.Contains(client.LocalClient.PlayerObject)) - { - m_ErrorLogLevel1.AppendLine($"[Client-{client.LocalClientId}] Local {nameof(NetworkSpawnManager.PlayerObjects)} does not contain {client.LocalClient.PlayerObject.name}!"); - success = false; - } + else if (!client.SpawnManager.PlayerObjects.Contains(client.LocalClient.PlayerObject)) + { + m_ErrorLogLevel1.AppendLine($"[Client-{client.LocalClientId}] Local {nameof(NetworkSpawnManager.PlayerObjects)} does not contain {client.LocalClient.PlayerObject.name}!"); + success = false; + } } return success; diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkShowHideTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkShowHideTests.cs index 43f6eac7de..1ef0a13eb4 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkShowHideTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkShowHideTests.cs @@ -488,11 +488,10 @@ private bool Object1IsNotVisibileToClient() m_ErrorLog.AppendLine($"{m_NetSpawnedObject1.name} is still visible to Client-{m_ClientWithoutVisibility}!"); } } - else - if (client.SpawnManager.SpawnedObjects[m_NetSpawnedObject1.NetworkObjectId].IsNetworkVisibleTo(m_ClientWithoutVisibility)) - { - m_ErrorLog.AppendLine($"Local instance of {m_NetSpawnedObject1.name} on Client-{client.LocalClientId} thinks Client-{m_ClientWithoutVisibility} still has visibility!"); - } + else if (client.SpawnManager.SpawnedObjects[m_NetSpawnedObject1.NetworkObjectId].IsNetworkVisibleTo(m_ClientWithoutVisibility)) + { + m_ErrorLog.AppendLine($"Local instance of {m_NetSpawnedObject1.name} on Client-{client.LocalClientId} thinks Client-{m_ClientWithoutVisibility} still has visibility!"); + } } return m_ErrorLog.Length == 0; } diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformNonAuthorityTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformNonAuthorityTests.cs index 5705d21942..350f312973 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformNonAuthorityTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformNonAuthorityTests.cs @@ -418,13 +418,12 @@ private bool ShouldSyncAxis(bool first, bool second, bool lastValue) // make the last one disabled. return false; } - else - if (!first && !second) - { - // If both are disabled, then make the - // last one enabled. - return true; - } + else if (!first && !second) + { + // If both are disabled, then make the + // last one enabled. + return true; + } } return Random.Range(start, 100) >= 50 ? false : true; } diff --git a/testproject/Assets/AddressableAssetsData/AddressableAssetSettings.asset b/testproject/Assets/AddressableAssetsData/AddressableAssetSettings.asset index 6a1c39a006..69bec9b722 100644 --- a/testproject/Assets/AddressableAssetsData/AddressableAssetSettings.asset +++ b/testproject/Assets/AddressableAssetsData/AddressableAssetSettings.asset @@ -15,7 +15,8 @@ MonoBehaviour: m_DefaultGroup: 93aa504d1b753cb41a8a779ae63f5795 m_currentHash: serializedVersion: 2 - Hash: c105cac3e36a87a6dabc4f3755bc1fd9 + Hash: 00000000000000000000000000000000 + m_ExtractTypeTreeData: 0 m_OptimizeCatalogSize: 0 m_BuildRemoteCatalog: 0 m_CatalogRequestsTimeout: 0 @@ -33,6 +34,7 @@ MonoBehaviour: m_UniqueBundleIds: 0 m_EnableJsonCatalog: 0 m_NonRecursiveBuilding: 1 + m_AllowNestedBundleFolders: 0 m_CCDEnabled: 0 m_maxConcurrentWebRequests: 500 m_UseUWRForLocalBundles: 0 @@ -41,6 +43,7 @@ MonoBehaviour: m_BundleRedirectLimit: -1 m_SharedBundleSettings: 0 m_SharedBundleSettingsCustomGroupIndex: 0 + m_simulatedLoadDelay: 0.1 m_ContiguousBundles: 0 m_StripUnityVersionFromBundleBuild: 0 m_DisableVisibleSubAssetRepresentations: 0 @@ -70,32 +73,32 @@ MonoBehaviour: m_Id: b7ba5fc73af2a49449023b732cdf652d m_ProfileName: Default m_Values: - - m_Id: a2553e7788fb43741926b3128a0aa641 - m_Value: '[UnityEditor.EditorUserBuildSettings.activeBuildTarget]' - - m_Id: 8bc200e556c0a2f4daf1a4696958eaa6 - m_Value: '[UnityEngine.AddressableAssets.Addressables.BuildPath]/[BuildTarget]' + - m_Id: 2a3d80e942fdbfe49a979d4a22bbe893 + m_Value: 'http://localhost/[BuildTarget]' - m_Id: 80085c797452bb94ca0bf0a4b2ec258c m_Value: '{UnityEngine.AddressableAssets.Addressables.RuntimePath}/[BuildTarget]' + - m_Id: 8bc200e556c0a2f4daf1a4696958eaa6 + m_Value: '[UnityEngine.AddressableAssets.Addressables.BuildPath]/[BuildTarget]' + - m_Id: a2553e7788fb43741926b3128a0aa641 + m_Value: '[UnityEditor.EditorUserBuildSettings.activeBuildTarget]' - m_Id: eaae5cc67c56cfe4299363a742a284b3 m_Value: 'ServerData/[BuildTarget]' - - m_Id: 2a3d80e942fdbfe49a979d4a22bbe893 - m_Value: 'http://localhost/[BuildTarget]' m_ProfileEntryNames: - - m_Id: a2553e7788fb43741926b3128a0aa641 - m_Name: BuildTarget + - m_Id: 2a3d80e942fdbfe49a979d4a22bbe893 + m_Name: Remote.LoadPath + m_InlineUsage: 0 + - m_Id: 80085c797452bb94ca0bf0a4b2ec258c + m_Name: Local.LoadPath m_InlineUsage: 0 - m_Id: 8bc200e556c0a2f4daf1a4696958eaa6 m_Name: Local.BuildPath m_InlineUsage: 0 - - m_Id: 80085c797452bb94ca0bf0a4b2ec258c - m_Name: Local.LoadPath + - m_Id: a2553e7788fb43741926b3128a0aa641 + m_Name: BuildTarget m_InlineUsage: 0 - m_Id: eaae5cc67c56cfe4299363a742a284b3 m_Name: Remote.BuildPath m_InlineUsage: 0 - - m_Id: 2a3d80e942fdbfe49a979d4a22bbe893 - m_Name: Remote.LoadPath - m_InlineUsage: 0 m_ProfileVersion: 1 m_LabelTable: m_LabelNames: diff --git a/testproject/Assets/AddressableAssetsData/AssetGroups/Default Local Group.asset b/testproject/Assets/AddressableAssetsData/AssetGroups/Default Local Group.asset index d3f0f5a0e5..36d70b4b1c 100644 --- a/testproject/Assets/AddressableAssetsData/AssetGroups/Default Local Group.asset +++ b/testproject/Assets/AddressableAssetsData/AssetGroups/Default Local Group.asset @@ -15,11 +15,6 @@ MonoBehaviour: m_GroupName: Default Local Group m_GUID: 93aa504d1b753cb41a8a779ae63f5795 m_SerializeEntries: - - m_GUID: 68d21678646384e6291bb2b568b5d95c - m_Address: Assets/Scenes/AddressableInSceneObject.unity - m_ReadOnly: 0 - m_SerializedLabels: [] - FlaggedDuringContentUpdateRestriction: 0 - m_GUID: ffa1ab8ed58b72343ad93116ded1700a m_Address: AddressableTestObject.prefab m_ReadOnly: 0 diff --git a/testproject/Assets/Scenes/MultiprocessTestScene.unity b/testproject/Assets/Scenes/MultiprocessTestScene.unity deleted file mode 100644 index f67263407e..0000000000 --- a/testproject/Assets/Scenes/MultiprocessTestScene.unity +++ /dev/null @@ -1,1062 +0,0 @@ -%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: 10 - 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_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 13 - m_BakeOnSceneLoad: 0 - 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_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: 130932425} ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 3 - 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 - buildHeightMesh: 0 - maxJobWorkers: 0 - preserveTilesOutsideBounds: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &127222500 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 127222502} - - component: {fileID: 127222501} - 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 &127222501 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 127222500} - m_Enabled: 1 - serializedVersion: 11 - m_Type: 1 - 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_ForceVisible: 0 - m_ShadowRadius: 0 - m_ShadowAngle: 0 - m_LightUnit: 1 - m_LuxAtDistance: 1 - m_EnableSpotReflector: 1 ---- !u!4 &127222502 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 127222500} - serializedVersion: 2 - 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_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!850595691 &130932425 -LightingSettings: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: - serializedVersion: 9 - m_EnableBakedLightmaps: 0 - 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_LightmapSizeFixed: 0 - m_UseMipmapLimits: 1 - m_BakeResolution: 40 - m_Padding: 2 - m_LightmapCompression: 3 - 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_EnableWorkerProcessBaking: 1 - m_TrainingDataDestination: TrainingData - m_RealtimeResolution: 2 - m_ForceWhiteAlbedo: 0 - m_ForceUpdates: 0 - 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: 2 - m_PVREnvironmentImportanceSampling: 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 - m_RespectSceneVisibilityWhenBakingGI: 0 ---- !u!1 &160940364 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 160940368} - - component: {fileID: 160940367} - - component: {fileID: 160940366} - - component: {fileID: 160940365} - m_Layer: 0 - m_Name: Boundary bottom left - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!135 &160940365 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 160940364} - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_IsTrigger: 0 - m_ProvidesContacts: 0 - m_Enabled: 1 - serializedVersion: 3 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &160940366 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 160940364} - 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_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - 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 &160940367 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 160940364} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &160940368 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 160940364} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -10, y: -10, z: -10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &430011403 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 430011407} - - component: {fileID: 430011406} - - component: {fileID: 430011405} - - component: {fileID: 430011404} - m_Layer: 0 - m_Name: ThreeDText - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &430011404 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 430011403} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 04cf3cc1396054b009a1ed283aa50021, type: 3} - m_Name: - m_EditorClassIdentifier: - IsTestCoordinatorActiveAndEnabled: 0 - CommandLineArguments: ---- !u!102 &430011405 -TextMesh: - serializedVersion: 3 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 430011403} - m_Text: Hello World - m_OffsetZ: 0 - m_CharacterSize: 1 - m_LineSpacing: 1 - m_Anchor: 0 - m_Alignment: 0 - m_TabSize: 4 - m_FontSize: 0 - m_FontStyle: 0 - m_RichText: 1 - m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} - m_Color: - serializedVersion: 2 - rgba: 4294967295 ---- !u!23 &430011406 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 430011403} - 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_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10100, guid: 0000000000000000e000000000000000, type: 0} - 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!4 &430011407 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 430011403} - serializedVersion: 2 - m_LocalRotation: {x: 0.2164396, y: 0, z: 0, w: 0.97629607} - m_LocalPosition: {x: -45, y: 10, z: 10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 25, y: 0, z: 0} ---- !u!1 &941021721 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 941021724} - - component: {fileID: 941021723} - - component: {fileID: 941021722} - 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 &941021722 -AudioListener: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 941021721} - m_Enabled: 1 ---- !u!20 &941021723 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 941021721} - 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_Iso: 200 - m_ShutterSpeed: 0.005 - m_Aperture: 16 - m_FocusDistance: 10 - m_FocalLength: 50 - m_BladeCount: 5 - m_Curvature: {x: 2, y: 11} - m_BarrelClipping: 0.25 - m_Anamorphism: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - 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 &941021724 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 941021721} - serializedVersion: 2 - m_LocalRotation: {x: 0.21736304, y: -0, z: -0, w: 0.97609085} - m_LocalPosition: {x: 0, y: 9.15, z: -27.5} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 25.108, y: 0, z: 0} ---- !u!1 &996484657 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 996484661} - - component: {fileID: 996484660} - - component: {fileID: 996484659} - - component: {fileID: 996484658} - m_Layer: 0 - m_Name: Boundary center - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!135 &996484658 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 996484657} - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_IsTrigger: 0 - m_ProvidesContacts: 0 - m_Enabled: 1 - serializedVersion: 3 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &996484659 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 996484657} - 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_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - 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 &996484660 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 996484657} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &996484661 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 996484657} - serializedVersion: 2 - 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_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1206022453 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1206022457} - - component: {fileID: 1206022456} - - component: {fileID: 1206022455} - - component: {fileID: 1206022454} - m_Layer: 0 - m_Name: Boundary top right - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!135 &1206022454 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1206022453} - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_IsTrigger: 0 - m_ProvidesContacts: 0 - m_Enabled: 1 - serializedVersion: 3 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1206022455 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1206022453} - 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_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - 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 &1206022456 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1206022453} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &1206022457 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1206022453} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 10, y: 10, z: 10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1211923374 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1211923376} - - component: {fileID: 1211923375} - - component: {fileID: 1211923378} - - component: {fileID: 1211923377} - m_Layer: 0 - m_Name: '[NetworkManager] (Multiprocess)' - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &1211923375 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1211923374} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 593a2fe42fa9d37498c96f9a383b6521, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkManagerExpanded: 0 - NetworkConfig: - ProtocolVersion: 0 - NetworkTransport: {fileID: 2027640073} - PlayerPrefab: {fileID: 4700706668509470175, guid: 7eeaaf9e50c0afc4dab93584a54fb0d6, - type: 3} - Prefabs: - NetworkPrefabsLists: [] - TickRate: 30 - ClientConnectionBufferTimeout: 10 - ConnectionApproval: 0 - ConnectionData: - EnableTimeResync: 0 - TimeResyncInterval: 30 - EnsureNetworkVariableLengthSafety: 0 - EnableSceneManagement: 1 - ForceSamePrefabs: 1 - RecycleNetworkIds: 1 - NetworkIdRecycleDelay: 120 - RpcHashSize: 0 - LoadSceneTimeOut: 120 - SpawnTimeout: 10 - EnableNetworkLogs: 1 - NetworkTopology: 0 - UseCMBService: 0 - AutoSpawnPlayerPrefabClientSide: 1 - NetworkProfilingMetrics: 1 - OldPrefabList: - - Override: 0 - Prefab: {fileID: 9115731988109684252, guid: c2851feb7276442cc86a6f2d1d69ea11, - type: 3} - SourcePrefabToOverride: {fileID: 0} - SourceHashToOverride: 0 - OverridingTargetPrefab: {fileID: 0} - RunInBackground: 1 - LogLevel: 1 ---- !u!4 &1211923376 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1211923374} - serializedVersion: 2 - 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_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 2027640072} - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &1211923377 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1211923374} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 068bf11ceb1344667af4cc40950f44f4, type: 3} - m_Name: - m_EditorClassIdentifier: - ReferencedPrefab: {fileID: 9115731988109684252, guid: c2851feb7276442cc86a6f2d1d69ea11, - type: 3} ---- !u!114 &1211923378 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1211923374} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 55d1c75ce242745ac98f7e7aca6d2d19, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!1 &1274245423 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1274245425} - - component: {fileID: 1274245424} - - component: {fileID: 1274245426} - m_Layer: 0 - m_Name: TestCoordinator - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &1274245424 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1274245423} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} - m_Name: - m_EditorClassIdentifier: - GlobalObjectIdHash: 2217825759 - InScenePlacedSourceGlobalObjectIdHash: 0 - DeferredDespawnTick: 0 - Ownership: 1 - AlwaysReplicateAsRoot: 0 - SynchronizeTransform: 1 - ActiveSceneSynchronization: 0 - SceneMigrationSynchronization: 1 - SpawnWithObservers: 1 - DontDestroyWithOwner: 0 - AutoObjectParentSync: 1 - SyncOwnerTransformWhenParented: 1 - AllowOwnerToParent: 0 ---- !u!4 &1274245425 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1274245423} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 10, y: 10, z: 10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &1274245426 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1274245423} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: ef1240e0784f84eadb77fe822e2e03c7, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!1 &2027640071 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2027640072} - - component: {fileID: 2027640073} - m_Layer: 0 - m_Name: UTP - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &2027640072 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2027640071} - serializedVersion: 2 - 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_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 1211923376} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &2027640073 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2027640071} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 6960e84d07fb87f47956e7a81d71c4e6, type: 3} - m_Name: - m_EditorClassIdentifier: - m_ProtocolType: 0 - m_UseWebSockets: 0 - m_UseEncryption: 0 - m_MaxPacketQueueSize: 128 - m_MaxPayloadSize: 4096 - m_HeartbeatTimeoutMS: 500 - m_ConnectTimeoutMS: 1000 - m_MaxConnectAttempts: 60 - m_DisconnectTimeoutMS: 30000 - ConnectionData: - Address: 127.0.0.1 - Port: 7777 - ServerListenAddress: 127.0.0.1 - DebugSimulator: - PacketDelayMS: 0 - PacketJitterMS: 0 - PacketDropRate: 0 ---- !u!1660057539 &9223372036854775807 -SceneRoots: - m_ObjectHideFlags: 0 - m_Roots: - - {fileID: 941021724} - - {fileID: 127222502} - - {fileID: 1211923376} - - {fileID: 1206022457} - - {fileID: 996484661} - - {fileID: 160940368} - - {fileID: 1274245425} - - {fileID: 430011407} diff --git a/testproject/Assets/Tests/Manual/IntegrationTestScenes/InSceneNetworkObjectMovesToDDOL.unity b/testproject/Assets/Tests/Manual/IntegrationTestScenes/InSceneNetworkObjectMovesToDDOL.unity new file mode 100644 index 0000000000..1cfda7fc2d --- /dev/null +++ b/testproject/Assets/Tests/Manual/IntegrationTestScenes/InSceneNetworkObjectMovesToDDOL.unity @@ -0,0 +1,198 @@ +%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: 10 + 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_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_BakeOnSceneLoad: 0 + 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_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: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + 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 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &1633685737 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1633685739} + - component: {fileID: 1633685738} + - component: {fileID: 1633685740} + m_Layer: 0 + m_Name: InSceneObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1633685738 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1633685737} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 974939462 + InScenePlacedSourceGlobalObjectIdHash: 0 + DeferredDespawnTick: 0 + Ownership: 1 + AlwaysReplicateAsRoot: 0 + SynchronizeTransform: 1 + m_InScenePlaced: 1 + ActiveSceneSynchronization: 0 + SceneMigrationSynchronization: 0 + SpawnWithObservers: 1 + DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 + SyncOwnerTransformWhenParented: 1 + AllowOwnerToParent: 0 +--- !u!4 &1633685739 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1633685737} + serializedVersion: 2 + 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_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1633685740 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1633685737} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 112072ebb4fab6341bfee4bd9d7e58da, type: 3} + m_Name: + m_EditorClassIdentifier: TestProject.ManualTests::TestProject.ManualTests.MoveInScenePlacedToDDOL + ShowTopMostFoldoutHeaderGroup: 1 +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 1633685739} diff --git a/testproject/Assets/Scenes/MultiprocessTestScene.unity.meta b/testproject/Assets/Tests/Manual/IntegrationTestScenes/InSceneNetworkObjectMovesToDDOL.unity.meta similarity index 74% rename from testproject/Assets/Scenes/MultiprocessTestScene.unity.meta rename to testproject/Assets/Tests/Manual/IntegrationTestScenes/InSceneNetworkObjectMovesToDDOL.unity.meta index 5a9d45d780..dfa51863fd 100644 --- a/testproject/Assets/Scenes/MultiprocessTestScene.unity.meta +++ b/testproject/Assets/Tests/Manual/IntegrationTestScenes/InSceneNetworkObjectMovesToDDOL.unity.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 76743cb7b342c49279327834918a9c6e +guid: 4c20c17b4f92e634f8796b0460851d49 DefaultImporter: externalObjects: {} userData: diff --git a/testproject/Assets/Tests/Manual/Scripts/MoveInScenePlacedToDDOL.cs b/testproject/Assets/Tests/Manual/Scripts/MoveInScenePlacedToDDOL.cs new file mode 100644 index 0000000000..0e9fa457a9 --- /dev/null +++ b/testproject/Assets/Tests/Manual/Scripts/MoveInScenePlacedToDDOL.cs @@ -0,0 +1,34 @@ +using Unity.Netcode; +using UnityEngine; + +namespace TestProject.ManualTests +{ + public class MoveInScenePlacedToDDOL : NetworkBehaviour + { + public bool ProcessedRpc { get; private set; } + + private void Awake() + { + ProcessedRpc = false; + var networkObject = GetComponent(); + Debug.Log($"[{name}][Moving to DDOL] InScenePlaced: {networkObject.InScenePlaced}"); + DontDestroyOnLoad(gameObject); + } + + protected override void OnNetworkPostSpawn() + { + if (HasAuthority) + { + SendOnSpawnRpc(); + } + + base.OnNetworkPostSpawn(); + } + + [Rpc(SendTo.Everyone)] + private void SendOnSpawnRpc(RpcParams rpcParams = default) + { + ProcessedRpc = true; + } + } +} diff --git a/testproject/Assets/Tests/Manual/Scripts/MoveInScenePlacedToDDOL.cs.meta b/testproject/Assets/Tests/Manual/Scripts/MoveInScenePlacedToDDOL.cs.meta new file mode 100644 index 0000000000..739e4ca2d4 --- /dev/null +++ b/testproject/Assets/Tests/Manual/Scripts/MoveInScenePlacedToDDOL.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 112072ebb4fab6341bfee4bd9d7e58da \ No newline at end of file diff --git a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs index 5b045b1855..9f441b8f58 100644 --- a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs +++ b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs @@ -496,12 +496,12 @@ public void UpdateSpawnsPerSecond() { StartSpawningBoxes(); } - else //Handle case where spawning coroutine is running but we set our spawn rate to zero - if (SpawnsPerSecond == 0 && m_IsSpawningObjects) - { - m_IsSpawningObjects = false; - StopCoroutine(SpawnObjects()); - } + //Handle case where spawning coroutine is running but we set our spawn rate to zero + else if (SpawnsPerSecond == 0 && m_IsSpawningObjects) + { + m_IsSpawningObjects = false; + StopCoroutine(SpawnObjects()); + } } } diff --git a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPoolAdditive.cs b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPoolAdditive.cs index 0c4992cbd9..44decc3dce 100644 --- a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPoolAdditive.cs +++ b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPoolAdditive.cs @@ -342,12 +342,12 @@ public void UpdateSpawnsPerSecond() { StartSpawningBoxes(); } - else //Handle case where spawning coroutine is running but we set our spawn rate to zero - if (SpawnsPerSecond == 0 && m_IsSpawningObjects) - { - m_IsSpawningObjects = false; - InternalStopCoroutine(); - } + //Handle case where spawning coroutine is running but we set our spawn rate to zero + else if (SpawnsPerSecond == 0 && m_IsSpawningObjects) + { + m_IsSpawningObjects = false; + InternalStopCoroutine(); + } } diff --git a/testproject/Assets/Tests/Runtime/AddressablesTests.cs b/testproject/Assets/Tests/Runtime/AddressablesTests.cs index 4f08597430..7dd8aff688 100644 --- a/testproject/Assets/Tests/Runtime/AddressablesTests.cs +++ b/testproject/Assets/Tests/Runtime/AddressablesTests.cs @@ -204,29 +204,29 @@ public IEnumerator WhenSpawningServerPrefabBeforeClientPrefabHasLoaded_SpawningI // TODO-[MTT-15388]: Reconsider whether this test should be valid // Reported on Github issue https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/issues/4049 - [UnityTest] - public IEnumerator RegisteringPrefabFromLoadedAddressablesSceneWorks() - { - var asset = new AssetReference(k_ValidScene); + //[UnityTest] + //public IEnumerator RegisteringPrefabFromLoadedAddressablesSceneWorks() + //{ + // var asset = new AssetReference(k_ValidScene); - CreateServerAndClients(); - foreach (var manager in m_NetworkManagers) - { - manager.NetworkConfig.ForceSamePrefabs = false; - } + // CreateServerAndClients(); + // foreach (var manager in m_NetworkManagers) + // { + // manager.NetworkConfig.ForceSamePrefabs = false; + // } - StartServerAndClientsWithTimeTravel(); + // StartServerAndClientsWithTimeTravel(); - var prefabResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); - yield return LoadSceneWithInSceneObject(asset, prefabResult); + // var prefabResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); + // yield return LoadSceneWithInSceneObject(asset, prefabResult); - foreach (var manager in m_NetworkManagers) - { - manager.AddNetworkPrefab(prefabResult.Result); - } + // foreach (var manager in m_NetworkManagers) + // { + // manager.AddNetworkPrefab(prefabResult.Result); + // } - SpawnAndValidate(prefabResult.Result, wasLoadedFromScene: true); - } + // SpawnAndValidate(prefabResult.Result, wasLoadedFromScene: true); + //} } } #endif diff --git a/testproject/Assets/Tests/Runtime/Animation/NetworkAnimatorTests.cs b/testproject/Assets/Tests/Runtime/Animation/NetworkAnimatorTests.cs index dc2493ec28..715e7f6156 100644 --- a/testproject/Assets/Tests/Runtime/Animation/NetworkAnimatorTests.cs +++ b/testproject/Assets/Tests/Runtime/Animation/NetworkAnimatorTests.cs @@ -527,11 +527,10 @@ private bool AllObserversSameLayerWeight(OwnerShipMode ownerShipMode, int layer, return false; } } - else - if (animatorTestHelper.Value.GetLayerWeight(layer) != targetWeight) - { - return false; - } + else if (animatorTestHelper.Value.GetLayerWeight(layer) != targetWeight) + { + return false; + } } return true; } diff --git a/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkObjectSceneMigrationTests.cs b/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkObjectSceneMigrationTests.cs index 9318e1d63e..736de24acf 100644 --- a/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkObjectSceneMigrationTests.cs +++ b/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkObjectSceneMigrationTests.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using System.Text; using NUnit.Framework; using Unity.Netcode; @@ -46,6 +47,13 @@ protected override IEnumerator OnSetup() return base.OnSetup(); } + protected override void OnCreatePlayerPrefab() + { + Object.DontDestroyOnLoad(m_PlayerPrefab); + m_PlayerPrefab.GetComponent().ActiveSceneSynchronization = true; + base.OnCreatePlayerPrefab(); + } + protected override void OnServerAndClientsCreated() { // Synchronize Scene Changes (default) Test Network Prefab @@ -66,42 +74,18 @@ protected override void OnServerAndClientsCreated() var shouldNeverSpawn = neverSpawnObj.AddComponent(); DestroyWithSceneInstancesTestHelper.ShouldNeverSpawn = shouldNeverSpawn; + var authority = GetAuthorityNetworkManager(); + authority.OnServerStarted += OnServerStarted; + base.OnServerAndClientsCreated(); } - private enum ExpectedLoadType - { - Loaded, - Unloaded - } - private bool ValidateSceneOnAllClients(StringBuilder errorLog, string sceneName, ExpectedLoadType loadType) + private void OnServerStarted() { - var allValid = true; - foreach (var networkManager in m_NetworkManagers) - { - var sceneLoaded = false; - foreach (var scene in networkManager.SceneManager.ScenesLoaded.Values) - { - if (scene.name == sceneName) - { - sceneLoaded = true; - break; - } - } - if (!sceneLoaded && loadType == ExpectedLoadType.Loaded) - { - errorLog.AppendLine($"[Client-{networkManager.LocalClientId}] scene {sceneName} wasn't loaded on this client!"); - allValid = false; - } - else if (sceneLoaded && loadType == ExpectedLoadType.Unloaded) - { - errorLog.AppendLine($"[Client-{networkManager.LocalClientId}] scene {sceneName} was still loaded on this client!"); - allValid = false; - } - } - - return allValid; + var authority = GetAuthorityNetworkManager(); + authority.OnServerStarted -= OnServerStarted; + authority.SceneManager.ActiveSceneSynchronizationEnabled = true; } private bool VerifyAllScenesMatch(StringBuilder errorLog, List authorityInstances) @@ -127,7 +111,6 @@ private bool VerifyAllScenesMatch(StringBuilder errorLog, List au Assert.AreEqual(originalSceneTracker.SceneWhereAwakeHappened, (NetworkSceneHandle)instance.SceneOrigin.handle, "The SceneOrigin of an object should never change!"); } } - return true; } @@ -159,10 +142,7 @@ public IEnumerator MigrateIntoNewSceneTest() authority.SceneManager.OnSceneEvent += SceneManager_OnSceneEvent; foreach (var sceneToLoad in m_TestScenes) { - var status = authority.SceneManager.LoadScene(sceneToLoad, LoadSceneMode.Additive); - Assert.True(status == SceneEventProgressStatus.Started, $"Failed to start loading scene {sceneToLoad}! Return status: {status}"); - yield return WaitForConditionOrTimeOut(errorLog => ValidateSceneOnAllClients(errorLog, sceneToLoad, ExpectedLoadType.Loaded)); - AssertOnTimeout($"Timed out waiting for all clients to load scene {sceneToLoad}!"); + yield return LoadScene(authority, sceneToLoad); } authority.SceneManager.OnSceneEvent -= SceneManager_OnSceneEvent; Assert.AreEqual(m_TestScenes.Count, m_ScenesLoaded.Count, "Not all the test scenes were loaded!"); @@ -257,6 +237,23 @@ private void MigrateObjects_OnSynchronize(ulong clientId) GetAuthorityNetworkManager().SceneManager.OnSynchronize -= MigrateObjects_OnSynchronize; } + protected override void OnNewClientCreated(NetworkManager networkManager) + { + var authority = GetAuthorityNetworkManager(); + foreach (var prefab in authority.NetworkConfig.Prefabs.Prefabs) + { + networkManager.NetworkConfig.Prefabs.Add(prefab); + } + networkManager.NetworkConfig.PlayerPrefab = m_PlayerPrefab; + base.OnNewClientCreated(networkManager); + } + + private void SetActiveScene(Scene scene) + { + Debug.Log($"[Previous = {SceneManager.GetActiveScene().name}][New = {scene.name}] Changing the active scene!"); + SceneManager.SetActiveScene(scene); + } + /// /// Integration test to verify changing the currently active scene /// will migrate NetworkObjects with ActiveSceneSynchronization set @@ -270,6 +267,17 @@ public IEnumerator ActiveSceneSynchronizationTest() // to synchronize them. NetworkSceneManager.DisableReSynchronization = true; + // Load three scenes first + authority.SceneManager.OnSceneEvent += SceneManager_OnSceneEvent; + foreach (var sceneName in m_TestScenes) + { + yield return LoadScene(authority, sceneName); + } + authority.SceneManager.OnSceneEvent -= SceneManager_OnSceneEvent; + + // Set the active scene to be the 1st scene loaded so we don't instantiate within the test runner scene. + SetActiveScene(m_ScenesLoaded[0]); + var autoSyncActive = new List(); // Spawn 3 NetworkObject instances that auto synchronize to active scene changes for (int i = 0; i < 3; i++) @@ -317,17 +325,6 @@ public IEnumerator ActiveSceneSynchronizationTest() yield return WaitForSpawnedOnAllOrTimeOut(authoritySpawnedInstances); AssertOnTimeout($"Timed out waiting for all clients to spawn {nameof(NetworkObject)}s!"); - // Now load three scenes - authority.SceneManager.OnSceneEvent += SceneManager_OnSceneEvent; - foreach (var sceneName in m_TestScenes) - { - var loadStatus = authority.SceneManager.LoadScene(sceneName, LoadSceneMode.Additive); - Assert.True(loadStatus == SceneEventProgressStatus.Started, $"Failed to start loading scene {sceneName}! Return status: {loadStatus}"); - yield return WaitForConditionOrTimeOut(errorLog => ValidateSceneOnAllClients(errorLog, sceneName, ExpectedLoadType.Loaded)); - AssertOnTimeout($"Timed out waiting for all clients to load scene {sceneName}!"); - } - authority.SceneManager.OnSceneEvent -= SceneManager_OnSceneEvent; - var sceneToMigrateTo = m_ScenesLoaded[2]; // Migrate the instances that don't synchronize with active scene changes into the 3rd loaded scene // (We are making sure these stay in the same scene they are migrated into) @@ -350,9 +347,7 @@ public IEnumerator ActiveSceneSynchronizationTest() // Now change the active scene var newActiveScene = m_ScenesLoaded[1]; - SceneManager.SetActiveScene(newActiveScene); - // We have to do this - Object.DontDestroyOnLoad(m_TestPrefabAutoSynchActiveScene); + SetActiveScene(newActiveScene); // First, make sure server-side scenes and client side scenes match yield return WaitForConditionOrTimeOut(errorLog => VerifyAllScenesMatch(errorLog, authoritySpawnedInstances)); @@ -379,14 +374,14 @@ public IEnumerator ActiveSceneSynchronizationTest() // Verify that a late joining client synchronizes properly and destroys the appropriate NetworkObjects yield return CreateAndStartNewClient(); + AssertOnTimeout("Failed to start or create a new client!"); yield return WaitForConditionOrTimeOut(errorLog => VerifyAllScenesMatch(errorLog, authoritySpawnedInstances)); AssertOnTimeout($"[Late Joined Client #1] Timed out waiting for all clients to migrate all NetworkObjects into the appropriate scenes!"); // Now, unload the scene containing the NetworkObjects that don't synchronize with active scene changes DestroyWithSceneInstancesTestHelper.NetworkObjectDestroyed += OnNonActiveSynchDestroyWithSceneNetworkObjectDestroyed; - var status = authority.SceneManager.UnloadScene(sceneToMigrateTo); - Assert.True(status == SceneEventProgressStatus.Started, $"Failed to start unloading scene {sceneToMigrateTo.name} with status {status}!"); - yield return WaitForConditionOrTimeOut(log => ValidateSceneOnAllClients(log, sceneToMigrateTo.name, ExpectedLoadType.Unloaded)); + + yield return UnloadScene(authority, sceneToMigrateTo); // Clean up any destroyed NetworkObjects for (int i = authoritySpawnedInstances.Count - 1; i >= 0; i--) @@ -415,9 +410,7 @@ public IEnumerator ActiveSceneSynchronizationTest() // Now unload the active scene to verify all remaining NetworkObjects are migrated into the SceneManager // assigned active scene - authority.SceneManager.UnloadScene(newActiveScene); - yield return WaitForConditionOrTimeOut(log => ValidateSceneOnAllClients(log, sceneToMigrateTo.name, ExpectedLoadType.Unloaded)); - AssertOnTimeout($"Timed out waiting for all clients to unload scene {newActiveScene.name}!"); + yield return UnloadScene(authority, newActiveScene); // Clean up any destroyed NetworkObjects for (int i = authoritySpawnedInstances.Count - 1; i >= 0; i--) @@ -445,6 +438,52 @@ public IEnumerator ActiveSceneSynchronizationTest() Assert.AreEqual(3, autoSyncInactive.Count(obj => obj != null), $"All the NetworkObjects with {nameof(NetworkObject.ActiveSceneSynchronization)}=false should have survived the active scene change!"); } + /// + /// Helper method to load a scene and wait for the OnLoadEventCompleted event to trigger. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private IEnumerator LoadScene(NetworkManager authority, string sceneToLoad) + { + m_LoadEventCompleted = false; + authority.SceneManager.OnLoadEventCompleted += OnLoadEventCompleted; + var loadStatus = authority.SceneManager.LoadScene(sceneToLoad, LoadSceneMode.Additive); + Assert.True(loadStatus == SceneEventProgressStatus.Started, $"Failed to start loading scene {sceneToLoad}! Return status: {loadStatus}"); + yield return WaitForConditionOrTimeOut(() => m_LoadEventCompleted); + // Remove subscription prior to potentially asserting. + authority.SceneManager.OnLoadEventCompleted -= OnLoadEventCompleted; + AssertOnTimeout($"Timed out waiting for all clients to load scene {sceneToLoad}!"); + } + + /// + /// Helper method to load a scene and wait for the OnUnloadEventCompleted event to trigger. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private IEnumerator UnloadScene(NetworkManager authority, Scene sceneToUnload) + { + m_UnloadEventCompleted = false; + authority.SceneManager.OnUnloadEventCompleted += OnUnloadEventCompleted; + authority.SceneManager.UnloadScene(sceneToUnload); + + // Always make sure the scene event has completed. Trying to check if the scenes are loaded as a metric can + // create edge case scenarios where the scene might have been just loaded but not processed during synchronization. + yield return WaitForConditionOrTimeOut(() => m_UnloadEventCompleted); + // Remove subscription prior to potentially asserting. + authority.SceneManager.OnUnloadEventCompleted -= OnUnloadEventCompleted; + AssertOnTimeout($"Timed out waiting for all clients to unload scene {sceneToUnload.name}!"); + } + + private bool m_LoadEventCompleted; + private void OnLoadEventCompleted(string sceneName, LoadSceneMode loadSceneMode, List clientsCompleted, List clientsTimedOut) + { + m_LoadEventCompleted = true; + } + + private bool m_UnloadEventCompleted; + private void OnUnloadEventCompleted(string sceneName, LoadSceneMode loadSceneMode, List clientsCompleted, List clientsTimedOut) + { + m_UnloadEventCompleted = true; + } + /// /// Callback invoked when a test prefab, with the /// component attached, is destroyed. @@ -475,6 +514,8 @@ protected override IEnumerator OnTearDown() m_TestPrefab = null; m_TestPrefabAutoSynchActiveScene = null; m_TestPrefabDestroyWithScene = null; + // Any static event that could be subscribed to but not unsubscribed to due to an assert needs to be cleaned up here. + DestroyWithSceneInstancesTestHelper.NetworkObjectDestroyed -= OnNonActiveSynchDestroyWithSceneNetworkObjectDestroyed; SceneManager.SetActiveScene(m_OriginalActiveScene); m_ServerSpawnedDestroyWithSceneInstances.Clear(); m_ServerSpawnedPrefabInstances.Clear(); diff --git a/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerStartupTests.cs b/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerStartupTests.cs new file mode 100644 index 0000000000..28cd0b49d2 --- /dev/null +++ b/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerStartupTests.cs @@ -0,0 +1,205 @@ +using System.Collections; +using System.Collections.Generic; +using NUnit.Framework; +using Unity.Netcode; +using Unity.Netcode.TestHelpers.Runtime; +using UnityEngine; +using UnityEngine.SceneManagement; +using UnityEngine.TestTools; + +namespace TestProject.RuntimeTests +{ + /// + /// Validates client synchronization. + /// + /// + /// This includes both client synchronization mode passes along with verifying + /// that s migrated into the DDOL will still be spawned + /// and preserve their value. + /// + internal class NetworkSceneManagerStartupTests : NetcodeIntegrationTest + { + private const string k_ActiveScene = "SessionSynchronize"; + private const string k_AdditionalScene = "InSceneNetworkObjectMovesToDDOL"; + + private readonly List m_ObjectsInScenes = new List(); + private Scene m_OriginalActiveScene; + private Scene m_SceneLoaded; + private bool m_CanStart = false; + + // Used with scene pre-loading + private string m_SceneToLoad; + private bool m_SceneWasLoaded; + + #region NetcodeIntegrationTest overrides + protected override int NumberOfClients => 0; + protected override bool CanStartServerAndClients() => m_CanStart; + + protected override void OnOneTimeSetup() + { + // Get the active scene prior to any interation running through the OnSetup. + m_OriginalActiveScene = SceneManager.GetActiveScene(); + base.OnOneTimeSetup(); + } + + protected override IEnumerator OnSetup() + { + // Always reset + m_CanStart = false; + return base.OnSetup(); + } + + protected override void OnCreatePlayerPrefab() + { + // Avoid trying to spawn this + Object.DontDestroyOnLoad(m_PlayerPrefab); + base.OnCreatePlayerPrefab(); + } + + protected override IEnumerator OnTearDown() + { + LogAssert.ignoreFailingMessages = false; + m_ObjectsInScenes.Clear(); + // Restore the integration test scene as the active scene. + SceneManager.SetActiveScene(m_OriginalActiveScene); + + // Unload everything else. + for (int i = 0; i < SceneManager.sceneCount - 1; i++) + { + var scene = SceneManager.GetSceneAt(i); + if (scene == m_OriginalActiveScene) + { + continue; + } + SceneManager.UnloadSceneAsync(scene); + yield return WaitForConditionOrTimeOut(() => !scene.isLoaded); + } + yield return base.OnTearDown(); + } + #endregion + + /// + /// Validates things migrated into the DDOL will be included when synchronizing clients. + /// + /// The client synchronization mode to use for the current pass. + [UnityTest] + public IEnumerator AllExistingObjectsAreSpawnedAtStartup([Values] LoadSceneMode clientSynchronizationMode) + { + LogAssert.ignoreFailingMessages = true; + yield return PreLoadScene(k_ActiveScene); + yield return PreLoadScene(k_AdditionalScene); + SceneManager.SetActiveScene(m_SceneLoaded); + + var existingObjects = new List(); + var dontDestroyOnLoadCount = 0; + + // Now get everything migrated into the DDOL and the DDOL scene itself. + var ddolScene = GetNetworkObjectsInDDOL(); + // Validate NetworkObjects in DDOL + foreach (var obj in m_ObjectsInScenes) + { + Assert.IsFalse(obj.IsSpawned, $"NetworkObject {obj.name} should not have been spawned!"); + + existingObjects.Add(obj); + if (obj.gameObject.scene.name == ddolScene.name) + { + dontDestroyOnLoadCount++; + } + } + + Assert.IsNotEmpty(existingObjects, $"Found no existing {nameof(NetworkObject)}s!"); + Assert.That(dontDestroyOnLoadCount, Is.GreaterThan(0), "Found no {nameof(NetworkObject)}s in the DDOL scene!"); + + // Now enable starting server and clients and start the server + m_CanStart = true; + yield return StartServerAndClients(); + + // Apply the test's client synchronization mode + GetAuthorityNetworkManager().SceneManager.SetClientSynchronizationMode(clientSynchronizationMode); + + // Validate the existing objects + foreach (var existingObject in existingObjects) + { + Assert.IsFalse(existingObject == null, "Expected existing object to still exist!"); + Assert.IsTrue(existingObject.IsSpawned, $"NetworkObject {existingObject.name} in scene {existingObject.gameObject.scene.name} was not spawned!"); + Assert.IsTrue(existingObject.InScenePlaced, $"NetworkObject {existingObject.name} in scene {existingObject.gameObject.scene.name} was not inScenePlaced!"); + } + + // If additive client synchronization mode, load the scenes that are already loaded + // on the scene authority instance so they will be used during client synchronization. + if (clientSynchronizationMode == LoadSceneMode.Additive) + { + yield return PreLoadScene(k_ActiveScene); + yield return PreLoadScene(k_AdditionalScene); + } + + // Late join a client + yield return CreateAndStartNewClient(); + + // Wait for all existing objects to spawn on the client + yield return WaitForSpawnedOnAllOrTimeOut(existingObjects); + AssertOnTimeout("Timed out waiting for objects to spawn on all clients!"); + } + + #region Scene loading and related methods + + /// + /// Uses the 's current scene which should be + /// the DDOL scene. + /// + /// The DDOL scene + private Scene GetNetworkObjectsInDDOL() + { + // This does catch any newly instantiated in-scene placed NetworkObjects moved into DDOL + // during awake. + var sceneToUse = NetworkManager.Singleton.gameObject.scene; + Assert.IsTrue(sceneToUse.IsValid() && sceneToUse.name == "DontDestroyOnLoad", $"[{NetworkManager.Singleton.name}] Is not in the DDOL! Is this being invoked too early?"); + + foreach (var rootObject in sceneToUse.GetRootGameObjects()) + { + foreach (var networkObject in rootObject.GetComponentsInChildren()) + { + if (!m_ObjectsInScenes.Contains(networkObject) && networkObject.InScenePlaced) + { + m_ObjectsInScenes.Add(networkObject); + } + } + } + return sceneToUse; + } + + private IEnumerator PreLoadScene(string sceneName) + { + m_SceneToLoad = sceneName; + m_SceneWasLoaded = false; + SceneManager.sceneLoaded += OnSceneLoad; + SceneManager.LoadScene(sceneName, LoadSceneMode.Additive); + yield return WaitForConditionOrTimeOut(() => m_SceneWasLoaded); + AssertOnTimeout("Timed out waiting for scene to load!"); + SceneManager.sceneLoaded -= OnSceneLoad; + } + + private void TrackObjectsInScene(Scene scene) + { + // This does not catch things moved into the DDOL during awake. + foreach (var rootObject in scene.GetRootGameObjects()) + { + foreach (var networkObject in rootObject.GetComponentsInChildren()) + { + m_ObjectsInScenes.Add(networkObject); + } + } + } + + private void OnSceneLoad(Scene scene, LoadSceneMode loadSceneMode) + { + if (m_SceneToLoad == scene.name) + { + m_SceneWasLoaded = true; + m_SceneLoaded = scene; + TrackObjectsInScene(scene); + } + } + #endregion + } +} diff --git a/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerStartupTests.cs.meta b/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerStartupTests.cs.meta new file mode 100644 index 0000000000..ddf1a7550e --- /dev/null +++ b/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerStartupTests.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ca8e58d04b6fc6c48a6661c90d4c12dd \ No newline at end of file diff --git a/testproject/ProjectSettings/EditorBuildSettings.asset b/testproject/ProjectSettings/EditorBuildSettings.asset index 9a93a17af6..63b5a1481e 100644 --- a/testproject/ProjectSettings/EditorBuildSettings.asset +++ b/testproject/ProjectSettings/EditorBuildSettings.asset @@ -44,9 +44,6 @@ EditorBuildSettings: - enabled: 1 path: Assets/Tests/Manual/NetworkSceneManagerCallbacks/SceneWeAreSwitchingFrom.unity guid: 073bd2111475c0643be45b7abe6a97ad - - enabled: 1 - path: Assets/Scenes/MultiprocessTestScene.unity - guid: 76743cb7b342c49279327834918a9c6e - enabled: 1 path: Assets/Scenes/EmptyScene.unity guid: a2545a872c007404fbb6b0393ab74974 @@ -161,7 +158,9 @@ EditorBuildSettings: - enabled: 1 path: Assets/Tests/Manual/NetworkAnimatorTests/AnimationBidirectionalTriggers/NetworkAnimatorDualTriggerCheer.unity guid: e12df855278120245a8a936a6a52b5bd + - enabled: 1 + path: Assets/Tests/Manual/IntegrationTestScenes/InSceneNetworkObjectMovesToDDOL.unity + guid: 4c20c17b4f92e634f8796b0460851d49 m_configObjects: com.unity.addressableassets: {fileID: 11400000, guid: 5a3d5c53c25349c48912726ae850f3b0, type: 2} - m_UseUCBPForAssetBundles: 0