diff --git a/com.unity.netcode.gameobjects/Runtime/Components/NetworkRigidBodyBase.cs b/com.unity.netcode.gameobjects/Runtime/Components/NetworkRigidBodyBase.cs index 0d0de9afa8..4094e084a8 100644 --- a/com.unity.netcode.gameobjects/Runtime/Components/NetworkRigidBodyBase.cs +++ b/com.unity.netcode.gameobjects/Runtime/Components/NetworkRigidBodyBase.cs @@ -2,6 +2,7 @@ using System.Runtime.CompilerServices; using UnityEngine; + namespace Unity.Netcode.Components { /// @@ -571,7 +572,7 @@ private void InternalMoveRotation2D(Quaternion rotation) { var quaternion = Quaternion.identity; var angles = quaternion.eulerAngles; - angles.z = m_InternalRigidbody2D.rotation; + angles.z = rotation.z; quaternion.eulerAngles = angles; m_InternalRigidbody2D.MoveRotation(quaternion); } @@ -845,6 +846,28 @@ public void SetIsKinematic(bool isKinematic) PostSetIsKinematic(); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private bool HasInterpolationTypeSet(InterpolationTypes interpolationType) + { +#if COM_UNITY_MODULES_PHYSICS && COM_UNITY_MODULES_PHYSICS2D + if (m_IsRigidbody2D) + { + return interpolationType == InterpolationTypes.Extrapolate ? m_InternalRigidbody2D.interpolation == RigidbodyInterpolation2D.Extrapolate : m_InternalRigidbody2D.interpolation == RigidbodyInterpolation2D.Interpolate; + } + else + { + return interpolationType == InterpolationTypes.Extrapolate ? m_InternalRigidbody.interpolation == RigidbodyInterpolation.Extrapolate : m_InternalRigidbody.interpolation == RigidbodyInterpolation.Interpolate; + } +#endif +#if COM_UNITY_MODULES_PHYSICS && !COM_UNITY_MODULES_PHYSICS2D + return interpolationType == InterpolationTypes.Extrapolate ? m_InternalRigidbody2D.interpolation == RigidbodyInterpolation2D.Extrapolate : m_InternalRigidbody2D.interpolation == RigidbodyInterpolation2D.Interpolate; +#endif +#if !COM_UNITY_MODULES_PHYSICS && COM_UNITY_MODULES_PHYSICS2D + return interpolationType == InterpolationTypes.Extrapolate ? m_InternalRigidbody.interpolation == RigidbodyInterpolation.Extrapolate : m_InternalRigidbody.interpolation == RigidbodyInterpolation.Interpolate; +#endif + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private void PostSetIsKinematic() { @@ -853,26 +876,29 @@ private void PostSetIsKinematic() { return; } + if (UseRigidBodyForMotion) { - // Only if the NetworkTransform is set to interpolate do we need to check for extrapolation - if (NetworkTransform.Interpolate && m_OriginalInterpolation == InterpolationTypes.Extrapolate) + // Exit early if the original interpolation type is not set to extrapolate or NetworkTransform interpolate is disabled + if (m_OriginalInterpolation != InterpolationTypes.Extrapolate || !NetworkTransform.Interpolate) { - if (IsKinematic()) - { - // If not already set to interpolate then set the Rigidbody to interpolate - if (m_InternalRigidbody.interpolation == RigidbodyInterpolation.Extrapolate) - { - // Sleep until the next fixed update when switching from extrapolation to interpolation - SleepRigidbody(); - SetInterpolation(InterpolationTypes.Interpolate); - } - } - else - { - // Switch it back to the original interpolation if non-kinematic (doesn't require sleep). - SetInterpolation(m_OriginalInterpolation); - } + return; + } + + // Otherwise, if this is the active physics object + if (!IsKinematic()) + { + // switch it back to the original interpolation and exit early + SetInterpolation(m_OriginalInterpolation); + return; + } + + // If the Rigidbody or Rigidbody2D is currently configured to extrapolate + if (HasInterpolationTypeSet(InterpolationTypes.Extrapolate)) + { + // sleep until the next fixed update when switching from extrapolation to interpolation + SleepRigidbody(); + SetInterpolation(InterpolationTypes.Interpolate); } } else diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Physics/NetworkRigidbody2DTest.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Physics/NetworkRigidbody2DTest.cs deleted file mode 100644 index 089eeee542..0000000000 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Physics/NetworkRigidbody2DTest.cs +++ /dev/null @@ -1,80 +0,0 @@ -#if COM_UNITY_MODULES_PHYSICS2D -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.Components; -using UnityEngine; -using UnityEngine.TestTools; -using Unity.Netcode.TestHelpers.Runtime; - -namespace Unity.Netcode.RuntimeTests -{ - internal class NetworkRigidbody2DDynamicTest : NetworkRigidbody2DTestBase - { - public override bool Kinematic => false; - } - - internal class NetworkRigidbody2DKinematicTest : NetworkRigidbody2DTestBase - { - public override bool Kinematic => true; - } - - public abstract class NetworkRigidbody2DTestBase : NetcodeIntegrationTest - { - protected override int NumberOfClients => 1; - - public abstract bool Kinematic { get; } - - protected override void OnCreatePlayerPrefab() - { - m_PlayerPrefab.AddComponent(); - m_PlayerPrefab.AddComponent(); - m_PlayerPrefab.AddComponent(); - m_PlayerPrefab.GetComponent().interpolation = RigidbodyInterpolation2D.Interpolate; - m_PlayerPrefab.GetComponent().isKinematic = Kinematic; - } - - /// - /// Tests that a server can destroy a NetworkObject and that it gets despawned correctly. - /// - /// - [UnityTest] - public IEnumerator TestRigidbodyKinematicEnableDisable() - { - // This is the *SERVER VERSION* of the *CLIENT PLAYER* - var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); - yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ServerNetworkManager, serverClientPlayerResult); - var serverPlayer = serverClientPlayerResult.Result.gameObject; - - // This is the *CLIENT VERSION* of the *CLIENT PLAYER* - var clientClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); - yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ClientNetworkManagers[0], clientClientPlayerResult); - var clientPlayer = clientClientPlayerResult.Result.gameObject; - - Assert.IsNotNull(serverPlayer); - Assert.IsNotNull(clientPlayer); - - yield return WaitForTicks(m_ServerNetworkManager, 5); - - // server rigidbody has authority and should have a kinematic mode of false - Assert.True(serverPlayer.GetComponent().isKinematic == Kinematic); - Assert.AreEqual(RigidbodyInterpolation2D.Interpolate, serverPlayer.GetComponent().interpolation); - - // client rigidbody has no authority and should have a kinematic mode of true - Assert.True(clientPlayer.GetComponent().isKinematic); - Assert.AreEqual(RigidbodyInterpolation2D.None, clientPlayer.GetComponent().interpolation); - - // despawn the server player, (but keep it around on the server) - serverPlayer.GetComponent().Despawn(false); - - yield return WaitForTicks(m_ServerNetworkManager, 5); - - // This should equal Kinematic - Assert.IsTrue(serverPlayer.GetComponent().isKinematic == Kinematic); - - yield return WaitForTicks(m_ServerNetworkManager, 5); - - Assert.IsTrue(clientPlayer == null); // safety check that object is actually despawned. - } - } -} -#endif // COM_UNITY_MODULES_PHYSICS2D diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Physics/NetworkRigidbody2DTest.cs.meta b/com.unity.netcode.gameobjects/Tests/Runtime/Physics/NetworkRigidbody2DTest.cs.meta deleted file mode 100644 index 48faa513f7..0000000000 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Physics/NetworkRigidbody2DTest.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f33b2f298cbb7b248b2a76ba48ee1d53 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Physics/NetworkRigidbodyTest.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Physics/NetworkRigidbodyTest.cs index 4509797369..1a7d768831 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Physics/NetworkRigidbodyTest.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Physics/NetworkRigidbodyTest.cs @@ -1,7 +1,6 @@ #if COM_UNITY_MODULES_PHYSICS || COM_UNITY_MODULES_PHYSICS2D using System.Collections; using System.Collections.Generic; -using System.Text; using NUnit.Framework; using Unity.Netcode.Components; using Unity.Netcode.TestHelpers.Runtime; @@ -10,487 +9,227 @@ namespace Unity.Netcode.RuntimeTests { - [TestFixture(RigidbodyInterpolation.Interpolate, true, true)] // This should be allowed under all condistions when using Rigidbody motion - [TestFixture(RigidbodyInterpolation.Extrapolate, true, true)] // This should not allow extrapolation on non-auth instances when using Rigidbody motion & NT interpolation - [TestFixture(RigidbodyInterpolation.Extrapolate, false, true)] // This should allow extrapolation on non-auth instances when using Rigidbody & NT has no interpolation - [TestFixture(RigidbodyInterpolation.Interpolate, true, false)] // This should not allow kinematic instances to have Rigidbody interpolation enabled - [TestFixture(RigidbodyInterpolation.Interpolate, false, false)] // Testing that rigid body interpolation remains the same if NT interpolate is disabled + [TestFixture(HostOrServer.Server)] + [TestFixture(HostOrServer.Host)] + [TestFixture(HostOrServer.DAHost)] internal class NetworkRigidbodyTest : NetcodeIntegrationTest { protected override int NumberOfClients => 1; - private bool m_NetworkTransformInterpolate; - private bool m_UseRigidBodyForMotion; - private RigidbodyInterpolation m_RigidbodyInterpolation; - public NetworkRigidbodyTest(RigidbodyInterpolation rigidbodyInterpolation, bool networkTransformInterpolate, bool useRigidbodyForMotion) - { - m_RigidbodyInterpolation = rigidbodyInterpolation; - m_NetworkTransformInterpolate = networkTransformInterpolate; - m_UseRigidBodyForMotion = useRigidbodyForMotion; - } - - protected override void OnCreatePlayerPrefab() - { - var networkTransform = m_PlayerPrefab.AddComponent(); - networkTransform.Interpolate = m_NetworkTransformInterpolate; - var rigidbody = m_PlayerPrefab.AddComponent(); - rigidbody.interpolation = m_RigidbodyInterpolation; - var networkRigidbody = m_PlayerPrefab.AddComponent(); - networkRigidbody.UseRigidBodyForMotion = m_UseRigidBodyForMotion; - } - - /// - /// Tests that a server can destroy a NetworkObject and that it gets despawned correctly. - /// - /// - [UnityTest] - public IEnumerator TestRigidbodyKinematicEnableDisable() - { - // This is the *SERVER VERSION* of the *CLIENT PLAYER* - var serverClientPlayerInstance = m_ServerNetworkManager.ConnectedClients[m_ClientNetworkManagers[0].LocalClientId].PlayerObject; - - // This is the *CLIENT VERSION* of the *CLIENT PLAYER* - var clientPlayerInstance = m_ClientNetworkManagers[0].LocalClient.PlayerObject; - - Assert.IsNotNull(serverClientPlayerInstance, $"{nameof(serverClientPlayerInstance)} is null!"); - Assert.IsNotNull(clientPlayerInstance, $"{nameof(clientPlayerInstance)} is null!"); - - var serverClientInstanceRigidBody = serverClientPlayerInstance.GetComponent(); - var clientRigidBody = clientPlayerInstance.GetComponent(); - - if (m_UseRigidBodyForMotion) - { - var interpolateCompareNonAuthoritative = m_NetworkTransformInterpolate ? RigidbodyInterpolation.Interpolate : m_RigidbodyInterpolation; - - // Server authoritative NT should yield non-kinematic mode for the server-side player instance - Assert.False(serverClientInstanceRigidBody.isKinematic, $"[Server-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} player's {nameof(Rigidbody)} is kinematic!"); - - // The authoritative instance can be None, Interpolate, or Extrapolate for the Rigidbody interpolation settings. - Assert.AreEqual(m_RigidbodyInterpolation, serverClientInstanceRigidBody.interpolation, $"[Server-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} " + - $"player's {nameof(Rigidbody)}'s interpolation is {serverClientInstanceRigidBody.interpolation} and not {m_RigidbodyInterpolation}!"); - - // Server authoritative NT should yield kinematic mode for the client-side player instance - Assert.True(clientRigidBody.isKinematic, $"[Client-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} player's {nameof(Rigidbody)} is not kinematic!"); - - // When using Rigidbody motion, authoritative and non-authoritative Rigidbody interpolation settings should be preserved (except when extrapolation is used - Assert.AreEqual(interpolateCompareNonAuthoritative, clientRigidBody.interpolation, $"[Client-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} " + - $"player's {nameof(Rigidbody)}'s interpolation is {clientRigidBody.interpolation} and not {interpolateCompareNonAuthoritative}!"); - } - else + private List<(RigidbodyInterpolation interpolationType, bool enableInterpolation, bool useRigidbodyForMotion)> m_TestConfigurations = + new List<(RigidbodyInterpolation interpolationType, bool enableInterpolation, bool useRigidbodyForMotion)>() { - // server rigidbody has authority and should not be kinematic - Assert.False(serverClientInstanceRigidBody.isKinematic, $"[Server-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} player's {nameof(Rigidbody)} is kinematic!"); - Assert.AreEqual(RigidbodyInterpolation.Interpolate, serverClientInstanceRigidBody.interpolation, $"[Server-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} " + - $"player's {nameof(Rigidbody)}'s interpolation is {serverClientInstanceRigidBody.interpolation} and not {nameof(RigidbodyInterpolation.Interpolate)}!"); - - // Server authoritative NT should yield kinematic mode for the client-side player instance - Assert.True(clientRigidBody.isKinematic, $"[Client-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} player's {nameof(Rigidbody)} is not kinematic!"); - - // client rigidbody has no authority with NT interpolation disabled should allow Rigidbody interpolation - if (!m_NetworkTransformInterpolate) - { - Assert.AreEqual(RigidbodyInterpolation.Interpolate, clientRigidBody.interpolation, $"[Client-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} " + - $"player's {nameof(Rigidbody)}'s interpolation is {clientRigidBody.interpolation} and not {nameof(RigidbodyInterpolation.Interpolate)}!"); - } - else - { - Assert.AreEqual(RigidbodyInterpolation.None, clientRigidBody.interpolation, $"[Client-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} " + - $"player's {nameof(Rigidbody)}'s interpolation is {clientRigidBody.interpolation} and not {nameof(RigidbodyInterpolation.None)}!"); - } - } - - // despawn the server player (but keep it around on the server) - serverClientPlayerInstance.Despawn(false); - - yield return WaitForConditionOrTimeOut(() => !serverClientPlayerInstance.IsSpawned && !clientPlayerInstance.IsSpawned); - AssertOnTimeout("Timed out waiting for client player to despawn on both server and client!"); - - // When despawned, we should always be kinematic (i.e. don't apply physics when despawned) - Assert.True(serverClientInstanceRigidBody.isKinematic, $"[Server-Side][Despawned] Client-{m_ClientNetworkManagers[0].LocalClientId} player's {nameof(Rigidbody)} is not kinematic when despawned!"); - Assert.IsTrue(clientPlayerInstance == null, $"[Client-Side] Player {nameof(NetworkObject)} is not null!"); - } - } - - internal class ContactEventTransformHelperWithInfo : ContactEventTransformHelper, IContactEventHandlerWithInfo - { - public ContactEventHandlerInfo GetContactEventHandlerInfo() - { - var contactEventHandlerInfo = new ContactEventHandlerInfo() - { - HasContactEventPriority = IsOwner, - ProvideNonRigidBodyContactEvents = m_EnableNonRigidbodyContacts.Value, + (RigidbodyInterpolation.Interpolate, true, true), // This should be allowed under all condistions when using Rigidbody motion + (RigidbodyInterpolation.Extrapolate, true, true), // This should not allow extrapolation on non-auth instances when using Rigidbody motion & NT interpolation + (RigidbodyInterpolation.Extrapolate, false, true), // This should allow extrapolation on non-auth instances when using Rigidbody & NT has no interpolation + (RigidbodyInterpolation.Interpolate, true, false), // This should not allow kinematic instances to have Rigidbody interpolation enabled + (RigidbodyInterpolation.Interpolate, false, false) // Testing that rigidbody interpolation remains the same if NT interpolate is disabled }; - return contactEventHandlerInfo; - } - - protected override void OnRegisterForContactEvents(bool isRegistering) - { - RigidbodyContactEventManager.Instance.RegisterHandler(this, isRegistering); - } - } + /// + /// The current test configuration applied to the current test running. + /// + private (RigidbodyInterpolation interpolationType, bool enableInterpolation, bool useRigidbodyForMotion) m_CurrentConfiguration; - internal class ContactEventTransformHelper : NetworkTransform, IContactEventHandler - { - public static Vector3 SessionOwnerSpawnPoint; - public static Vector3 ClientSpawnPoint; - public static bool VerboseDebug; - public enum HelperStates + public NetworkRigidbodyTest(HostOrServer hostOrServer) : base(hostOrServer) { - None, - MoveForward, } - private HelperStates m_HelperState; - - public void SetHelperState(HelperStates state) - { - m_HelperState = state; - if (!m_NetworkRigidbody.IsKinematic()) - { - m_NetworkRigidbody.Rigidbody.angularVelocity = Vector3.zero; - m_NetworkRigidbody.Rigidbody.linearVelocity = Vector3.zero; - } - m_NetworkRigidbody.Rigidbody.isKinematic = m_HelperState == HelperStates.None; - if (!m_NetworkRigidbody.IsKinematic()) - { - m_NetworkRigidbody.Rigidbody.angularVelocity = Vector3.zero; - m_NetworkRigidbody.Rigidbody.linearVelocity = Vector3.zero; - } + /// + /// Base prefab for and + /// + private GameObject m_RigidbodyPrefab; + private NetworkTransform m_3DNetworkTransform; + private Rigidbody m_PrefabRigidbody; + private NetworkRigidbody m_PrefabNetworkRigidbody; + private NetworkObject m_3DAuthorityInstance; - } + /// + /// Base prefab for and + /// + private GameObject m_Rigidbody2DPrefab; + private NetworkTransform m_2DNetworkTransform; + private Rigidbody2D m_PrefabRigidbody2D; + private NetworkRigidbody2D m_PrefabNetworkRigidbody2D; + private NetworkObject m_2DAuthorityInstance; - protected struct ContactEventInfo + protected override void OnServerAndClientsCreated() { - public ulong EventId; - public Vector3 AveragedCollisionNormal; - public Rigidbody CollidingBody; - public Vector3 ContactPoint; - } + m_RigidbodyPrefab = CreateNetworkObjectPrefab("RBTest"); + m_3DNetworkTransform = m_RigidbodyPrefab.AddComponent(); + m_PrefabRigidbody = m_RigidbodyPrefab.AddComponent(); + m_PrefabNetworkRigidbody = m_RigidbodyPrefab.AddComponent(); - protected List m_ContactEvents = new List(); + m_Rigidbody2DPrefab = CreateNetworkObjectPrefab("RB2DTest"); + m_2DNetworkTransform = m_Rigidbody2DPrefab.AddComponent(); + m_PrefabRigidbody2D = m_Rigidbody2DPrefab.AddComponent(); + m_PrefabNetworkRigidbody2D = m_Rigidbody2DPrefab.AddComponent(); - protected NetworkVariable m_EnableNonRigidbodyContacts = new NetworkVariable(false, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - - protected NetworkRigidbody m_NetworkRigidbody; - public ContactEventTransformHelper Target; - - public bool HasContactEvents() - { - return m_ContactEvents.Count > 0; + base.OnServerAndClientsCreated(); } - public Rigidbody GetRigidbody() + private string m_ConfigHeader; + private void ApplyCurrentTestConfiguration() { - return m_NetworkRigidbody.Rigidbody; - } - - public bool HadContactWith(ContactEventTransformHelper otherObject) - { - if (otherObject == null) - { - return false; - } - foreach (var contactEvent in m_ContactEvents) - { - if (contactEvent.CollidingBody == otherObject.m_NetworkRigidbody.Rigidbody) - { - return true; - } - } - return false; - } + // Configure both 3D and 2D versions based on the current test configuration + m_3DNetworkTransform.Interpolate = m_CurrentConfiguration.enableInterpolation; + m_PrefabRigidbody.interpolation = m_CurrentConfiguration.interpolationType; + m_PrefabNetworkRigidbody.UseRigidBodyForMotion = m_CurrentConfiguration.useRigidbodyForMotion; + m_2DNetworkTransform.Interpolate = m_CurrentConfiguration.enableInterpolation; + m_PrefabRigidbody2D.interpolation = m_CurrentConfiguration.interpolationType == RigidbodyInterpolation.Interpolate ? RigidbodyInterpolation2D.Interpolate : RigidbodyInterpolation2D.Extrapolate; + m_PrefabNetworkRigidbody2D.UseRigidBodyForMotion = m_CurrentConfiguration.useRigidbodyForMotion; - protected virtual void CheckToStopMoving() - { - SetHelperState(HadContactWith(Target) ? HelperStates.None : HelperStates.MoveForward); + // Build a header used in assert messages + m_ConfigHeader = $"[{m_CurrentConfiguration.interpolationType}][Interpolate: {m_CurrentConfiguration.enableInterpolation}][RB-Motion: {m_CurrentConfiguration.useRigidbodyForMotion}]"; } - public void ContactEvent(ulong eventId, Vector3 averagedCollisionNormal, Rigidbody collidingBody, Vector3 contactPoint, bool hasCollisionStay = false, Vector3 averagedCollisionStayNormal = default) + /// + /// Iterates through the to validate various + /// Rigidbody interpolation settings and kinematic states for authority and non-authority + /// instances. + /// + [UnityTest] + public IEnumerator TestRigidbodyKinematicEnableDisable() { - if (Target == null) + foreach (var configuration in m_TestConfigurations) { - return; - } + m_CurrentConfiguration = configuration; + ApplyCurrentTestConfiguration(); - if (collidingBody != null) - { - Log($">>>>>>> contact event with {collidingBody.name}!"); - } - else - { - Log($">>>>>>> contact event with non-rigidbody!"); - } + // Host, Server, DAHost/Session-owner are spawn authority + yield return RunTestConfiguration(); - m_ContactEvents.Add(new ContactEventInfo() - { - EventId = eventId, - AveragedCollisionNormal = averagedCollisionNormal, - CollidingBody = collidingBody, - ContactPoint = contactPoint, - }); - CheckToStopMoving(); - } - - private void SetInitialPositionClientServer() - { - if (IsServer) - { - if (!NetworkManager.DistributedAuthorityMode && !IsLocalPlayer) - { - transform.position = ClientSpawnPoint; - m_NetworkRigidbody.Rigidbody.position = ClientSpawnPoint; - } - else + // When using distributed authority, swap the session owner with + // the non-session owner client as being the spawn authority. + if (m_DistributedAuthority) { - transform.position = SessionOwnerSpawnPoint; - m_NetworkRigidbody.Rigidbody.position = SessionOwnerSpawnPoint; + yield return RunTestConfiguration(true); } } - else - { - transform.position = ClientSpawnPoint; - m_NetworkRigidbody.Rigidbody.position = ClientSpawnPoint; - } } - private void SetInitialPositionDistributedAuthority() - { - if (HasAuthority) + /// + /// Validates the current applied test configuration. + /// + private IEnumerator RunTestConfiguration(bool swapAuthority = false) + { + // The authority is the "spawn authority". + // Distributed authority runs this a second time with a non-session owner client being the + // spawn authority to validate that scenario works correctly. + var authority = !swapAuthority ? GetAuthorityNetworkManager() : GetNonAuthorityNetworkManager(); + var nonAuthority = !swapAuthority ? GetNonAuthorityNetworkManager() : GetAuthorityNetworkManager(); + + // Spawn instances of both the 3D and 2D prefabs configured for the current test. + m_3DAuthorityInstance = SpawnObject(m_RigidbodyPrefab, authority).GetComponent(); + yield return WaitForSpawnedOnAllOrTimeOut(m_3DAuthorityInstance); + AssertOnTimeout($"Failed to spawn {m_3DAuthorityInstance.name} on all clients!"); + + m_2DAuthorityInstance = SpawnObject(m_Rigidbody2DPrefab, authority).GetComponent(); + yield return WaitForSpawnedOnAllOrTimeOut(m_2DAuthorityInstance); + AssertOnTimeout($"Failed to spawn {m_2DAuthorityInstance.name} on all clients!"); + + // Test 3D Rigidbody + #region 3D Rigidbody validation + var authorityRigidbody = m_3DAuthorityInstance.GetComponent(); + var nonAuthorityInstance = nonAuthority.SpawnManager.SpawnedObjects[m_3DAuthorityInstance.NetworkObjectId]; + var nonAuthorityRigidbody = nonAuthorityInstance.GetComponent(); + var authorityHeader = $"{m_ConfigHeader}[Authority] Client-{authority.LocalClientId}'s instance of {m_3DAuthorityInstance.name}"; + // The authority instance should always be non-kinematic + Assert.False(authorityRigidbody.isKinematic, $"{authorityHeader} is kinematic!"); + + var nonAuthorityHeader = $"{m_ConfigHeader}[Non-Authority] Client-{nonAuthority.LocalClientId}'s instance of {nonAuthorityInstance.name}"; + // Non-authority instances should always be kinematic + Assert.True(nonAuthorityRigidbody.isKinematic, $"{nonAuthorityHeader} is not kinematic!"); + var interpolateCompareNonAuthoritative = RigidbodyInterpolation.None; + + if (m_CurrentConfiguration.useRigidbodyForMotion) { - if (IsSessionOwner) - { - transform.position = SessionOwnerSpawnPoint; - m_NetworkRigidbody.Rigidbody.position = SessionOwnerSpawnPoint; - } - else - { - transform.position = ClientSpawnPoint; - m_NetworkRigidbody.Rigidbody.position = ClientSpawnPoint; - } - } - } - - public override void OnNetworkSpawn() - { - m_NetworkRigidbody = GetComponent(); + // The authoritative instance can be None, Interpolate, or Extrapolate for the Rigidbody interpolation settings. + Assert.AreEqual(m_CurrentConfiguration.interpolationType, authorityRigidbody.interpolation, $"{authorityHeader} interpolation is {authorityRigidbody.interpolation} " + + $"and not {m_CurrentConfiguration.interpolationType}!"); - m_NetworkRigidbody.Rigidbody.maxLinearVelocity = 15; - m_NetworkRigidbody.Rigidbody.maxAngularVelocity = 10; + // When using Rigidbody motion, authoritative and non-authoritative Rigidbody interpolation settings should be preserved (except when extrapolation is used + interpolateCompareNonAuthoritative = m_CurrentConfiguration.enableInterpolation ? RigidbodyInterpolation.Interpolate : m_CurrentConfiguration.interpolationType; - if (NetworkManager.DistributedAuthorityMode) - { - SetInitialPositionDistributedAuthority(); } else { - SetInitialPositionClientServer(); - } - if (IsLocalPlayer) - { - RegisterForContactEvents(true); - } - else - { - m_NetworkRigidbody.Rigidbody.detectCollisions = false; - } - base.OnNetworkSpawn(); - } - - protected virtual void OnRegisterForContactEvents(bool isRegistering) - { - RigidbodyContactEventManager.Instance.RegisterHandler(this, isRegistering); - } - - public void RegisterForContactEvents(bool isRegistering) - { - OnRegisterForContactEvents(isRegistering); - } - - private void FixedUpdate() - { - if (!IsSpawned || !IsOwner || m_HelperState != HelperStates.MoveForward) - { - return; - } - var distance = Vector3.Distance(Target.transform.position, transform.position); - var moveAmount = Mathf.Max(1.2f, distance); - // Head towards our target - var dir = (Target.transform.position - transform.position).normalized; - var deltaMove = dir * moveAmount * Time.fixedDeltaTime; - m_NetworkRigidbody.Rigidbody.MovePosition(m_NetworkRigidbody.Rigidbody.position + deltaMove); - + Assert.AreEqual(RigidbodyInterpolation.Interpolate, authorityRigidbody.interpolation, $"{authorityHeader} interpolation is {authorityRigidbody.interpolation} " + + $"and not {RigidbodyInterpolation.Interpolate}!"); - Log($" Loc: {transform.position} | Dest: {Target.transform.position} | Dist: {distance} | MoveDelta: {deltaMove}"); - } - - protected void Log(string msg) - { - if (VerboseDebug) - { - Debug.Log($"Client-{OwnerClientId} {msg}"); + // client rigidbody has no authority with NT interpolation disabled should allow Rigidbody interpolation + interpolateCompareNonAuthoritative = m_CurrentConfiguration.enableInterpolation ? RigidbodyInterpolation.None : RigidbodyInterpolation.Interpolate; } - } - } - - [TestFixture(HostOrServer.Host, ContactEventTypes.Default)] - [TestFixture(HostOrServer.DAHost, ContactEventTypes.Default)] - [TestFixture(HostOrServer.Host, ContactEventTypes.WithInfo)] - [TestFixture(HostOrServer.DAHost, ContactEventTypes.WithInfo)] - internal class RigidbodyContactEventManagerTests : IntegrationTestWithApproximation - { - protected override int NumberOfClients => 1; - - private GameObject m_RigidbodyContactEventManager; - public enum ContactEventTypes - { - Default, - WithInfo - } + Assert.AreEqual(interpolateCompareNonAuthoritative, nonAuthorityRigidbody.interpolation, $"{nonAuthorityHeader} interpolation is {nonAuthorityRigidbody.interpolation} " + + $"and not {interpolateCompareNonAuthoritative}!"); + #endregion - private ContactEventTypes m_ContactEventType; - private StringBuilder m_ErrorLogger = new StringBuilder(); + // Test 2D Rigidbody + #region 2D Rigidbody validation + var authorityRigidbody2D = m_2DAuthorityInstance.GetComponent(); + var nonAuthorityInstance2D = nonAuthority.SpawnManager.SpawnedObjects[m_2DAuthorityInstance.NetworkObjectId]; + var nonAuthorityRigidbody2D = nonAuthorityInstance2D.GetComponent(); - public RigidbodyContactEventManagerTests(HostOrServer hostOrServer, ContactEventTypes contactEventType) : base(hostOrServer) - { - m_ContactEventType = contactEventType; - } + authorityHeader = $"{m_ConfigHeader}[Authority] Client-{authority.LocalClientId}'s instance of {m_2DAuthorityInstance.name}"; + // The authority instance should always be non-kinematic + Assert.False(authorityRigidbody2D.bodyType == RigidbodyType2D.Kinematic, $"{authorityHeader} is kinematic!"); - protected override void OnCreatePlayerPrefab() - { - ContactEventTransformHelper.SessionOwnerSpawnPoint = GetRandomVector3(-4, -3); - ContactEventTransformHelper.ClientSpawnPoint = GetRandomVector3(3, 4); - if (m_ContactEventType == ContactEventTypes.Default) + nonAuthorityHeader = $"{m_ConfigHeader}[Non-Authority] Client-{nonAuthority.LocalClientId}'s instance of {nonAuthorityInstance.name}"; + // Non-authority instances should always be kinematic + Assert.True(nonAuthorityRigidbody2D.bodyType == RigidbodyType2D.Kinematic, $"{nonAuthorityHeader} is not kinematic!"); + var interpolateCompareNonAuthoritative2D = RigidbodyInterpolation2D.None; + var configInterpolation2D = m_CurrentConfiguration.interpolationType == RigidbodyInterpolation.Interpolate ? RigidbodyInterpolation2D.Interpolate : RigidbodyInterpolation2D.Extrapolate; + if (m_CurrentConfiguration.useRigidbodyForMotion) { - var helper = m_PlayerPrefab.AddComponent(); - helper.AuthorityMode = NetworkTransform.AuthorityModes.Owner; + // The authoritative instance can be None, Interpolate, or Extrapolate for the Rigidbody interpolation settings. + Assert.AreEqual(configInterpolation2D, authorityRigidbody2D.interpolation, $"{authorityHeader} interpolation is {authorityRigidbody2D.interpolation} " + + $"and not {m_CurrentConfiguration.interpolationType}!"); + + // When using Rigidbody motion, authoritative and non-authoritative Rigidbody interpolation settings should be preserved (except when extrapolation is used + interpolateCompareNonAuthoritative2D = m_CurrentConfiguration.enableInterpolation ? RigidbodyInterpolation2D.Interpolate : configInterpolation2D; } else { - var helperWithInfo = m_PlayerPrefab.AddComponent(); - helperWithInfo.AuthorityMode = NetworkTransform.AuthorityModes.Owner; - } - - var rigidbody = m_PlayerPrefab.AddComponent(); - rigidbody.useGravity = false; - rigidbody.isKinematic = true; - rigidbody.mass = 5.0f; - rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous; - var sphereCollider = m_PlayerPrefab.AddComponent(); - sphereCollider.radius = 0.5f; - sphereCollider.providesContacts = true; - - var networkRigidbody = m_PlayerPrefab.AddComponent(); - networkRigidbody.UseRigidBodyForMotion = true; - networkRigidbody.AutoUpdateKinematicState = false; - - m_RigidbodyContactEventManager = new GameObject(); - m_RigidbodyContactEventManager.AddComponent(); - } - + Assert.AreEqual(RigidbodyInterpolation2D.Interpolate, authorityRigidbody2D.interpolation, $"{authorityHeader} interpolation is {authorityRigidbody2D.interpolation} " + + $"and not {RigidbodyInterpolation2D.Interpolate}!"); - - private bool PlayersSpawnedInRightLocation() - { - var authority = GetAuthorityNetworkManager(); - var nonAuthority = GetNonAuthorityNetworkManager(); - - var position = authority.LocalClient.PlayerObject.transform.position; - if (!Approximately(ContactEventTransformHelper.SessionOwnerSpawnPoint, position)) - { - m_ErrorLogger.AppendLine($"Client-{authority.LocalClientId} player position {position} does not match the assigned player position {ContactEventTransformHelper.SessionOwnerSpawnPoint}!"); - return false; - } - - position = nonAuthority.LocalClient.PlayerObject.transform.position; - if (!Approximately(ContactEventTransformHelper.ClientSpawnPoint, position)) - { - m_ErrorLogger.AppendLine($"Client-{nonAuthority.LocalClientId} player position {position} does not match the assigned player position {ContactEventTransformHelper.ClientSpawnPoint}!"); - return false; - } - var playerObject = (NetworkObject)null; - if (!authority.SpawnManager.SpawnedObjects.ContainsKey(nonAuthority.LocalClient.PlayerObject.NetworkObjectId)) - { - m_ErrorLogger.AppendLine($"Client-{authority.LocalClientId} cannot find a local spawned instance of Client-{nonAuthority.LocalClientId}'s player object!"); - return false; + // client rigidbody has no authority with NT interpolation disabled should allow Rigidbody interpolation + interpolateCompareNonAuthoritative2D = m_CurrentConfiguration.enableInterpolation ? RigidbodyInterpolation2D.None : RigidbodyInterpolation2D.Interpolate; } - playerObject = authority.SpawnManager.SpawnedObjects[nonAuthority.LocalClient.PlayerObject.NetworkObjectId]; - position = playerObject.transform.position; - if (!Approximately(ContactEventTransformHelper.ClientSpawnPoint, position)) - { - m_ErrorLogger.AppendLine($"Client-{authority.LocalClientId} player position {position} for Client-{playerObject.OwnerClientId} does not match the assigned player position {ContactEventTransformHelper.ClientSpawnPoint}!"); - return false; - } + Assert.AreEqual(interpolateCompareNonAuthoritative2D, nonAuthorityRigidbody2D.interpolation, $"{nonAuthorityHeader} interpolation is {nonAuthorityRigidbody2D.interpolation} " + + $"and not {interpolateCompareNonAuthoritative}!"); + #endregion - if (!nonAuthority.SpawnManager.SpawnedObjects.ContainsKey(authority.LocalClient.PlayerObject.NetworkObjectId)) - { - m_ErrorLogger.AppendLine($"Client-{nonAuthority.LocalClientId} cannot find a local spawned instance of Client-{authority.LocalClientId}'s player object!"); - return false; - } - playerObject = nonAuthority.SpawnManager.SpawnedObjects[authority.LocalClient.PlayerObject.NetworkObjectId]; - position = playerObject.transform.position; - if (!Approximately(ContactEventTransformHelper.SessionOwnerSpawnPoint, playerObject.transform.position)) - { - m_ErrorLogger.AppendLine($"Client-{nonAuthority.LocalClientId} player position {position} for Client-{playerObject.OwnerClientId} does not match the assigned player position {ContactEventTransformHelper.SessionOwnerSpawnPoint}!"); - return false; - } - return true; + var spawnedInstances = new List() { m_3DAuthorityInstance, m_2DAuthorityInstance }; + m_3DAuthorityInstance.Despawn(); + m_2DAuthorityInstance.Despawn(); + yield return WaitForDespawnedOnAllOrTimeOut(spawnedInstances); + AssertOnTimeout($"Failed to de-spawn instances on all clients!"); + m_3DAuthorityInstance = null; + m_2DAuthorityInstance = null; } - - [UnityTest] - public IEnumerator TestContactEvents() + /// + /// Handle clean up in case of a failed test + /// + protected override IEnumerator OnTearDown() { - ContactEventTransformHelper.VerboseDebug = m_EnableVerboseDebug; - - m_PlayerPrefab.SetActive(false); - m_ErrorLogger.Clear(); - // Validate all instances are spawned in the right location - yield return WaitForConditionOrTimeOut(PlayersSpawnedInRightLocation); - AssertOnTimeout($"Timed out waiting for all player instances to spawn in the corect location:\n {m_ErrorLogger}"); - m_ErrorLogger.Clear(); - - var authority = GetAuthorityNetworkManager(); - var nonAuthority = GetNonAuthorityNetworkManager(); + // If either of these are not null then we most likely failed and didn't cleanup. - var sessionOwnerPlayer = m_ContactEventType == ContactEventTypes.Default ? authority.LocalClient.PlayerObject.GetComponent() : - authority.LocalClient.PlayerObject.GetComponent(); - var clientPlayer = m_ContactEventType == ContactEventTypes.Default ? nonAuthority.LocalClient.PlayerObject.GetComponent() : - nonAuthority.LocalClient.PlayerObject.GetComponent(); - - // Get both players to point towards each other - sessionOwnerPlayer.Target = clientPlayer; - clientPlayer.Target = sessionOwnerPlayer; - - sessionOwnerPlayer.SetHelperState(ContactEventTransformHelper.HelperStates.MoveForward); - clientPlayer.SetHelperState(ContactEventTransformHelper.HelperStates.MoveForward); - - - yield return WaitForConditionOrTimeOut(() => sessionOwnerPlayer.HadContactWith(clientPlayer) || clientPlayer.HadContactWith(sessionOwnerPlayer)); - AssertOnTimeout("Timed out waiting for a player to collide with another player!"); - - clientPlayer.RegisterForContactEvents(false); - sessionOwnerPlayer.RegisterForContactEvents(false); - var otherPlayer = m_ContactEventType == ContactEventTypes.Default ? authority.SpawnManager.SpawnedObjects[clientPlayer.NetworkObjectId].GetComponent() : - authority.SpawnManager.SpawnedObjects[clientPlayer.NetworkObjectId].GetComponent(); - otherPlayer.RegisterForContactEvents(false); - otherPlayer = m_ContactEventType == ContactEventTypes.Default ? nonAuthority.SpawnManager.SpawnedObjects[sessionOwnerPlayer.NetworkObjectId].GetComponent() : - nonAuthority.SpawnManager.SpawnedObjects[sessionOwnerPlayer.NetworkObjectId].GetComponent(); - otherPlayer.RegisterForContactEvents(false); - - Object.Destroy(m_RigidbodyContactEventManager); - m_RigidbodyContactEventManager = null; - } + // Clean-up m_3DAuthorityInstance + if (m_3DAuthorityInstance) + { + Object.Destroy(m_3DAuthorityInstance); + m_3DAuthorityInstance = null; + } - protected override IEnumerator OnTearDown() - { - // In case of a test failure - if (m_RigidbodyContactEventManager) + // Clean-up m_2DAuthorityInstance + if (m_2DAuthorityInstance) { - Object.Destroy(m_RigidbodyContactEventManager); - m_RigidbodyContactEventManager = null; + Object.Destroy(m_2DAuthorityInstance); + m_2DAuthorityInstance = null; } return base.OnTearDown(); diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Physics/RigidbodyContactEventManagerTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Physics/RigidbodyContactEventManagerTests.cs new file mode 100644 index 0000000000..51aaa5ba56 --- /dev/null +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Physics/RigidbodyContactEventManagerTests.cs @@ -0,0 +1,403 @@ +#if COM_UNITY_MODULES_PHYSICS || COM_UNITY_MODULES_PHYSICS2D +using System.Collections; +using System.Collections.Generic; +using System.Text; +using NUnit.Framework; +using Unity.Netcode.Components; +using Unity.Netcode.TestHelpers.Runtime; +using UnityEngine; +using UnityEngine.TestTools; + + +namespace Unity.Netcode.RuntimeTests +{ + + + [TestFixture(HostOrServer.Host, ContactEventTypes.Default)] + [TestFixture(HostOrServer.DAHost, ContactEventTypes.Default)] + [TestFixture(HostOrServer.Host, ContactEventTypes.WithInfo)] + [TestFixture(HostOrServer.DAHost, ContactEventTypes.WithInfo)] + internal class RigidbodyContactEventManagerTests : IntegrationTestWithApproximation + { + protected override int NumberOfClients => 1; + + private GameObject m_RigidbodyContactEventManager; + + public enum ContactEventTypes + { + Default, + WithInfo + } + + private ContactEventTypes m_ContactEventType; + private StringBuilder m_ErrorLogger = new StringBuilder(); + + public RigidbodyContactEventManagerTests(HostOrServer hostOrServer, ContactEventTypes contactEventType) : base(hostOrServer) + { + m_ContactEventType = contactEventType; + } + + protected override void OnCreatePlayerPrefab() + { + ContactEventTransformHelper.SessionOwnerSpawnPoint = GetRandomVector3(-4, -3); + ContactEventTransformHelper.ClientSpawnPoint = GetRandomVector3(3, 4); + if (m_ContactEventType == ContactEventTypes.Default) + { + var helper = m_PlayerPrefab.AddComponent(); + helper.AuthorityMode = NetworkTransform.AuthorityModes.Owner; + } + else + { + var helperWithInfo = m_PlayerPrefab.AddComponent(); + helperWithInfo.AuthorityMode = NetworkTransform.AuthorityModes.Owner; + } + + var rigidbody = m_PlayerPrefab.AddComponent(); + rigidbody.useGravity = false; + rigidbody.isKinematic = true; + rigidbody.mass = 5.0f; + rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous; + var sphereCollider = m_PlayerPrefab.AddComponent(); + sphereCollider.radius = 0.5f; + sphereCollider.providesContacts = true; + + var networkRigidbody = m_PlayerPrefab.AddComponent(); + networkRigidbody.UseRigidBodyForMotion = true; + networkRigidbody.AutoUpdateKinematicState = false; + + m_RigidbodyContactEventManager = new GameObject(); + m_RigidbodyContactEventManager.AddComponent(); + } + + + + private bool PlayersSpawnedInRightLocation() + { + var authority = GetAuthorityNetworkManager(); + var nonAuthority = GetNonAuthorityNetworkManager(); + + var position = authority.LocalClient.PlayerObject.transform.position; + if (!Approximately(ContactEventTransformHelper.SessionOwnerSpawnPoint, position)) + { + m_ErrorLogger.AppendLine($"Client-{authority.LocalClientId} player position {position} does not match the assigned player position {ContactEventTransformHelper.SessionOwnerSpawnPoint}!"); + return false; + } + + position = nonAuthority.LocalClient.PlayerObject.transform.position; + if (!Approximately(ContactEventTransformHelper.ClientSpawnPoint, position)) + { + m_ErrorLogger.AppendLine($"Client-{nonAuthority.LocalClientId} player position {position} does not match the assigned player position {ContactEventTransformHelper.ClientSpawnPoint}!"); + return false; + } + var playerObject = (NetworkObject)null; + if (!authority.SpawnManager.SpawnedObjects.ContainsKey(nonAuthority.LocalClient.PlayerObject.NetworkObjectId)) + { + m_ErrorLogger.AppendLine($"Client-{authority.LocalClientId} cannot find a local spawned instance of Client-{nonAuthority.LocalClientId}'s player object!"); + return false; + } + playerObject = authority.SpawnManager.SpawnedObjects[nonAuthority.LocalClient.PlayerObject.NetworkObjectId]; + position = playerObject.transform.position; + + if (!Approximately(ContactEventTransformHelper.ClientSpawnPoint, position)) + { + m_ErrorLogger.AppendLine($"Client-{authority.LocalClientId} player position {position} for Client-{playerObject.OwnerClientId} does not match the assigned player position {ContactEventTransformHelper.ClientSpawnPoint}!"); + return false; + } + + if (!nonAuthority.SpawnManager.SpawnedObjects.ContainsKey(authority.LocalClient.PlayerObject.NetworkObjectId)) + { + m_ErrorLogger.AppendLine($"Client-{nonAuthority.LocalClientId} cannot find a local spawned instance of Client-{authority.LocalClientId}'s player object!"); + return false; + } + playerObject = nonAuthority.SpawnManager.SpawnedObjects[authority.LocalClient.PlayerObject.NetworkObjectId]; + position = playerObject.transform.position; + if (!Approximately(ContactEventTransformHelper.SessionOwnerSpawnPoint, playerObject.transform.position)) + { + m_ErrorLogger.AppendLine($"Client-{nonAuthority.LocalClientId} player position {position} for Client-{playerObject.OwnerClientId} does not match the assigned player position {ContactEventTransformHelper.SessionOwnerSpawnPoint}!"); + return false; + } + return true; + } + + + [UnityTest] + public IEnumerator TestContactEvents() + { + ContactEventTransformHelper.VerboseDebug = m_EnableVerboseDebug; + + m_PlayerPrefab.SetActive(false); + m_ErrorLogger.Clear(); + // Validate all instances are spawned in the right location + yield return WaitForConditionOrTimeOut(PlayersSpawnedInRightLocation); + AssertOnTimeout($"Timed out waiting for all player instances to spawn in the corect location:\n {m_ErrorLogger}"); + m_ErrorLogger.Clear(); + + var authority = GetAuthorityNetworkManager(); + var nonAuthority = GetNonAuthorityNetworkManager(); + + var sessionOwnerPlayer = m_ContactEventType == ContactEventTypes.Default ? authority.LocalClient.PlayerObject.GetComponent() : + authority.LocalClient.PlayerObject.GetComponent(); + var clientPlayer = m_ContactEventType == ContactEventTypes.Default ? nonAuthority.LocalClient.PlayerObject.GetComponent() : + nonAuthority.LocalClient.PlayerObject.GetComponent(); + + // Get both players to point towards each other + sessionOwnerPlayer.Target = clientPlayer; + clientPlayer.Target = sessionOwnerPlayer; + + sessionOwnerPlayer.SetHelperState(ContactEventTransformHelper.HelperStates.MoveForward); + clientPlayer.SetHelperState(ContactEventTransformHelper.HelperStates.MoveForward); + + + yield return WaitForConditionOrTimeOut(() => sessionOwnerPlayer.HadContactWith(clientPlayer) || clientPlayer.HadContactWith(sessionOwnerPlayer)); + AssertOnTimeout("Timed out waiting for a player to collide with another player!"); + + clientPlayer.RegisterForContactEvents(false); + sessionOwnerPlayer.RegisterForContactEvents(false); + var otherPlayer = m_ContactEventType == ContactEventTypes.Default ? authority.SpawnManager.SpawnedObjects[clientPlayer.NetworkObjectId].GetComponent() : + authority.SpawnManager.SpawnedObjects[clientPlayer.NetworkObjectId].GetComponent(); + otherPlayer.RegisterForContactEvents(false); + otherPlayer = m_ContactEventType == ContactEventTypes.Default ? nonAuthority.SpawnManager.SpawnedObjects[sessionOwnerPlayer.NetworkObjectId].GetComponent() : + nonAuthority.SpawnManager.SpawnedObjects[sessionOwnerPlayer.NetworkObjectId].GetComponent(); + otherPlayer.RegisterForContactEvents(false); + + Object.Destroy(m_RigidbodyContactEventManager); + m_RigidbodyContactEventManager = null; + } + + protected override IEnumerator OnTearDown() + { + // In case of a test failure + if (m_RigidbodyContactEventManager) + { + Object.Destroy(m_RigidbodyContactEventManager); + m_RigidbodyContactEventManager = null; + } + + return base.OnTearDown(); + } + } + + #region Test helper classes + internal class ContactEventTransformHelperWithInfo : ContactEventTransformHelper, IContactEventHandlerWithInfo + { + public ContactEventHandlerInfo GetContactEventHandlerInfo() + { + var contactEventHandlerInfo = new ContactEventHandlerInfo() + { + HasContactEventPriority = IsOwner, + ProvideNonRigidBodyContactEvents = m_EnableNonRigidbodyContacts.Value, + }; + return contactEventHandlerInfo; + } + + protected override void OnRegisterForContactEvents(bool isRegistering) + { + RigidbodyContactEventManager.Instance.RegisterHandler(this, isRegistering); + } + } + + internal class ContactEventTransformHelper : NetworkTransform, IContactEventHandler + { + public static Vector3 SessionOwnerSpawnPoint; + public static Vector3 ClientSpawnPoint; + public static bool VerboseDebug; + public enum HelperStates + { + None, + MoveForward, + } + + private HelperStates m_HelperState; + + public void SetHelperState(HelperStates state) + { + m_HelperState = state; + if (!m_NetworkRigidbody.IsKinematic()) + { + m_NetworkRigidbody.Rigidbody.angularVelocity = Vector3.zero; + m_NetworkRigidbody.Rigidbody.linearVelocity = Vector3.zero; + } + m_NetworkRigidbody.Rigidbody.isKinematic = m_HelperState == HelperStates.None; + if (!m_NetworkRigidbody.IsKinematic()) + { + m_NetworkRigidbody.Rigidbody.angularVelocity = Vector3.zero; + m_NetworkRigidbody.Rigidbody.linearVelocity = Vector3.zero; + } + + } + + protected struct ContactEventInfo + { + public ulong EventId; + public Vector3 AveragedCollisionNormal; + public Rigidbody CollidingBody; + public Vector3 ContactPoint; + } + + protected List m_ContactEvents = new List(); + + protected NetworkVariable m_EnableNonRigidbodyContacts = new NetworkVariable(false, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + + protected NetworkRigidbody m_NetworkRigidbody; + public ContactEventTransformHelper Target; + + public bool HasContactEvents() + { + return m_ContactEvents.Count > 0; + } + + public Rigidbody GetRigidbody() + { + return m_NetworkRigidbody.Rigidbody; + } + + public bool HadContactWith(ContactEventTransformHelper otherObject) + { + if (otherObject == null) + { + return false; + } + foreach (var contactEvent in m_ContactEvents) + { + if (contactEvent.CollidingBody == otherObject.m_NetworkRigidbody.Rigidbody) + { + return true; + } + } + return false; + } + + protected virtual void CheckToStopMoving() + { + SetHelperState(HadContactWith(Target) ? HelperStates.None : HelperStates.MoveForward); + } + + public void ContactEvent(ulong eventId, Vector3 averagedCollisionNormal, Rigidbody collidingBody, Vector3 contactPoint, bool hasCollisionStay = false, Vector3 averagedCollisionStayNormal = default) + { + if (Target == null) + { + return; + } + + if (collidingBody != null) + { + Log($">>>>>>> contact event with {collidingBody.name}!"); + } + else + { + Log($">>>>>>> contact event with non-rigidbody!"); + } + + m_ContactEvents.Add(new ContactEventInfo() + { + EventId = eventId, + AveragedCollisionNormal = averagedCollisionNormal, + CollidingBody = collidingBody, + ContactPoint = contactPoint, + }); + CheckToStopMoving(); + } + + private void SetInitialPositionClientServer() + { + if (IsServer) + { + if (!NetworkManager.DistributedAuthorityMode && !IsLocalPlayer) + { + transform.position = ClientSpawnPoint; + m_NetworkRigidbody.Rigidbody.position = ClientSpawnPoint; + } + else + { + transform.position = SessionOwnerSpawnPoint; + m_NetworkRigidbody.Rigidbody.position = SessionOwnerSpawnPoint; + } + } + else + { + transform.position = ClientSpawnPoint; + m_NetworkRigidbody.Rigidbody.position = ClientSpawnPoint; + } + } + + private void SetInitialPositionDistributedAuthority() + { + if (HasAuthority) + { + if (IsSessionOwner) + { + transform.position = SessionOwnerSpawnPoint; + m_NetworkRigidbody.Rigidbody.position = SessionOwnerSpawnPoint; + } + else + { + transform.position = ClientSpawnPoint; + m_NetworkRigidbody.Rigidbody.position = ClientSpawnPoint; + } + } + } + + public override void OnNetworkSpawn() + { + m_NetworkRigidbody = GetComponent(); + + m_NetworkRigidbody.Rigidbody.maxLinearVelocity = 15; + m_NetworkRigidbody.Rigidbody.maxAngularVelocity = 10; + + if (NetworkManager.DistributedAuthorityMode) + { + SetInitialPositionDistributedAuthority(); + } + else + { + SetInitialPositionClientServer(); + } + if (IsLocalPlayer) + { + RegisterForContactEvents(true); + } + else + { + m_NetworkRigidbody.Rigidbody.detectCollisions = false; + } + base.OnNetworkSpawn(); + } + + protected virtual void OnRegisterForContactEvents(bool isRegistering) + { + RigidbodyContactEventManager.Instance.RegisterHandler(this, isRegistering); + } + + public void RegisterForContactEvents(bool isRegistering) + { + OnRegisterForContactEvents(isRegistering); + } + + private void FixedUpdate() + { + if (!IsSpawned || !IsOwner || m_HelperState != HelperStates.MoveForward) + { + return; + } + var distance = Vector3.Distance(Target.transform.position, transform.position); + var moveAmount = Mathf.Max(1.2f, distance); + // Head towards our target + var dir = (Target.transform.position - transform.position).normalized; + var deltaMove = dir * moveAmount * Time.fixedDeltaTime; + m_NetworkRigidbody.Rigidbody.MovePosition(m_NetworkRigidbody.Rigidbody.position + deltaMove); + + + Log($" Loc: {transform.position} | Dest: {Target.transform.position} | Dist: {distance} | MoveDelta: {deltaMove}"); + } + + protected void Log(string msg) + { + if (VerboseDebug) + { + Debug.Log($"Client-{OwnerClientId} {msg}"); + } + } + } + #endregion +} +#endif diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Physics/RigidbodyContactEventManagerTests.cs.meta b/com.unity.netcode.gameobjects/Tests/Runtime/Physics/RigidbodyContactEventManagerTests.cs.meta new file mode 100644 index 0000000000..687995a482 --- /dev/null +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Physics/RigidbodyContactEventManagerTests.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 6d002e232abdb5049aa3c4f5cc36292d \ No newline at end of file diff --git a/testproject/Assets/Tests/Runtime/Physics.meta b/testproject/Assets/Tests/Runtime/Physics.meta deleted file mode 100644 index de0808f1a7..0000000000 --- a/testproject/Assets/Tests/Runtime/Physics.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: efc90b4d4d76f7a48ad1cf726a3a193e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbody2DCntChangeOwnershipTest.cs b/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbody2DCntChangeOwnershipTest.cs deleted file mode 100644 index 4f3c651cb3..0000000000 --- a/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbody2DCntChangeOwnershipTest.cs +++ /dev/null @@ -1,95 +0,0 @@ -// using System.Collections; -// using NUnit.Framework; -// using Unity.Netcode.Components; -// using Unity.Netcode.Samples; -// using UnityEngine; -// using UnityEngine.TestTools; -// -// // Tests for ClientNetworkTransform (CNT) + NetworkRigidbody. This test is in TestProject because it needs access to ClientNetworkTransform -// namespace Unity.Netcode.RuntimeTests -// { -// public class NetworkRigidbody2DDynamicCntChangeOwnershipTest : NetworkRigidbody2DCntChangeOwnershipTestBase -// { -// public override bool Kinematic => false; -// } -// -// public class NetworkRigidbody2DKinematicCntChangeOwnershipTest : NetworkRigidbody2DCntChangeOwnershipTestBase -// { -// public override bool Kinematic => true; -// } -// -// public abstract class NetworkRigidbody2DCntChangeOwnershipTestBase : NetcodeIntegrationTest -// { -// protected override int NumberOfClients => 1; -// -// public abstract bool Kinematic { get; } -// -// [UnitySetUp] -// public override IEnumerator Setup() -// { -// yield return StartSomeClientsAndServerWithPlayers(true, NumberOfClients, playerPrefab => -// { -// playerPrefab.AddComponent(); -// playerPrefab.AddComponent(); -// playerPrefab.AddComponent(); -// playerPrefab.GetComponent().isKinematic = Kinematic; -// }); -// } -// /// -// /// Tests that a server can destroy a NetworkObject and that it gets despawned correctly. -// /// -// /// -// [UnityTest] -// public IEnumerator TestRigidbodyKinematicEnableDisable() -// { -// // This is the *SERVER VERSION* of the *CLIENT PLAYER* -// var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); -// yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ServerNetworkManager, serverClientPlayerResult); -// var serverPlayer = serverClientPlayerResult.Result.gameObject; -// -// // This is the *CLIENT VERSION* of the *CLIENT PLAYER* -// var clientClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); -// yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ClientNetworkManagers[0], clientClientPlayerResult); -// var clientPlayer = clientClientPlayerResult.Result.gameObject; -// -// Assert.IsNotNull(serverPlayer); -// Assert.IsNotNull(clientPlayer); -// -// int waitFor = Time.frameCount + 2; -// yield return new WaitUntil(() => Time.frameCount >= waitFor); -// -// TestKinematicSetCorrectly(clientPlayer, serverPlayer); -// -// -// // give server ownership over the player -// -// serverPlayer.GetComponent().ChangeOwnership(NetworkManager.ServerClientId); -// -// yield return null; -// yield return null; -// -// // server should now be able to commit to transform -// TestKinematicSetCorrectly(serverPlayer, clientPlayer); -// -// // return ownership to client -// serverPlayer.GetComponent().ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId); -// yield return null; -// yield return null; -// -// // client should again be able to commit -// TestKinematicSetCorrectly(clientPlayer, serverPlayer); -// } -// -// -// -// private void TestKinematicSetCorrectly(GameObject canCommitPlayer, GameObject canNotCommitPlayer) -// { -// -// // can commit player has authority and should have a kinematic mode of false (or true in case body was already kinematic). -// Assert.True(canCommitPlayer.GetComponent().isKinematic == Kinematic); -// -// // can not commit player has no authority and should have a kinematic mode of true -// Assert.True(canNotCommitPlayer.GetComponent().isKinematic); -// } -// } -// } diff --git a/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbody2DCntChangeOwnershipTest.cs.meta b/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbody2DCntChangeOwnershipTest.cs.meta deleted file mode 100644 index b1c3736256..0000000000 --- a/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbody2DCntChangeOwnershipTest.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a51c7f7b93f04e3499089963d9bbb254 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbody2DCntTest.cs b/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbody2DCntTest.cs deleted file mode 100644 index eac6d42d7e..0000000000 --- a/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbody2DCntTest.cs +++ /dev/null @@ -1,82 +0,0 @@ -// using System.Collections; -// using NUnit.Framework; -// using Unity.Netcode.Components; -// using Unity.Netcode.Samples; -// using UnityEngine; -// using UnityEngine.TestTools; -// -// // Tests for ClientNetworkTransform (CNT) + NetworkRigidbody2D. This test is in TestProject because it needs access to ClientNetworkTransform -// namespace Unity.Netcode.RuntimeTests -// { -// public class NetworkRigidbody2DDynamicCntTest : NetworkRigidbody2DCntTestBase -// { -// public override bool Kinematic => false; -// } -// -// public class NetworkRigidbody2DKinematicCntTest : NetworkRigidbody2DCntTestBase -// { -// public override bool Kinematic => true; -// } -// -// public abstract class NetworkRigidbody2DCntTestBase : NetcodeIntegrationTest -// { -// protected override int NumberOfClients => 1; -// -// public abstract bool Kinematic { get; } -// -// [UnitySetUp] -// public override IEnumerator Setup() -// { -// yield return StartSomeClientsAndServerWithPlayers(true, NumberOfClients, playerPrefab => -// { -// playerPrefab.AddComponent(); -// playerPrefab.AddComponent(); -// playerPrefab.AddComponent(); -// playerPrefab.GetComponent().isKinematic = Kinematic; -// }); -// } -// -// /// -// /// Tests that a server can destroy a NetworkObject and that it gets despawned correctly. -// /// -// /// -// [UnityTest] -// public IEnumerator TestRigidbodyKinematicEnableDisable() -// { -// // This is the *SERVER VERSION* of the *CLIENT PLAYER* -// var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); -// yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ServerNetworkManager, serverClientPlayerResult); -// var serverPlayer = serverClientPlayerResult.Result.gameObject; -// -// // This is the *CLIENT VERSION* of the *CLIENT PLAYER* -// var clientClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); -// yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ClientNetworkManagers[0], clientClientPlayerResult); -// var clientPlayer = clientClientPlayerResult.Result.gameObject; -// -// Assert.IsNotNull(serverPlayer); -// Assert.IsNotNull(clientPlayer); -// -// int waitFor = Time.frameCount + 2; -// yield return new WaitUntil(() => Time.frameCount >= waitFor); -// -// TestKinematicSetCorrectly(clientPlayer, serverPlayer); -// -// // despawn the server player -// serverPlayer.GetComponent().Despawn(false); -// -// yield return null; -// yield return null; -// Assert.IsTrue(clientPlayer == null); // safety check that object is actually despawned. -// } -// -// private void TestKinematicSetCorrectly(GameObject canCommitPlayer, GameObject canNotCommitPlayer) -// { -// -// // can commit player has authority and should have a kinematic mode of false (or true in case body was already kinematic). -// Assert.True(canCommitPlayer.GetComponent().isKinematic == Kinematic); -// -// // can not commit player has no authority and should have a kinematic mode of true -// Assert.True(canNotCommitPlayer.GetComponent().isKinematic); -// } -// } -// } diff --git a/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbody2DCntTest.cs.meta b/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbody2DCntTest.cs.meta deleted file mode 100644 index f0d4cff600..0000000000 --- a/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbody2DCntTest.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5ae5587c06cba7a46b93ee6774741c0d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbodyCntChangeOwnershipTest.cs b/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbodyCntChangeOwnershipTest.cs deleted file mode 100644 index 2e45162f52..0000000000 --- a/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbodyCntChangeOwnershipTest.cs +++ /dev/null @@ -1,95 +0,0 @@ -// using System.Collections; -// using NUnit.Framework; -// using Unity.Netcode.Components; -// using Unity.Netcode.Samples; -// using UnityEngine; -// using UnityEngine.TestTools; -// -// // Tests for ClientNetworkTransform (CNT) + NetworkRigidbody. This test is in TestProject because it needs access to ClientNetworkTransform -// namespace Unity.Netcode.RuntimeTests -// { -// public class NetworkRigidbodyDynamicCntChangeOwnershipTest : NetworkRigidbodyCntChangeOwnershipTestBase -// { -// public override bool Kinematic => false; -// } -// -// public class NetworkRigidbodyKinematicCntChangeOwnershipTest : NetworkRigidbodyCntChangeOwnershipTestBase -// { -// public override bool Kinematic => true; -// } -// -// public abstract class NetworkRigidbodyCntChangeOwnershipTestBase : NetcodeIntegrationTest -// { -// protected override int NumberOfClients => 1; -// -// public abstract bool Kinematic { get; } -// -// [UnitySetUp] -// public override IEnumerator Setup() -// { -// yield return StartSomeClientsAndServerWithPlayers(true, NumberOfClients, playerPrefab => -// { -// playerPrefab.AddComponent(); -// playerPrefab.AddComponent(); -// playerPrefab.AddComponent(); -// playerPrefab.GetComponent().isKinematic = Kinematic; -// }); -// } -// /// -// /// Tests that a server can destroy a NetworkObject and that it gets despawned correctly. -// /// -// /// -// [UnityTest] -// public IEnumerator TestRigidbodyKinematicEnableDisable() -// { -// // This is the *SERVER VERSION* of the *CLIENT PLAYER* -// var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); -// yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ServerNetworkManager, serverClientPlayerResult); -// var serverPlayer = serverClientPlayerResult.Result.gameObject; -// -// // This is the *CLIENT VERSION* of the *CLIENT PLAYER* -// var clientClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); -// yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ClientNetworkManagers[0], clientClientPlayerResult); -// var clientPlayer = clientClientPlayerResult.Result.gameObject; -// -// Assert.IsNotNull(serverPlayer); -// Assert.IsNotNull(clientPlayer); -// -// int waitFor = Time.frameCount + 2; -// yield return new WaitUntil(() => Time.frameCount >= waitFor); -// -// TestKinematicSetCorrectly(clientPlayer, serverPlayer); -// -// -// // give server ownership over the player -// -// serverPlayer.GetComponent().ChangeOwnership(NetworkManager.ServerClientId); -// -// yield return null; -// yield return null; -// -// // server should now be able to commit to transform -// TestKinematicSetCorrectly(serverPlayer, clientPlayer); -// -// // return ownership to client -// serverPlayer.GetComponent().ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId); -// yield return null; -// yield return null; -// -// // client should again be able to commit -// TestKinematicSetCorrectly(clientPlayer, serverPlayer); -// } -// -// -// -// private void TestKinematicSetCorrectly(GameObject canCommitPlayer, GameObject canNotCommitPlayer) -// { -// -// // can commit player has authority and should have a kinematic mode of false (or true in case body was already kinematic). -// Assert.True(canCommitPlayer.GetComponent().isKinematic == Kinematic); -// -// // can not commit player has no authority and should have a kinematic mode of true -// Assert.True(canNotCommitPlayer.GetComponent().isKinematic); -// } -// } -// } diff --git a/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbodyCntChangeOwnershipTest.cs.meta b/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbodyCntChangeOwnershipTest.cs.meta deleted file mode 100644 index 3eb4f88f5b..0000000000 --- a/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbodyCntChangeOwnershipTest.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 941008c8040f03c44bd835d24b073260 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbodyCntTest.cs b/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbodyCntTest.cs deleted file mode 100644 index 72f0c72b96..0000000000 --- a/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbodyCntTest.cs +++ /dev/null @@ -1,82 +0,0 @@ -// using System.Collections; -// using NUnit.Framework; -// using Unity.Netcode.Components; -// using Unity.Netcode.Samples; -// using UnityEngine; -// using UnityEngine.TestTools; -// -// // Tests for ClientNetworkTransform (CNT) + NetworkRigidbody. This test is in TestProject because it needs access to ClientNetworkTransform -// namespace Unity.Netcode.RuntimeTests -// { -// public class NetworkRigidbodyDynamicCntTest : NetworkRigidbodyCntTestBase -// { -// public override bool Kinematic => false; -// } -// -// public class NetworkRigidbodyKinematicCntTest : NetworkRigidbodyCntTestBase -// { -// public override bool Kinematic => true; -// } -// -// public abstract class NetworkRigidbodyCntTestBase : NetcodeIntegrationTest -// { -// protected override int NumberOfClients => 1; -// -// public abstract bool Kinematic { get; } -// -// [UnitySetUp] -// public override IEnumerator Setup() -// { -// yield return StartSomeClientsAndServerWithPlayers(true, NumberOfClients, playerPrefab => -// { -// playerPrefab.AddComponent(); -// playerPrefab.AddComponent(); -// playerPrefab.AddComponent(); -// playerPrefab.GetComponent().isKinematic = Kinematic; -// }); -// } -// /// -// /// Tests that a server can destroy a NetworkObject and that it gets despawned correctly. -// /// -// /// -// [UnityTest] -// public IEnumerator TestRigidbodyKinematicEnableDisable() -// { -// // This is the *SERVER VERSION* of the *CLIENT PLAYER* -// var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); -// yield returnNetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ServerNetworkManager, serverClientPlayerResult); -// var serverPlayer = serverClientPlayerResult.Result.gameObject; -// -// // This is the *CLIENT VERSION* of the *CLIENT PLAYER* -// var clientClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); -// yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ClientNetworkManagers[0], clientClientPlayerResult); -// var clientPlayer = clientClientPlayerResult.Result.gameObject; -// -// Assert.IsNotNull(serverPlayer); -// Assert.IsNotNull(clientPlayer); -// -// int waitFor = Time.frameCount + 2; -// yield return new WaitUntil(() => Time.frameCount >= waitFor); -// -// TestKinematicSetCorrectly(clientPlayer, serverPlayer); -// -// // despawn the server player -// serverPlayer.GetComponent().Despawn(false); -// -// yield return null; -// yield return null; -// -// Assert.IsTrue(clientPlayer == null); // safety check that object is actually despawned. -// } -// -// private void TestKinematicSetCorrectly(GameObject canCommitPlayer, GameObject canNotCommitPlayer) -// { -// -// // can commit player has authority and should have a kinematic mode of false (or true in case body was already kinematic). -// Assert.True(canCommitPlayer.GetComponent().isKinematic == Kinematic); -// -// // can not commit player has no authority and should have a kinematic mode of true -// Assert.True(canNotCommitPlayer.GetComponent().isKinematic); -// } -// } -// } diff --git a/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbodyCntTest.cs.meta b/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbodyCntTest.cs.meta deleted file mode 100644 index cea97efc01..0000000000 --- a/testproject/Assets/Tests/Runtime/Physics/NetworkRigidbodyCntTest.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e89712f9406aaa84d85508fa07d97655 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: