diff --git a/com.unity.netcode.gameobjects/Components/NetworkTransform.cs b/com.unity.netcode.gameobjects/Components/NetworkTransform.cs index 82c1ab8b2c..40d244168c 100644 --- a/com.unity.netcode.gameobjects/Components/NetworkTransform.cs +++ b/com.unity.netcode.gameobjects/Components/NetworkTransform.cs @@ -60,8 +60,8 @@ internal struct NetworkTransformState : INetworkSerializable private const int k_ScaleYBit = 8; private const int k_ScaleZBit = 9; private const int k_TeleportingBit = 10; - // 11-15: + private ushort m_Bitset; internal bool InLocalSpace @@ -366,7 +366,22 @@ public void NetworkSerialize(BufferSerializer serializer) where T : IReade /// protected NetworkManager m_CachedNetworkManager; - private readonly NetworkVariable m_ReplicatedNetworkState = new NetworkVariable(new NetworkTransformState()); + private readonly NetworkVariable m_ReplicatedNetworkStateServer = new NetworkVariable(new NetworkTransformState(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); + private readonly NetworkVariable m_ReplicatedNetworkStateOwner = new NetworkVariable(new NetworkTransformState(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + + + internal NetworkVariable ReplicatedNetworkState + { + get + { + if (!IsServerAuthoritative()) + { + return m_ReplicatedNetworkStateOwner; + } + + return m_ReplicatedNetworkStateServer; + } + } private NetworkTransformState m_LocalAuthoritativeNetworkState; @@ -388,20 +403,36 @@ public void NetworkSerialize(BufferSerializer serializer) where T : IReade private int m_LastSentTick; private NetworkTransformState m_LastSentState; + internal NetworkTransformState GetLastSentState() + { + return m_LastSentState; + } + /// - /// Tries updating the server authoritative transform, only if allowed. - /// If this called server side, this will commit directly. - /// If no update is needed, nothing will be sent. This method should still be called every update, it'll self manage when it should and shouldn't send + /// Refer to , this is a legacy method. /// - /// - /// protected void TryCommitTransformToServer(Transform transformToCommit, double dirtyTime) { + TryCommitTransform(transformToCommit, dirtyTime); + } + + /// + /// Tries updating the server authoritative transform, only if allowed. + /// + /// the transform to be committed + /// time it was marked dirty + protected void TryCommitTransform(Transform transformToCommit, double dirtyTime) + { + if (!CanCommitToTransform) + { + NetworkLog.LogError($"[{name}] is trying to commit the transform without authority!"); + return; + } var isDirty = ApplyTransformToNetworkState(ref m_LocalAuthoritativeNetworkState, dirtyTime, transformToCommit); TryCommit(isDirty); } - private void TryCommitValuesToServer(Vector3 position, Vector3 rotation, Vector3 scale, double dirtyTime) + private void TryCommitValues(Vector3 position, Vector3 rotation, Vector3 scale, double dirtyTime) { var isDirty = ApplyTransformToNetworkStateWithInfo(ref m_LocalAuthoritativeNetworkState, dirtyTime, position, rotation, scale); @@ -412,7 +443,7 @@ private void TryCommit(bool isDirty) { void Send(NetworkTransformState stateToSend) { - if (m_CachedIsServer) + if (CanCommitToTransform) { // server RPC takes a few frames to execute server side, we want this to execute immediately CommitLocallyAndReplicate(stateToSend); @@ -456,12 +487,7 @@ private void CommitTransformServerRpc(NetworkTransformState networkState, Server private void CommitLocallyAndReplicate(NetworkTransformState networkState) { - m_ReplicatedNetworkState.Value = networkState; - - if (Interpolate) - { - AddInterpolatedState(networkState); - } + ReplicatedNetworkState.Value = networkState; } private void ResetInterpolatedStateToCurrentAuthoritativeState() @@ -523,76 +549,130 @@ internal bool ApplyTransformToNetworkState(ref NetworkTransformState networkStat // this still is overly costly and could use more improvements. // // (ditto for scale components) - if (SyncPositionX && - Mathf.Abs(networkState.PositionX - position.x) > PositionThreshold) + if (SyncPositionX) { - networkState.PositionX = position.x; - networkState.HasPositionX = true; - isPositionDirty = true; + if (Mathf.Abs(networkState.PositionX - position.x) > PositionThreshold) + { + networkState.PositionX = position.x; + networkState.HasPositionX = true; + isPositionDirty = true; + } + else + { + networkState.HasPositionX = false; + } } - if (SyncPositionY && - Mathf.Abs(networkState.PositionY - position.y) > PositionThreshold) + if (SyncPositionY) { - networkState.PositionY = position.y; - networkState.HasPositionY = true; - isPositionDirty = true; + if (Mathf.Abs(networkState.PositionY - position.y) > PositionThreshold) + { + networkState.PositionY = position.y; + networkState.HasPositionY = true; + isPositionDirty = true; + } + else + { + networkState.HasPositionY = false; + } } - if (SyncPositionZ && - Mathf.Abs(networkState.PositionZ - position.z) > PositionThreshold) + if (SyncPositionZ) { - networkState.PositionZ = position.z; - networkState.HasPositionZ = true; - isPositionDirty = true; + if (Mathf.Abs(networkState.PositionZ - position.z) > PositionThreshold) + { + networkState.PositionZ = position.z; + networkState.HasPositionZ = true; + isPositionDirty = true; + } + else + { + networkState.HasPositionZ = false; + } } - if (SyncRotAngleX && - Mathf.Abs(Mathf.DeltaAngle(networkState.RotAngleX, rotAngles.x)) > RotAngleThreshold) + if (SyncRotAngleX) { - networkState.RotAngleX = rotAngles.x; - networkState.HasRotAngleX = true; - isRotationDirty = true; + if (Mathf.Abs(Mathf.DeltaAngle(networkState.RotAngleX, rotAngles.x)) > RotAngleThreshold) + { + networkState.RotAngleX = rotAngles.x; + networkState.HasRotAngleX = true; + isRotationDirty = true; + } + else + { + networkState.HasRotAngleX = false; + } } - if (SyncRotAngleY && - Mathf.Abs(Mathf.DeltaAngle(networkState.RotAngleY, rotAngles.y)) > RotAngleThreshold) + if (SyncRotAngleY) { - networkState.RotAngleY = rotAngles.y; - networkState.HasRotAngleY = true; - isRotationDirty = true; + if (Mathf.Abs(Mathf.DeltaAngle(networkState.RotAngleY, rotAngles.y)) > RotAngleThreshold) + { + networkState.RotAngleY = rotAngles.y; + networkState.HasRotAngleY = true; + isRotationDirty = true; + } + else + { + networkState.HasRotAngleY = false; + } } - if (SyncRotAngleZ && - Mathf.Abs(Mathf.DeltaAngle(networkState.RotAngleZ, rotAngles.z)) > RotAngleThreshold) + if (SyncRotAngleZ) { - networkState.RotAngleZ = rotAngles.z; - networkState.HasRotAngleZ = true; - isRotationDirty = true; + if (Mathf.Abs(Mathf.DeltaAngle(networkState.RotAngleZ, rotAngles.z)) > RotAngleThreshold) + { + networkState.RotAngleZ = rotAngles.z; + networkState.HasRotAngleZ = true; + isRotationDirty = true; + } + else + { + networkState.HasRotAngleZ = false; + } } - if (SyncScaleX && - Mathf.Abs(networkState.ScaleX - scale.x) > ScaleThreshold) + if (SyncScaleX) { - networkState.ScaleX = scale.x; - networkState.HasScaleX = true; - isScaleDirty = true; + if (Mathf.Abs(networkState.ScaleX - scale.x) > ScaleThreshold) + { + networkState.ScaleX = scale.x; + networkState.HasScaleX = true; + isScaleDirty = true; + } + else + { + networkState.HasScaleX = false; + } } - if (SyncScaleY && - Mathf.Abs(networkState.ScaleY - scale.y) > ScaleThreshold) + if (SyncScaleY) { - networkState.ScaleY = scale.y; - networkState.HasScaleY = true; - isScaleDirty = true; + if (Mathf.Abs(networkState.ScaleY - scale.y) > ScaleThreshold) + { + networkState.ScaleY = scale.y; + networkState.HasScaleY = true; + isScaleDirty = true; + } + else + { + networkState.HasScaleY = false; + } } - if (SyncScaleZ && - Mathf.Abs(networkState.ScaleZ - scale.z) > ScaleThreshold) + if (SyncScaleZ) { - networkState.ScaleZ = scale.z; - networkState.HasScaleZ = true; - isScaleDirty = true; + if (Mathf.Abs(networkState.ScaleZ - scale.z) > ScaleThreshold) + { + networkState.ScaleZ = scale.z; + networkState.HasScaleZ = true; + isScaleDirty = true; + } + else + { + networkState.HasScaleZ = false; + } } isDirty |= isPositionDirty || isRotationDirty || isScaleDirty; @@ -605,7 +685,15 @@ internal bool ApplyTransformToNetworkState(ref NetworkTransformState networkStat return (isDirty, isPositionDirty, isRotationDirty, isScaleDirty); } - private void ApplyInterpolatedNetworkStateToTransform(NetworkTransformState networkState, Transform transformToUpdate) + /// + /// Applies the authoritative state to the local transform + /// + /// + /// The serverTime is required for position and scale in order to prevent a single element of each 3 elements + /// from having too large of a delta time between the time it was last updated and the time any new update is + /// sent. + /// + private void ApplyInterpolatedNetworkStateToTransform(NetworkTransformState networkState, Transform transformToUpdate, double serverTime) { var interpolatedPosition = InLocalSpace ? transformToUpdate.localPosition : transformToUpdate.position; @@ -615,24 +703,25 @@ private void ApplyInterpolatedNetworkStateToTransform(NetworkTransformState netw // InLocalSpace Read InLocalSpace = networkState.InLocalSpace; - // Position Read - if (SyncPositionX) + + // Update the position values that were changed in this state update + if (networkState.HasPositionX) { interpolatedPosition.x = networkState.IsTeleportingNextFrame || !Interpolate ? networkState.Position.x : m_PositionXInterpolator.GetInterpolatedValue(); } - if (SyncPositionY) + if (networkState.HasPositionY) { interpolatedPosition.y = networkState.IsTeleportingNextFrame || !Interpolate ? networkState.Position.y : m_PositionYInterpolator.GetInterpolatedValue(); } - if (SyncPositionZ) + if (networkState.HasPositionZ) { interpolatedPosition.z = networkState.IsTeleportingNextFrame || !Interpolate ? networkState.Position.z : m_PositionZInterpolator.GetInterpolatedValue(); } - // again, we should be using quats here - if (SyncRotAngleX || SyncRotAngleY || SyncRotAngleZ) + // Update the rotation values that were changed in this state update + if (networkState.HasRotAngleX || networkState.HasRotAngleY || networkState.HasRotAngleZ) { var eulerAngles = new Vector3(); if (Interpolate) @@ -640,43 +729,44 @@ private void ApplyInterpolatedNetworkStateToTransform(NetworkTransformState netw eulerAngles = m_RotationInterpolator.GetInterpolatedValue().eulerAngles; } - if (SyncRotAngleX) + if (networkState.HasRotAngleX) { interpolatedRotAngles.x = networkState.IsTeleportingNextFrame || !Interpolate ? networkState.Rotation.x : eulerAngles.x; } - if (SyncRotAngleY) + if (networkState.HasRotAngleY) { interpolatedRotAngles.y = networkState.IsTeleportingNextFrame || !Interpolate ? networkState.Rotation.y : eulerAngles.y; } - if (SyncRotAngleZ) + if (networkState.HasRotAngleZ) { interpolatedRotAngles.z = networkState.IsTeleportingNextFrame || !Interpolate ? networkState.Rotation.z : eulerAngles.z; } } - // Scale Read - if (SyncScaleX) + // Update all scale axis that were changed in this state update + if (networkState.HasScaleX) { interpolatedScale.x = networkState.IsTeleportingNextFrame || !Interpolate ? networkState.Scale.x : m_ScaleXInterpolator.GetInterpolatedValue(); } - if (SyncScaleY) + if (networkState.HasScaleY) { interpolatedScale.y = networkState.IsTeleportingNextFrame || !Interpolate ? networkState.Scale.y : m_ScaleYInterpolator.GetInterpolatedValue(); } - if (SyncScaleZ) + if (networkState.HasScaleZ) { interpolatedScale.z = networkState.IsTeleportingNextFrame || !Interpolate ? networkState.Scale.z : m_ScaleZInterpolator.GetInterpolatedValue(); } - // Position Apply - if (SyncPositionX || SyncPositionY || SyncPositionZ) + // Apply the new position + if (networkState.HasPositionX || networkState.HasPositionY || networkState.HasPositionZ) { if (InLocalSpace) { + transformToUpdate.localPosition = interpolatedPosition; } else @@ -685,8 +775,8 @@ private void ApplyInterpolatedNetworkStateToTransform(NetworkTransformState netw } } - // RotAngles Apply - if (SyncRotAngleX || SyncRotAngleY || SyncRotAngleZ) + // Apply the new rotation + if (networkState.HasRotAngleX || networkState.HasRotAngleY || networkState.HasRotAngleZ) { if (InLocalSpace) { @@ -698,8 +788,8 @@ private void ApplyInterpolatedNetworkStateToTransform(NetworkTransformState netw } } - // Scale Apply - if (SyncScaleX || SyncScaleY || SyncScaleZ) + // Apply the new scale + if (networkState.HasScaleX || networkState.HasScaleY || networkState.HasScaleZ) { transformToUpdate.localScale = interpolatedScale; } @@ -745,37 +835,76 @@ private void AddInterpolatedState(NetworkTransformState newState, bool reset = f return; } + + var currentPosition = InLocalSpace ? m_Transform.localPosition : m_Transform.position; + + // Note: Any values we don't have an update for need their interpolator deltas reset. + // Bandwidth optimizations mean that an update without the value set indicates "this hasn't changed", + // and so we need to tell the interpolators that it's the last currently known axis value(s) at this + // time delta. + if (newState.HasPositionX) { m_PositionXInterpolator.AddMeasurement(newState.PositionX, sentTime); } + else + { + m_PositionXInterpolator.AddMeasurement(m_LastStatePosition.x, sentTime); + } if (newState.HasPositionY) { m_PositionYInterpolator.AddMeasurement(newState.PositionY, sentTime); } + else + { + m_PositionYInterpolator.AddMeasurement(m_LastStatePosition.y, sentTime); + } if (newState.HasPositionZ) { m_PositionZInterpolator.AddMeasurement(newState.PositionZ, sentTime); } + else + { + m_PositionZInterpolator.AddMeasurement(m_LastStatePosition.z, sentTime); + } - m_RotationInterpolator.AddMeasurement(Quaternion.Euler(newState.Rotation), sentTime); + if (newState.HasRotAngleX || newState.HasRotAngleY || newState.HasRotAngleZ) + { + m_RotationInterpolator.AddMeasurement(Quaternion.Euler(newState.Rotation), sentTime); + } + else + { + m_RotationInterpolator.AddMeasurement(m_LastStateRotation, sentTime); + } if (newState.HasScaleX) { m_ScaleXInterpolator.AddMeasurement(newState.ScaleX, sentTime); } + else + { + m_ScaleXInterpolator.AddMeasurement(m_LocalScale.x, sentTime); + } if (newState.HasScaleY) { m_ScaleYInterpolator.AddMeasurement(newState.ScaleY, sentTime); } + else + { + m_ScaleYInterpolator.AddMeasurement(m_LocalScale.y, sentTime); + } if (newState.HasScaleZ) { m_ScaleZInterpolator.AddMeasurement(newState.ScaleZ, sentTime); } + else + { + m_ScaleZInterpolator.AddMeasurement(m_LocalScale.z, sentTime); + } } private void OnNetworkStateChanged(NetworkTransformState oldState, NetworkTransformState newState) @@ -796,11 +925,6 @@ private void OnNetworkStateChanged(NetworkTransformState oldState, NetworkTransf AddInterpolatedState(newState, (newState.InLocalSpace != m_LastInterpolateLocal)); } m_LastInterpolateLocal = newState.InLocalSpace; - - if (m_CachedNetworkManager.LogLevel == LogLevel.Developer) - { - var pos = new Vector3(newState.PositionX, newState.PositionY, newState.PositionZ); - } } /// @@ -844,26 +968,57 @@ private void Awake() } } + /// + /// These local values are for the non-authoritative side + /// This prevents non-authoritative instances from changing + /// the transform. + /// + private Vector3 m_LastStatePosition; + private Vector3 m_LocalScale; + private Quaternion m_LastStateRotation; + + /// + /// Applies the last authorized position, scale, and rotation + /// + private void ApplyTransformValues() + { + if (InLocalSpace) + { + m_Transform.localPosition = m_LastStatePosition; + } + else + { + m_Transform.position = m_LastStatePosition; + } + + if (InLocalSpace) + { + m_Transform.localRotation = m_LastStateRotation; + } + else + { + m_Transform.rotation = m_LastStateRotation; + } + + m_Transform.localScale = m_LocalScale; + } + + /// + /// Sets the currently authorized position, scale, and rotation + /// + private void SetTransformValues() + { + m_LastStatePosition = InLocalSpace ? m_Transform.localPosition : m_Transform.position; + m_LastStateRotation = InLocalSpace ? m_Transform.localRotation : m_Transform.rotation; + m_LocalScale = m_Transform.localScale; + } /// public override void OnNetworkSpawn() { - // must set up m_Transform in OnNetworkSpawn because it's possible an object spawns but is disabled - // and thus awake won't be called. - // TODO: investigate further on not sending data for something that is not enabled - m_Transform = transform; - m_ReplicatedNetworkState.OnValueChanged += OnNetworkStateChanged; - - CanCommitToTransform = IsServer; m_CachedIsServer = IsServer; m_CachedNetworkManager = NetworkManager; - if (CanCommitToTransform) - { - TryCommitTransformToServer(m_Transform, m_CachedNetworkManager.LocalTime.Time); - } - m_LocalAuthoritativeNetworkState = m_ReplicatedNetworkState.Value; - // crucial we do this to reset the interpolators so that recycled objects when using a pool will // not have leftover interpolator state from the previous object Initialize(); @@ -872,7 +1027,7 @@ public override void OnNetworkSpawn() /// public override void OnNetworkDespawn() { - m_ReplicatedNetworkState.OnValueChanged -= OnNetworkStateChanged; + ReplicatedNetworkState.OnValueChanged -= OnNetworkStateChanged; } /// @@ -889,15 +1044,35 @@ public override void OnLostOwnership() private void Initialize() { - ResetInterpolatedStateToCurrentAuthoritativeState(); // useful for late joining + if (!IsSpawned) + { + return; + } + + // must set up m_Transform in OnNetworkSpawn because it's possible an object spawns but is disabled + // and thus awake won't be called. + // TODO: investigate further on not sending data for something that is not enabled + m_Transform = transform; + + CanCommitToTransform = IsServerAuthoritative() ? IsServer : IsOwner; + var replicatedState = ReplicatedNetworkState; + m_LocalAuthoritativeNetworkState = replicatedState.Value; if (CanCommitToTransform) { - m_ReplicatedNetworkState.SetDirty(true); + replicatedState.OnValueChanged -= OnNetworkStateChanged; + TryCommitTransform(m_Transform, m_CachedNetworkManager.LocalTime.Time); + replicatedState.SetDirty(true); } - else if (m_Transform != null) + else { - ApplyInterpolatedNetworkStateToTransform(m_ReplicatedNetworkState.Value, m_Transform); + replicatedState.OnValueChanged += OnNetworkStateChanged; + + // In case we are late joining + ResetInterpolatedStateToCurrentAuthoritativeState(); + + // For the non-authoritative side, we need to capture the initial values of the transform + SetTransformValues(); } } @@ -970,36 +1145,31 @@ protected virtual void Update() return; } - if (!Interpolate && m_LastInterpolate) + if (CanCommitToTransform) { - // if we just stopped interpolating, let's clear the interpolators - foreach (var interpolator in m_AllFloatInterpolators) - { - interpolator.Clear(); - } + TryCommitTransform(m_Transform, m_CachedNetworkManager.LocalTime.Time); } - - m_LastInterpolate = Interpolate; - - if (CanCommitToTransform) + else { - if (m_CachedIsServer) + if (!Interpolate && m_LastInterpolate) { - TryCommitTransformToServer(m_Transform, m_CachedNetworkManager.LocalTime.Time); + // if we just stopped interpolating, let's clear the interpolators + foreach (var interpolator in m_AllFloatInterpolators) + { + interpolator.Clear(); + } } - } - // apply interpolated value - if (m_CachedNetworkManager.IsConnectedClient || m_CachedNetworkManager.IsListening) - { + m_LastInterpolate = Interpolate; + // eventually, we could hoist this calculation so that it happens once for all objects, not once per object - var cachedDeltaTime = Time.deltaTime; - var serverTime = NetworkManager.ServerTime; - var cachedServerTime = serverTime.Time; - var cachedRenderTime = serverTime.TimeTicksAgo(1).Time; + var serverTime = NetworkManager.ServerTime; if (Interpolate) { + var cachedDeltaTime = Time.deltaTime; + var cachedServerTime = serverTime.Time; + var cachedRenderTime = serverTime.TimeTicksAgo(1).Time; foreach (var interpolator in m_AllFloatInterpolators) { interpolator.Update(cachedDeltaTime, cachedRenderTime, cachedServerTime); @@ -1008,17 +1178,22 @@ protected virtual void Update() m_RotationInterpolator.Update(cachedDeltaTime, cachedRenderTime, cachedServerTime); } - if (!CanCommitToTransform) - { - // Apply updated interpolated value - ApplyInterpolatedNetworkStateToTransform(m_ReplicatedNetworkState.Value, m_Transform); - } + // Always update from the last transform values before updating from the transform state to assure + // no non-authoritative changes are allowed + ApplyTransformValues(); + + // Apply updated interpolated value + ApplyInterpolatedNetworkStateToTransform(ReplicatedNetworkState.Value, m_Transform, serverTime.Time); + + // Always set the any new transform values to assure only the authoritative side is updating the transform + SetTransformValues(); } + m_LocalAuthoritativeNetworkState.IsTeleportingNextFrame = false; } /// - /// Teleports the transform to the given values without interpolating + /// Teleport the transform to the given values without interpolating /// /// new position to move to. /// new rotation to rotate to. @@ -1037,11 +1212,11 @@ public void Teleport(Vector3 newPosition, Quaternion newRotation, Vector3 newSca stateToSend.Position = newPosition; stateToSend.Rotation = newRotationEuler; stateToSend.Scale = newScale; - ApplyInterpolatedNetworkStateToTransform(stateToSend, transform); + // set teleport flag in state to signal to ghosts not to interpolate m_LocalAuthoritativeNetworkState.IsTeleportingNextFrame = true; - // check server side - TryCommitValuesToServer(newPosition, newRotationEuler, newScale, m_CachedNetworkManager.LocalTime.Time); + + TryCommitValues(newPosition, newRotationEuler, newScale, m_CachedNetworkManager.LocalTime.Time); m_LocalAuthoritativeNetworkState.IsTeleportingNextFrame = false; } diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs index 0d6c58ff4e..d248d929c0 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; #if NGO_TRANSFORM_DEBUG using System.Text.RegularExpressions; @@ -57,7 +56,7 @@ protected override void OnCreatePlayerPrefab() else { var networkTransform = m_PlayerPrefab.AddComponent(); - networkTransform.Interpolate = false; + networkTransform.Interpolate = true; } } @@ -74,8 +73,8 @@ protected override void OnServerAndClientsCreated() protected override IEnumerator OnServerAndClientsConnected() { // Get the client player representation on both the server and the client side - m_ServerSideClientPlayer = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId]; - m_ClientSideClientPlayer = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ClientNetworkManagers[0].LocalClientId]; + m_ServerSideClientPlayer = m_ServerNetworkManager.ConnectedClients[m_ClientNetworkManagers[0].LocalClientId].PlayerObject; + m_ClientSideClientPlayer = m_ClientNetworkManagers[0].LocalClient.PlayerObject; // Get the NetworkTransformTestComponent to make sure the client side is ready before starting test var otherSideNetworkTransformComponent = m_ClientSideClientPlayer.GetComponent(); @@ -118,38 +117,38 @@ public IEnumerator TestAuthoritativeTransformChangeOneAtATime([Values] bool test authPlayerTransform.position = new Vector3(10, 20, 30); - yield return WaitForConditionOrTimeOut(() => otherSideNetworkTransform.transform.position.x > approximation); + yield return WaitForConditionOrTimeOut(ServerClientPositionMatches); - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"timeout while waiting for position change! Otherside value {otherSideNetworkTransform.transform.position.x} vs. Approximation {approximation}"); + AssertOnTimeout($"timeout while waiting for position change! Otherside value {otherSideNetworkTransform.transform.position.x} vs. Approximation {approximation}"); - Assert.True(new Vector3(10, 20, 30) == otherSideNetworkTransform.transform.position, $"wrong position on ghost, {otherSideNetworkTransform.transform.position}"); // Vector3 already does float approximation with == + //Assert.True(new Vector3(10, 20, 30) == otherSideNetworkTransform.transform.position, $"wrong position on ghost, {otherSideNetworkTransform.transform.position}"); // Vector3 already does float approximation with == // test rotation authPlayerTransform.rotation = Quaternion.Euler(45, 40, 35); // using euler angles instead of quaternions directly to really see issues users might encounter Assert.AreEqual(Quaternion.identity, otherSideNetworkTransform.transform.rotation, "wrong initial value for rotation"); // sanity check - yield return WaitForConditionOrTimeOut(() => otherSideNetworkTransform.transform.rotation.eulerAngles.x > approximation); + yield return WaitForConditionOrTimeOut(ServerClientRotationMatches); - Assert.False(s_GlobalTimeoutHelper.TimedOut, "timeout while waiting for rotation change"); + AssertOnTimeout("timeout while waiting for rotation change"); - // approximation needed here since eulerAngles isn't super precise. - Assert.LessOrEqual(Math.Abs(45 - otherSideNetworkTransform.transform.rotation.eulerAngles.x), approximation, $"wrong rotation on ghost on x, got {otherSideNetworkTransform.transform.rotation.eulerAngles.x}"); - Assert.LessOrEqual(Math.Abs(40 - otherSideNetworkTransform.transform.rotation.eulerAngles.y), approximation, $"wrong rotation on ghost on y, got {otherSideNetworkTransform.transform.rotation.eulerAngles.y}"); - Assert.LessOrEqual(Math.Abs(35 - otherSideNetworkTransform.transform.rotation.eulerAngles.z), approximation, $"wrong rotation on ghost on z, got {otherSideNetworkTransform.transform.rotation.eulerAngles.z}"); + //// approximation needed here since eulerAngles isn't super precise. + //Assert.LessOrEqual(Math.Abs(45 - otherSideNetworkTransform.transform.rotation.eulerAngles.x), approximation, $"wrong rotation on ghost on x, got {otherSideNetworkTransform.transform.rotation.eulerAngles.x}"); + //Assert.LessOrEqual(Math.Abs(40 - otherSideNetworkTransform.transform.rotation.eulerAngles.y), approximation, $"wrong rotation on ghost on y, got {otherSideNetworkTransform.transform.rotation.eulerAngles.y}"); + //Assert.LessOrEqual(Math.Abs(35 - otherSideNetworkTransform.transform.rotation.eulerAngles.z), approximation, $"wrong rotation on ghost on z, got {otherSideNetworkTransform.transform.rotation.eulerAngles.z}"); // test scale - UnityEngine.Assertions.Assert.AreApproximatelyEqual(1f, otherSideNetworkTransform.transform.lossyScale.x, "wrong initial value for scale"); // sanity check - UnityEngine.Assertions.Assert.AreApproximatelyEqual(1f, otherSideNetworkTransform.transform.lossyScale.y, "wrong initial value for scale"); // sanity check - UnityEngine.Assertions.Assert.AreApproximatelyEqual(1f, otherSideNetworkTransform.transform.lossyScale.z, "wrong initial value for scale"); // sanity check + //UnityEngine.Assertions.Assert.AreApproximatelyEqual(1f, otherSideNetworkTransform.transform.lossyScale.x, "wrong initial value for scale"); // sanity check + //UnityEngine.Assertions.Assert.AreApproximatelyEqual(1f, otherSideNetworkTransform.transform.lossyScale.y, "wrong initial value for scale"); // sanity check + //UnityEngine.Assertions.Assert.AreApproximatelyEqual(1f, otherSideNetworkTransform.transform.lossyScale.z, "wrong initial value for scale"); // sanity check authPlayerTransform.localScale = new Vector3(2, 3, 4); - yield return WaitForConditionOrTimeOut(() => otherSideNetworkTransform.transform.lossyScale.x > 1f + approximation); + yield return WaitForConditionOrTimeOut(ServerClientScaleMatches); - Assert.False(s_GlobalTimeoutHelper.TimedOut, "timeout while waiting for scale change"); + AssertOnTimeout("timeout while waiting for scale change"); - UnityEngine.Assertions.Assert.AreApproximatelyEqual(2f, otherSideNetworkTransform.transform.lossyScale.x, "wrong scale on ghost"); - UnityEngine.Assertions.Assert.AreApproximatelyEqual(3f, otherSideNetworkTransform.transform.lossyScale.y, "wrong scale on ghost"); - UnityEngine.Assertions.Assert.AreApproximatelyEqual(4f, otherSideNetworkTransform.transform.lossyScale.z, "wrong scale on ghost"); + //UnityEngine.Assertions.Assert.AreApproximatelyEqual(2f, otherSideNetworkTransform.transform.lossyScale.x, "wrong scale on ghost"); + //UnityEngine.Assertions.Assert.AreApproximatelyEqual(3f, otherSideNetworkTransform.transform.lossyScale.y, "wrong scale on ghost"); + //UnityEngine.Assertions.Assert.AreApproximatelyEqual(4f, otherSideNetworkTransform.transform.lossyScale.z, "wrong scale on ghost"); // todo reparent and test // todo test all public API @@ -251,6 +250,93 @@ public IEnumerator TestRotationThresholdDeltaCheck() Assert.IsTrue(results.isRotationDirty, $"Rotation was not dirty when rotated by {Mathf.DeltaAngle(0, serverEulerRotation.y)} degrees!"); } + private bool ValidateBitSetValues(NetworkTransform.NetworkTransformState serverState, NetworkTransform.NetworkTransformState clientState) + { + if (serverState.HasPositionX == clientState.HasPositionX && serverState.HasPositionY == clientState.HasPositionY && serverState.HasPositionZ == clientState.HasPositionZ && + serverState.HasRotAngleX == clientState.HasRotAngleX && serverState.HasRotAngleY == clientState.HasRotAngleY && serverState.HasRotAngleZ == clientState.HasRotAngleZ && + serverState.HasScaleX == clientState.HasScaleX && serverState.HasScaleY == clientState.HasScaleY && serverState.HasScaleZ == clientState.HasScaleZ) + { + return true; + } + return false; + } + + /// + /// + [UnityTest] + public IEnumerator TestBitsetValue() + { + // Get the client player's NetworkTransform for both instances + var authoritativeNetworkTransform = m_ServerSideClientPlayer.GetComponent(); + var otherSideNetworkTransform = m_ClientSideClientPlayer.GetComponent(); + otherSideNetworkTransform.RotAngleThreshold = authoritativeNetworkTransform.RotAngleThreshold = 0.1f; + yield return s_DefaultWaitForTick; + + authoritativeNetworkTransform.Interpolate = true; + otherSideNetworkTransform.Interpolate = true; + + yield return s_DefaultWaitForTick; + + authoritativeNetworkTransform.transform.rotation = Quaternion.Euler(1, 2, 3); + var serverLastSentState = authoritativeNetworkTransform.GetLastSentState(); + var clientReplicatedState = otherSideNetworkTransform.ReplicatedNetworkState.Value; + yield return WaitForConditionOrTimeOut(() => ValidateBitSetValues(serverLastSentState, clientReplicatedState)); + AssertOnTimeout($"Server-side sent Bitset state != Client-side replicated Bitset state!"); + + yield return WaitForConditionOrTimeOut(ServerClientRotationMatches); + AssertOnTimeout($"[Timed-Out] Server-side client rotation {m_ServerSideClientPlayer.transform.rotation.eulerAngles} != Client-side client rotation {m_ClientSideClientPlayer.transform.rotation.eulerAngles}"); + } + + private bool Aproximately(float x, float y) + { + return Mathf.Abs(x - y) <= k_AproximateDeltaVariance; + } + + private const float k_AproximateDeltaVariance = 0.01f; + + private bool ServerClientRotationMatches() + { + var serverEulerRotation = m_ServerSideClientPlayer.transform.rotation.eulerAngles; + var clientEulerRotation = m_ClientSideClientPlayer.transform.rotation.eulerAngles; + var xIsEqual = Aproximately(serverEulerRotation.x, clientEulerRotation.x); + var yIsEqual = Aproximately(serverEulerRotation.y, clientEulerRotation.y); + var zIsEqual = Aproximately(serverEulerRotation.z, clientEulerRotation.z); + if (!xIsEqual || !yIsEqual || !zIsEqual) + { + VerboseDebug($"Server-side client rotation {m_ServerSideClientPlayer.transform.rotation.eulerAngles} != Client-side client rotation {m_ClientSideClientPlayer.transform.rotation.eulerAngles}"); + } + return xIsEqual && yIsEqual && zIsEqual; + } + + private bool ServerClientPositionMatches() + { + var serverPosition = m_ServerSideClientPlayer.transform.position; + var clientPosition = m_ClientSideClientPlayer.transform.position; + var xIsEqual = Aproximately(serverPosition.x, clientPosition.x); + var yIsEqual = Aproximately(serverPosition.y, clientPosition.y); + var zIsEqual = Aproximately(serverPosition.z, clientPosition.z); + if (!xIsEqual || !yIsEqual || !zIsEqual) + { + VerboseDebug($"Server-side client position {m_ServerSideClientPlayer.transform.position} != Client-side client position {m_ClientSideClientPlayer.transform.position}"); + } + return xIsEqual && yIsEqual && zIsEqual; + } + + private bool ServerClientScaleMatches() + { + var serverScale = m_ServerSideClientPlayer.transform.localScale; + var clientScale = m_ClientSideClientPlayer.transform.localScale; + var xIsEqual = Aproximately(serverScale.x, clientScale.x); + var yIsEqual = Aproximately(serverScale.y, clientScale.y); + var zIsEqual = Aproximately(serverScale.z, clientScale.z); + if (!xIsEqual || !yIsEqual || !zIsEqual) + { + VerboseDebug($"Server-side client scale {m_ServerSideClientPlayer.transform.localScale} != Client-side client scale {m_ClientSideClientPlayer.transform.localScale}"); + } + return xIsEqual && yIsEqual && zIsEqual; + } + + /* * ownership change * test teleport with interpolation @@ -259,7 +345,8 @@ public IEnumerator TestRotationThresholdDeltaCheck() */ protected override IEnumerator OnTearDown() { - UnityEngine.Object.DestroyImmediate(m_PlayerPrefab); + m_EnableVerboseDebug = false; + Object.DestroyImmediate(m_PlayerPrefab); yield return base.OnTearDown(); } } diff --git a/testproject/Assets/Prefabs/ObjectToOverride-VariantBlueCylinder.prefab b/testproject/Assets/Prefabs/ObjectToOverride-VariantBlueCylinder.prefab index d584980843..6bcfbaca76 100644 --- a/testproject/Assets/Prefabs/ObjectToOverride-VariantBlueCylinder.prefab +++ b/testproject/Assets/Prefabs/ObjectToOverride-VariantBlueCylinder.prefab @@ -82,5 +82,10 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} + - target: {fileID: 4600632750638426092, guid: 29cabf623d47bb345a9bb4140e4397d7, + type: 3} + propertyPath: PositionThreshold + value: 0.01 + objectReference: {fileID: 0} m_RemovedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 29cabf623d47bb345a9bb4140e4397d7, type: 3} diff --git a/testproject/Assets/Prefabs/Player.prefab b/testproject/Assets/Prefabs/Player.prefab index 82e49fd5c8..fbb2e970a4 100644 --- a/testproject/Assets/Prefabs/Player.prefab +++ b/testproject/Assets/Prefabs/Player.prefab @@ -36,6 +36,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 5, y: 0.625, z: 5} m_LocalScale: {x: 1.25, y: 1.25, z: 1.25} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 3519470446676406143} m_Father: {fileID: 0} @@ -62,12 +63,11 @@ MonoBehaviour: SyncScaleX: 1 SyncScaleY: 1 SyncScaleZ: 1 - PositionThreshold: 0 - RotAngleThreshold: 0 - ScaleThreshold: 0 + PositionThreshold: 0.01 + RotAngleThreshold: 0.01 + ScaleThreshold: 0.1 InLocalSpace: 0 Interpolate: 1 - FixedSendsPerSecond: 15 --- !u!114 &-3775814466963834669 MonoBehaviour: m_ObjectHideFlags: 0 @@ -103,6 +103,7 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 @@ -239,6 +240,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 1.045, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4079352819444256611} m_RootOrder: 0 @@ -262,6 +264,7 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 diff --git a/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/AdditiveSceneMultiInstance.unity b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/AdditiveSceneMultiInstance.unity index 6ea9d5e74b..a762b39af1 100644 --- a/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/AdditiveSceneMultiInstance.unity +++ b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/AdditiveSceneMultiInstance.unity @@ -195,6 +195,21 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} + - target: {fileID: 4600632750638426092, guid: ea906834639fa3f4ba65c95db6181d6b, + type: 3} + propertyPath: ScaleThreshold + value: 0.01 + objectReference: {fileID: 0} + - target: {fileID: 4600632750638426092, guid: ea906834639fa3f4ba65c95db6181d6b, + type: 3} + propertyPath: PositionThreshold + value: 0.01 + objectReference: {fileID: 0} + - target: {fileID: 4600632750638426092, guid: ea906834639fa3f4ba65c95db6181d6b, + type: 3} + propertyPath: RotAngleThreshold + value: 0.1 + objectReference: {fileID: 0} m_RemovedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: ea906834639fa3f4ba65c95db6181d6b, type: 3} --- !u!1001 &365996112 @@ -269,6 +284,21 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} + - target: {fileID: 4600632750638426092, guid: ea906834639fa3f4ba65c95db6181d6b, + type: 3} + propertyPath: ScaleThreshold + value: 0.01 + objectReference: {fileID: 0} + - target: {fileID: 4600632750638426092, guid: ea906834639fa3f4ba65c95db6181d6b, + type: 3} + propertyPath: PositionThreshold + value: 0.01 + objectReference: {fileID: 0} + - target: {fileID: 4600632750638426092, guid: ea906834639fa3f4ba65c95db6181d6b, + type: 3} + propertyPath: RotAngleThreshold + value: 0.1 + objectReference: {fileID: 0} m_RemovedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: ea906834639fa3f4ba65c95db6181d6b, type: 3} --- !u!850595691 &903034822 @@ -278,7 +308,7 @@ LightingSettings: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: - serializedVersion: 3 + serializedVersion: 4 m_GIWorkflowMode: 1 m_EnableBakedLightmaps: 1 m_EnableRealtimeLightmaps: 0 @@ -291,7 +321,7 @@ LightingSettings: m_LightmapMaxSize: 1024 m_BakeResolution: 40 m_Padding: 2 - m_TextureCompression: 1 + m_LightmapCompression: 3 m_AO: 0 m_AOMaxDistance: 1 m_CompAOExponent: 1 @@ -332,6 +362,7 @@ LightingSettings: m_PVRFilteringAtrousPositionSigmaDirect: 0.5 m_PVRFilteringAtrousPositionSigmaIndirect: 2 m_PVRFilteringAtrousPositionSigmaAO: 1 + m_PVRTiledBaking: 0 --- !u!1001 &1152084533 PrefabInstance: m_ObjectHideFlags: 0 @@ -404,6 +435,21 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} + - target: {fileID: 4600632750638426092, guid: ea906834639fa3f4ba65c95db6181d6b, + type: 3} + propertyPath: ScaleThreshold + value: 0.01 + objectReference: {fileID: 0} + - target: {fileID: 4600632750638426092, guid: ea906834639fa3f4ba65c95db6181d6b, + type: 3} + propertyPath: PositionThreshold + value: 0.01 + objectReference: {fileID: 0} + - target: {fileID: 4600632750638426092, guid: ea906834639fa3f4ba65c95db6181d6b, + type: 3} + propertyPath: RotAngleThreshold + value: 0.1 + objectReference: {fileID: 0} m_RemovedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: ea906834639fa3f4ba65c95db6181d6b, type: 3} --- !u!1001 &1247056486 @@ -478,5 +524,20 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} + - target: {fileID: 4600632750638426092, guid: ea906834639fa3f4ba65c95db6181d6b, + type: 3} + propertyPath: ScaleThreshold + value: 0.01 + objectReference: {fileID: 0} + - target: {fileID: 4600632750638426092, guid: ea906834639fa3f4ba65c95db6181d6b, + type: 3} + propertyPath: PositionThreshold + value: 0.01 + objectReference: {fileID: 0} + - target: {fileID: 4600632750638426092, guid: ea906834639fa3f4ba65c95db6181d6b, + type: 3} + propertyPath: RotAngleThreshold + value: 0.1 + objectReference: {fileID: 0} m_RemovedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: ea906834639fa3f4ba65c95db6181d6b, type: 3} diff --git a/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/ClientNetworkTransform.cs b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/ClientNetworkTransform.cs new file mode 100644 index 0000000000..f236eac9bf --- /dev/null +++ b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/ClientNetworkTransform.cs @@ -0,0 +1,12 @@ +using Unity.Netcode.Components; + +namespace TestProject.ManualTests +{ + public class ClientNetworkTransform : NetworkTransform + { + protected override bool OnIsServerAuthoritative() + { + return false; + } + } +} diff --git a/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/ClientNetworkTransform.cs.meta b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/ClientNetworkTransform.cs.meta new file mode 100644 index 0000000000..1c86c33058 --- /dev/null +++ b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/ClientNetworkTransform.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cf01cca54b77c0241ad6d9da5ef6a709 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/PlayerClientAuthoritative.prefab b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/PlayerClientAuthoritative.prefab new file mode 100644 index 0000000000..5fe8f7e1d0 --- /dev/null +++ b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/PlayerClientAuthoritative.prefab @@ -0,0 +1,297 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &4079352819444256614 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4079352819444256611} + - component: {fileID: 972770265172480408} + - component: {fileID: -3775814466963834669} + - component: {fileID: 4079352819444256610} + - component: {fileID: 4079352819444256613} + - component: {fileID: 4079352819444256612} + - component: {fileID: 1750810845806302260} + - component: {fileID: 4053684789567975459} + - component: {fileID: 6442518961346739709} + - component: {fileID: 2756533617708860847} + - component: {fileID: 9187250582412873179} + m_Layer: 8 + m_Name: PlayerClientAuthoritative + m_TagString: Player + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4079352819444256611 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4079352819444256614} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 5, y: 0.625, z: 5} + m_LocalScale: {x: 1.25, y: 1.25, z: 1.25} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 3519470446676406143} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &972770265172480408 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4079352819444256614} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: cf01cca54b77c0241ad6d9da5ef6a709, type: 3} + m_Name: + m_EditorClassIdentifier: + SyncPositionX: 1 + SyncPositionY: 1 + SyncPositionZ: 1 + SyncRotAngleX: 1 + SyncRotAngleY: 1 + SyncRotAngleZ: 1 + SyncScaleX: 1 + SyncScaleY: 1 + SyncScaleZ: 1 + PositionThreshold: 0.01 + RotAngleThreshold: 0.01 + ScaleThreshold: 0.01 + InLocalSpace: 0 + Interpolate: 1 +--- !u!114 &-3775814466963834669 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4079352819444256614} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 951099334 + AlwaysReplicateAsRoot: 0 + DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 +--- !u!33 &4079352819444256610 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4079352819444256614} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &4079352819444256613 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4079352819444256614} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: a7b755ad8e4fe4bdb8f5518c951abc70, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!65 &4079352819444256612 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4079352819444256614} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!54 &1750810845806302260 +Rigidbody: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4079352819444256614} + serializedVersion: 2 + m_Mass: 100 + m_Drag: 7 + m_AngularDrag: 0.05 + m_UseGravity: 1 + m_IsKinematic: 0 + m_Interpolate: 1 + m_Constraints: 112 + m_CollisionDetection: 1 +--- !u!114 &4053684789567975459 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4079352819444256614} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 24a9235f10bc6456183432fdb3015157, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &6442518961346739709 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4079352819444256614} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e3e4ecffca0894dfa88af779c2a67b9e, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &2756533617708860847 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4079352819444256614} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8e5aa2f75493a4fee8ec635d215f03c2, type: 3} + m_Name: + m_EditorClassIdentifier: + MoveSpeed: 10 +--- !u!114 &9187250582412873179 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4079352819444256614} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f6c0be61502bb534f922ebb746851216, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &6479012615216050269 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3519470446676406143} + - component: {fileID: 6858102498835906389} + - component: {fileID: 2780619303711114328} + m_Layer: 8 + m_Name: PlayerSub + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &3519470446676406143 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6479012615216050269} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1.045, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 4079352819444256611} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &6858102498835906389 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6479012615216050269} + m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &2780619303711114328 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6479012615216050269} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 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} diff --git a/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/PlayerClientAuthoritative.prefab.meta b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/PlayerClientAuthoritative.prefab.meta new file mode 100644 index 0000000000..3b1a7f37fd --- /dev/null +++ b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/PlayerClientAuthoritative.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3cc5d500f7b2e1245bfb8652adadb286 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/SceneTransitioningBase1.unity b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/SceneTransitioningBase1.unity index bf5d0be2c7..be71473fbe 100644 --- a/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/SceneTransitioningBase1.unity +++ b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/SceneTransitioningBase1.unity @@ -171,8 +171,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 475de064003ff104fb88b1fbccd0f417, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_ActivateOnLoad: 0 m_SceneToLoad: AdditiveSceneMultiInstance m_SceneAsset: {fileID: 102900000, guid: 0ae94f636016d3b40bfbecad57d99553, type: 3} @@ -224,12 +224,13 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 244f0414ea8419b41ac51adb305d64b0, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_SwitchSceneButtonObject: {fileID: 1347823141} m_SceneToSwitchTo: SceneTransitioningBase2 m_EnableAutoSwitch: 0 m_AutoSwitchTimeOut: 60 + DisconnectClientUponLoadScene: 0 --- !u!1 &37242881 GameObject: m_ObjectHideFlags: 0 @@ -379,8 +380,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -455,8 +456,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -632,8 +633,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 475de064003ff104fb88b1fbccd0f417, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_ActivateOnLoad: 0 m_SceneToLoad: AdditiveSceneMultiInstance m_SceneAsset: {fileID: 102900000, guid: 0ae94f636016d3b40bfbecad57d99553, type: 3} @@ -686,8 +687,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -762,8 +763,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -823,8 +824,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_IgnoreReversedGraphics: 1 m_BlockingObjects: 0 m_BlockingMask: @@ -840,8 +841,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_UiScaleMode: 0 m_ReferencePixelsPerUnit: 100 m_ScaleFactor: 1 @@ -924,8 +925,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_IgnoreReversedGraphics: 1 m_BlockingObjects: 0 m_BlockingMask: @@ -941,8 +942,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_UiScaleMode: 1 m_ReferencePixelsPerUnit: 100 m_ScaleFactor: 1 @@ -1055,8 +1056,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 475de064003ff104fb88b1fbccd0f417, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_ActivateOnLoad: 0 m_SceneToLoad: AdditiveScene2 m_SceneAsset: {fileID: 102900000, guid: c6a3d883c8253ee43bca4f2b03797d7b, type: 3} @@ -1109,8 +1110,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Navigation: m_Mode: 3 m_WrapAround: 0 @@ -1156,7 +1157,7 @@ MonoBehaviour: m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine m_IntArgument: 0 m_FloatArgument: 0 - m_StringArgument: + m_StringArgument: m_BoolArgument: 0 m_CallState: 2 m_IsOn: 0 @@ -1306,8 +1307,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Navigation: m_Mode: 3 m_WrapAround: 0 @@ -1353,7 +1354,7 @@ MonoBehaviour: m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine m_IntArgument: 0 m_FloatArgument: 0 - m_StringArgument: + m_StringArgument: m_BoolArgument: 0 m_CallState: 2 m_IsOn: 0 @@ -1406,8 +1407,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -1482,8 +1483,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -1558,8 +1559,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 0.9811321, g: 0.9811321, b: 0.9811321, a: 1} m_RaycastTarget: 1 @@ -1722,8 +1723,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 0.5058824, b: 0.003921569, a: 1} m_RaycastTarget: 1 @@ -1802,8 +1803,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -1878,8 +1879,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -1954,8 +1955,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -2030,8 +2031,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 475de064003ff104fb88b1fbccd0f417, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_ActivateOnLoad: 0 m_SceneToLoad: AdditiveScene1 m_SceneAsset: {fileID: 102900000, guid: 41a0239b0c49e2047b7063c822f0df8a, type: 3} @@ -2041,8 +2042,8 @@ LightingSettings: m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_Name: - serializedVersion: 3 + m_Name: + serializedVersion: 4 m_GIWorkflowMode: 1 m_EnableBakedLightmaps: 1 m_EnableRealtimeLightmaps: 0 @@ -2145,8 +2146,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -2299,8 +2300,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 475de064003ff104fb88b1fbccd0f417, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_ActivateOnLoad: 0 m_SceneToLoad: AdditiveSceneMultiInstance m_SceneAsset: {fileID: 102900000, guid: 0ae94f636016d3b40bfbecad57d99553, type: 3} @@ -2313,10 +2314,10 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 1024114720} - - component: {fileID: 1024114719} - component: {fileID: 1024114718} - component: {fileID: 1024114721} - component: {fileID: 1024114722} + - component: {fileID: 1024114723} m_Layer: 0 m_Name: NetworkManager m_TagString: Untagged @@ -2334,14 +2335,14 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 593a2fe42fa9d37498c96f9a383b6521, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: RunInBackground: 1 LogLevel: 1 NetworkConfig: ProtocolVersion: 0 - NetworkTransport: {fileID: 1024114719} - PlayerPrefab: {fileID: 4079352819444256614, guid: c16f03336b6104576a565ef79ad643c0, + NetworkTransport: {fileID: 1024114723} + PlayerPrefab: {fileID: 4079352819444256614, guid: 3cc5d500f7b2e1245bfb8652adadb286, type: 3} NetworkPrefabs: - Override: 0 @@ -2397,7 +2398,7 @@ MonoBehaviour: TickRate: 30 ClientConnectionBufferTimeout: 10 ConnectionApproval: 0 - ConnectionData: + ConnectionData: EnableTimeResync: 0 TimeResyncInterval: 30 EnsureNetworkVariableLengthSafety: 0 @@ -2409,25 +2410,6 @@ MonoBehaviour: LoadSceneTimeOut: 120 SpawnTimeout: 1 EnableNetworkLogs: 1 ---- !u!114 &1024114719 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1024114717} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: b84c2d8dfe509a34fb59e2b81f8e1319, type: 3} - m_Name: - m_EditorClassIdentifier: - MessageBufferSize: 65535 - MaxConnections: 100 - MaxSentMessageQueueSize: 512 - ConnectAddress: 127.0.0.1 - ConnectPort: 7777 - ServerListenPort: 7777 - MessageSendMode: 0 --- !u!4 &1024114720 Transform: m_ObjectHideFlags: 0 @@ -2453,8 +2435,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 0e6f8504d891fc44881b2d9703017d03, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: --- !u!114 &1024114722 MonoBehaviour: m_ObjectHideFlags: 0 @@ -2465,10 +2447,38 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 71c52a32bd1c1c84691050b6d045ab4a, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: LogToConsole: 1 TimeToLive: 10 +--- !u!114 &1024114723 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1024114717} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6960e84d07fb87f47956e7a81d71c4e6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ProtocolType: 0 + m_MaxPacketQueueSize: 128 + m_MaxPayloadSize: 512000 + m_MaxSendQueueSize: 4096000 + m_HeartbeatTimeoutMS: 500 + m_ConnectTimeoutMS: 1000 + m_MaxConnectAttempts: 60 + m_DisconnectTimeoutMS: 30000 + ConnectionData: + Address: 127.0.0.1 + Port: 7777 + ServerListenAddress: + DebugSimulator: + PacketDelayMS: 0 + PacketJitterMS: 0 + PacketDropRate: 0 --- !u!1 &1113539278 GameObject: m_ObjectHideFlags: 0 @@ -2497,8 +2507,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 8c48ea35c67e64f7fac22a3f6831ca88, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: AutoSpawnEnable: 1 InitialSpawnDelay: 0.2 SpawnsPerSecond: 1 @@ -2538,8 +2548,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: GlobalObjectIdHash: 1983031731 AlwaysReplicateAsRoot: 0 DontDestroyWithOwner: 0 @@ -2592,8 +2602,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 475de064003ff104fb88b1fbccd0f417, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_ActivateOnLoad: 0 m_SceneToLoad: AdditiveSceneMultiInstance m_SceneAsset: {fileID: 102900000, guid: 0ae94f636016d3b40bfbecad57d99553, type: 3} @@ -2645,8 +2655,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -2726,8 +2736,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -2935,8 +2945,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -3017,8 +3027,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Navigation: m_Mode: 3 m_WrapAround: 0 @@ -3060,7 +3070,7 @@ MonoBehaviour: m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine m_IntArgument: 0 m_FloatArgument: 0 - m_StringArgument: + m_StringArgument: m_BoolArgument: 0 m_CallState: 2 --- !u!114 &1347823144 @@ -3073,8 +3083,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 0.1981132, g: 0.1981132, b: 0.1981132, a: 1} m_RaycastTarget: 1 @@ -3150,8 +3160,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Navigation: m_Mode: 3 m_WrapAround: 0 @@ -3197,7 +3207,7 @@ MonoBehaviour: m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine m_IntArgument: 0 m_FloatArgument: 0 - m_StringArgument: + m_StringArgument: m_BoolArgument: 0 m_CallState: 2 m_IsOn: 0 @@ -3249,8 +3259,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 0.990566, g: 0.990566, b: 0.990566, a: 1} m_RaycastTarget: 1 @@ -3367,8 +3377,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -3443,8 +3453,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -3519,8 +3529,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -3595,8 +3605,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -3673,8 +3683,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Navigation: m_Mode: 3 m_WrapAround: 0 @@ -3716,7 +3726,7 @@ MonoBehaviour: m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine m_IntArgument: 0 m_FloatArgument: 0 - m_StringArgument: + m_StringArgument: m_BoolArgument: 0 m_CallState: 2 --- !u!114 &1588117330 @@ -3729,8 +3739,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 0.1981132, g: 0.1981132, b: 0.1981132, a: 1} m_RaycastTarget: 1 @@ -3805,8 +3815,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -3886,8 +3896,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Navigation: m_Mode: 3 m_WrapAround: 0 @@ -3933,7 +3943,7 @@ MonoBehaviour: m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine m_IntArgument: 0 m_FloatArgument: 0 - m_StringArgument: + m_StringArgument: m_BoolArgument: 0 m_CallState: 2 m_IsOn: 0 @@ -3986,8 +3996,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Navigation: m_Mode: 3 m_WrapAround: 0 @@ -4033,7 +4043,7 @@ MonoBehaviour: m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine m_IntArgument: 0 m_FloatArgument: 0 - m_StringArgument: + m_StringArgument: m_BoolArgument: 0 m_CallState: 2 m_IsOn: 0 @@ -4086,8 +4096,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -4162,8 +4172,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -4218,8 +4228,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_HorizontalAxis: Horizontal m_VerticalAxis: Vertical m_SubmitButton: Submit @@ -4237,8 +4247,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_FirstSelected: {fileID: 0} m_sendNavigationEvents: 1 m_DragThreshold: 10 @@ -4305,8 +4315,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 0.5058824, b: 0.003921569, a: 1} m_RaycastTarget: 1 @@ -4645,8 +4655,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Navigation: m_Mode: 3 m_WrapAround: 0 @@ -4692,7 +4702,7 @@ MonoBehaviour: m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine m_IntArgument: 0 m_FloatArgument: 0 - m_StringArgument: + m_StringArgument: m_BoolArgument: 0 m_CallState: 2 m_IsOn: 0 @@ -4744,8 +4754,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 @@ -4920,8 +4930,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 67db9e8f0e2ae9c40bc1e2b64352a6b4, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_Navigation: m_Mode: 3 m_WrapAround: 0 @@ -4970,7 +4980,7 @@ MonoBehaviour: m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine m_IntArgument: 0 m_FloatArgument: 0 - m_StringArgument: + m_StringArgument: m_BoolArgument: 0 m_CallState: 2 --- !u!1 &2107482020 @@ -5016,11 +5026,10 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: cb5f3e55f5dd247129d8a4979b80ebbb, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: m_ClientServerToggle: {fileID: 1588117327} m_TrackSceneEvents: 1 - m_LogSceneEventsToConsole: 1 --- !u!114 &2107482023 MonoBehaviour: m_ObjectHideFlags: 0 @@ -5031,8 +5040,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: GlobalObjectIdHash: 3197939627 AlwaysReplicateAsRoot: 0 DontDestroyWithOwner: 0 @@ -5162,7 +5171,7 @@ PrefabInstance: - target: {fileID: 2848221157716786269, guid: 3200770c16e3b2b4ebe7f604154faac7, type: 3} propertyPath: m_FontData.m_Font - value: + value: objectReference: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} - target: {fileID: 2848221157716786269, guid: 3200770c16e3b2b4ebe7f604154faac7, type: 3} @@ -5197,7 +5206,7 @@ PrefabInstance: - target: {fileID: 5266522511616468950, guid: 3200770c16e3b2b4ebe7f604154faac7, type: 3} propertyPath: m_SceneMenuToLoad - value: + value: objectReference: {fileID: 11400000, guid: c10d995498e0c514a853c3506031d3fb, type: 2} m_RemovedComponents: [] diff --git a/testproject/Assets/Tests/Manual/Scripts/PlayerMovementManager.cs b/testproject/Assets/Tests/Manual/Scripts/PlayerMovementManager.cs index 763ef5819e..b8c0ae786b 100644 --- a/testproject/Assets/Tests/Manual/Scripts/PlayerMovementManager.cs +++ b/testproject/Assets/Tests/Manual/Scripts/PlayerMovementManager.cs @@ -20,22 +20,20 @@ private void Start() private void Update() { - if (NetworkObject != null) + if (!IsSpawned) { - if (IsOwner && Input.GetKeyDown(KeyCode.Space)) + return; + } + + if (IsOwner) + { + if (Input.GetKeyDown(KeyCode.Space)) { - if (m_RandomMovement) - { - m_RandomMovement.enabled = !m_RandomMovement.enabled; - } + m_RandomMovement.enabled = !m_RandomMovement.enabled; } - - if (NetworkObject != null && NetworkObject.NetworkManager != null && NetworkObject.NetworkManager.IsListening) + if (m_RandomMovement.enabled) { - if (m_RandomMovement.enabled) - { - m_RandomMovement.Move(MoveSpeed); - } + m_RandomMovement.Move(MoveSpeed); } } } diff --git a/testproject/Assets/Tests/Manual/Scripts/RandomMovement.cs b/testproject/Assets/Tests/Manual/Scripts/RandomMovement.cs index 6aa161ceb0..846d64aa4c 100644 --- a/testproject/Assets/Tests/Manual/Scripts/RandomMovement.cs +++ b/testproject/Assets/Tests/Manual/Scripts/RandomMovement.cs @@ -1,5 +1,6 @@ using UnityEngine; using Unity.Netcode; +using Unity.Netcode.Components; namespace TestProject.ManualTests { @@ -12,13 +13,33 @@ public class RandomMovement : NetworkBehaviour, IPlayerMovement private Vector3 m_Direction; private Rigidbody m_Rigidbody; + private NetworkTransform m_NetworkTransform; + private ClientNetworkTransform m_ClientNetworkTransform; + + private bool HasAuthority() + { + if (m_NetworkTransform != null) + { + if (m_ClientNetworkTransform == null) + { + m_ClientNetworkTransform = m_NetworkTransform as ClientNetworkTransform; + } + if (m_ClientNetworkTransform != null) + { + return IsOwner; + } + } + + return IsServer; + } public override void OnNetworkSpawn() { m_Rigidbody = GetComponent(); + m_NetworkTransform = GetComponent(); if (NetworkObject != null && m_Rigidbody != null) { - if (NetworkObject.IsOwner) + if (m_NetworkTransform.NetworkObject.IsOwner) { ChangeDirection(true, true); } @@ -40,18 +61,18 @@ private void MovePlayerServerRpc(Vector3 moveTowards) public void Move(int speed) { // Server sets this locally - if (IsServer && IsOwner) + if (HasAuthority()) { m_MoveTowardsPosition = (m_Direction * speed); } - else if (!IsServer && IsOwner) + else if (m_ClientNetworkTransform == null && !IsServer && IsOwner) { // Client must sent Rpc MovePlayerServerRpc(m_Direction * speed * 1.05f); - } - else if (IsServer && !IsOwner) - { - m_MoveTowardsPosition = Vector3.Lerp(m_MoveTowardsPosition, Vector3.zero, 0.01f); + if (IsServer && !IsOwner) + { + m_MoveTowardsPosition = Vector3.Lerp(m_MoveTowardsPosition, Vector3.zero, 0.01f); + } } } @@ -59,7 +80,11 @@ public void Move(int speed) // We just apply our current direction with magnitude to our current position during fixed update private void FixedUpdate() { - if (IsServer && NetworkObject && NetworkObject.NetworkManager && NetworkObject.NetworkManager.IsListening) + if (!IsSpawned) + { + return; + } + if (HasAuthority()) { if (m_Rigidbody == null) { @@ -84,7 +109,7 @@ private void ChangeDirectionClientRpc(Vector3 direction) private void OnCollisionStay(Collision collision) { - if (IsServer) + if (HasAuthority()) { if (collision.gameObject.CompareTag("Floor") || collision.gameObject.CompareTag("GenericObject")) { @@ -98,7 +123,7 @@ private void OnCollisionStay(Collision collision) // If we are not the owner then we need to notify the client that their direction // must change - if (!IsOwner) + if (m_ClientNetworkTransform == null && IsServer && !IsOwner) { m_MoveTowardsPosition = m_Direction * m_MoveTowardsPosition.magnitude; ChangeDirectionClientRpc(m_Direction);