From 4427d35ddeae0c1864dfa08cc48edcbac84b198c Mon Sep 17 00:00:00 2001 From: Samuel Bellomo Date: Fri, 21 May 2021 14:12:17 -0400 Subject: [PATCH 01/16] base --- .../Tests/Runtime/NetworkTransformTests.cs | 98 +++++++++++++++++++ .../Runtime/NetworkTransformTests.cs.meta | 3 + 2 files changed, 101 insertions(+) create mode 100644 com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs create mode 100644 com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs.meta diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs new file mode 100644 index 0000000000..ac3d61438e --- /dev/null +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs @@ -0,0 +1,98 @@ +// using System; +// using System.Collections; +// using MLAPI.Prototyping; +// using NUnit.Framework; +// using UnityEngine; +// using UnityEngine.TestTools; +// +// namespace MLAPI.RuntimeTests +// { +// public class NetworkTransformTests +// { +// private NetworkObject m_Player; +// private NetworkObject m_PlayerGhost; +// +// [UnitySetUp] +// public IEnumerator Setup() +// { +// LogAssert.ignoreFailingMessages = true; +// +// // Create multiple NetworkManager instances +// if (!MultiInstanceHelpers.Create(1, out NetworkManager server, out NetworkManager[] clients)) +// { +// Debug.LogError("Failed to create instances"); +// Assert.Fail("Failed to create instances"); +// } +// +// // Create playerPrefab +// GameObject playerPrefab = new GameObject("Player"); +// NetworkObject networkObject = playerPrefab.AddComponent(); +// var networkTransform = playerPrefab.AddComponent(); +// networkTransform.authority = NetworkTransform.Authority.Client; +// +// // Make it a prefab +// MultiInstanceHelpers.MakeNetworkedObjectTestPrefab(networkObject); +// +// // Set the player prefab +// server.NetworkConfig.PlayerPrefab = playerPrefab; +// +// for (int i = 0; i < clients.Length; i++) +// { +// clients[i].NetworkConfig.PlayerPrefab = playerPrefab; +// } +// +// // Start the instances +// if (!MultiInstanceHelpers.Start(true, server, clients)) +// { +// Debug.LogError("Failed to start instances"); +// Assert.Fail("Failed to start instances"); +// } +// +// // Wait for connection on client side +// yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientConnected(clients[0])); +// +// // Wait for connection on server side +// yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientConnectedToServer(server)); +// +// // This is the *SERVER VERSION* of the *CLIENT PLAYER* +// var serverClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper(); +// yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == clients[0].LocalClientId), server, serverClientPlayerResult)); +// +// // This is the *CLIENT VERSION* of the *CLIENT PLAYER* +// var clientClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper(); +// yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == clients[0].LocalClientId), clients[0], clientClientPlayerResult)); +// +// m_PlayerGhost = serverClientPlayerResult.Result; +// m_Player = clientClientPlayerResult.Result; +// } +// +// [UnityTest()] +// public IEnumerator TestMove() +// { +// Debug.Log("Testing position"); +// var playerTransform = m_Player.transform; +// playerTransform.position = new Vector3(10, 0, 0); +// Assert.AreEqual(0f, m_PlayerGhost.transform.position.x, "wrong initial value"); // sanity check +// yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => m_PlayerGhost.transform.position.x != 0 )); +// Assert.AreEqual(10, m_PlayerGhost.transform.position.x, "wrong position on ghost"); +// Debug.Log("Testing rotation"); +// +// playerTransform.rotation = Quaternion.Euler(90, 0, 0); +// Assert.AreEqual(90, playerTransform.rotation.eulerAngles.x); // sanity check +// Assert.AreEqual(0f, m_PlayerGhost.transform.rotation.x, "wrong initial value"); // sanity check +// yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => m_PlayerGhost.transform.rotation.eulerAngles.x != 0 )); +// Assert.True(Math.Abs(90 - m_PlayerGhost.transform.rotation.eulerAngles.x) < 0.05f, $"wrong rotation on ghost, expected 90, got {m_PlayerGhost.transform.rotation.eulerAngles.x}"); +// Debug.Log("Testing scale"); +// +// playerTransform.localScale = new Vector3(2, 2, 2); +// Assert.AreEqual(1f, m_PlayerGhost.transform.lossyScale.x, "wrong initial value"); // sanity check +// yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => m_PlayerGhost.transform.lossyScale.x > 1f )); +// Assert.AreEqual(2, m_PlayerGhost.transform.lossyScale.x, "wrong scale on ghost"); +// +// // todo reparent and test +// // todo add tests for authority +// // todo test all public API +// +// } +// } +// } diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs.meta b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs.meta new file mode 100644 index 0000000000..eeff764982 --- /dev/null +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5b3f72de99484a1c9e835c1f0d349475 +timeCreated: 1620872927 \ No newline at end of file From 5eee5876acb54ab629143f2b484c09902871c5b7 Mon Sep 17 00:00:00 2001 From: Samuel Bellomo Date: Fri, 21 May 2021 17:45:35 -0400 Subject: [PATCH 02/16] base tests work, more tests incoming added base test class to remove boiler plate code --- .../Prototyping/NetworkTransform.cs | 40 ++-- .../MultiInstance/BaseMultiInstanceTest.cs | 92 ++++++++ .../BaseMultiInstanceTest.cs.meta | 3 + .../Tests/Runtime/NetworkTransformTests.cs | 216 ++++++++++-------- ...nity.multiplayer.mlapi.runtimetests.asmdef | 22 +- 5 files changed, 256 insertions(+), 117 deletions(-) create mode 100644 com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs create mode 100644 com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs.meta diff --git a/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs b/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs index 2e7ab08182..90fb8f6783 100644 --- a/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs +++ b/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs @@ -107,6 +107,31 @@ public bool UseLocal set => m_UseLocal.Value = value; } + public void SetAuthority(Authority newAuthority) + { + TransformAuthority = newAuthority; + UpdateVarPermissions(); + // todo this should be synced with the other side. let's wait for a more final solution before adding more code here + } + + private void UpdateVarPermissions() + { + if (TransformAuthority == Authority.Client) + { + m_NetworkPosition.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; + m_NetworkRotation.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; + m_NetworkWorldScale.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; + m_UseLocal.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; + } + else if (TransformAuthority == Authority.Shared) + { + m_NetworkPosition.Settings.WritePermission = NetworkVariablePermission.Everyone; + m_NetworkRotation.Settings.WritePermission = NetworkVariablePermission.Everyone; + m_NetworkWorldScale.Settings.WritePermission = NetworkVariablePermission.Everyone; + m_UseLocal.Settings.WritePermission = NetworkVariablePermission.Everyone; + } + } + private NetworkVariableVector3 m_NetworkPosition = new NetworkVariableVector3(); private NetworkVariableQuaternion m_NetworkRotation = new NetworkVariableQuaternion(); private NetworkVariableVector3 m_NetworkWorldScale = new NetworkVariableVector3(); @@ -205,20 +230,7 @@ void SetupVar(NetworkVariable v, T initialValue, ref T oldVal) SetupVar(m_NetworkRotation, m_CurrentRotation, ref m_OldRotation); SetupVar(m_NetworkWorldScale, m_CurrentScale, ref m_OldScale); - if (TransformAuthority == Authority.Client) - { - m_NetworkPosition.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; - m_NetworkRotation.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; - m_NetworkWorldScale.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; - m_UseLocal.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; - } - else if (TransformAuthority == Authority.Shared) - { - m_NetworkPosition.Settings.WritePermission = NetworkVariablePermission.Everyone; - m_NetworkRotation.Settings.WritePermission = NetworkVariablePermission.Everyone; - m_NetworkWorldScale.Settings.WritePermission = NetworkVariablePermission.Everyone; - m_UseLocal.Settings.WritePermission = NetworkVariablePermission.Everyone; - } + UpdateVarPermissions(); } private NetworkVariable.OnValueChangedDelegate GetOnValueChangedDelegate(Action assignCurrent) diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs new file mode 100644 index 0000000000..0b4847aff4 --- /dev/null +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections; +using NUnit.Framework; +using UnityEngine; + +namespace MLAPI.RuntimeTests +{ + public class BaseMultiInstanceTest + { + private int m_OriginalTargetFrameRate; + + protected GameObject m_PlayerPrefab; + + protected NetworkManager m_ServerNetworkManager; + protected NetworkManager[] m_ClientNetworkManagers; + + public virtual void Setup() + { + // Just always track the current target frame rate (will be re-applied upon TearDown) + m_OriginalTargetFrameRate = Application.targetFrameRate; + + // Since we use frame count as a metric, we need to assure it runs at a "common update rate" + // between platforms (i.e. Ubuntu seems to run at much higher FPS when set to -1) + if (Application.targetFrameRate < 0 || Application.targetFrameRate > 120) + { + Application.targetFrameRate = 120; + } + } + + public virtual IEnumerator Teardown() + { + // Shutdown and clean up both of our NetworkManager instances + MultiInstanceHelpers.Destroy(); + + // Set the application's target frame rate back to its original value + Application.targetFrameRate = m_OriginalTargetFrameRate; + yield return new WaitForSeconds(0); // wait for next frame so everything is destroyed, so following tests can execute from clean environment + } + + /// + /// Utility to spawn some clients and a server and set them up + /// + /// + /// Update the prefab with whatever is needed before players spawn + /// + public IEnumerator StartSomeClientAndServer(int nbClients, Action updatePlayerPrefab) + { + // Create multiple NetworkManager instances + if (!MultiInstanceHelpers.Create(nbClients, out NetworkManager server, out NetworkManager[] clients)) + { + Debug.LogError("Failed to create instances"); + Assert.Fail("Failed to create instances"); + } + + m_ClientNetworkManagers = clients; + m_ServerNetworkManager = server; + + // Create playerPrefab + m_PlayerPrefab = new GameObject("Player"); + NetworkObject networkObject = m_PlayerPrefab.AddComponent(); + + // Make it a prefab + MultiInstanceHelpers.MakeNetworkedObjectTestPrefab(networkObject); + + updatePlayerPrefab(m_PlayerPrefab); // update player prefab with whatever is needed before players are spawned + + // Set the player prefab + server.NetworkConfig.PlayerPrefab = m_PlayerPrefab; + + for (int i = 0; i < clients.Length; i++) + { + clients[i].NetworkConfig.PlayerPrefab = m_PlayerPrefab; + } + + // Start the instances + if (!MultiInstanceHelpers.Start(true, server, clients)) + { + Debug.LogError("Failed to start instances"); + Assert.Fail("Failed to start instances"); + } + + // Wait for connection on client side + for (int i = 0; i < clients.Length; i++) + { + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientConnected(clients[i])); + } + + // Wait for connection on server side + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnectedToServer(server, clientCount: nbClients+1)); + } + } +} diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs.meta b/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs.meta new file mode 100644 index 0000000000..94eb21978a --- /dev/null +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 789a3189410645aca48f11a51c823418 +timeCreated: 1621620979 \ No newline at end of file diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs index ac3d61438e..6548441988 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs @@ -1,98 +1,118 @@ -// using System; -// using System.Collections; -// using MLAPI.Prototyping; -// using NUnit.Framework; -// using UnityEngine; -// using UnityEngine.TestTools; -// -// namespace MLAPI.RuntimeTests -// { -// public class NetworkTransformTests -// { -// private NetworkObject m_Player; -// private NetworkObject m_PlayerGhost; -// -// [UnitySetUp] -// public IEnumerator Setup() -// { -// LogAssert.ignoreFailingMessages = true; -// -// // Create multiple NetworkManager instances -// if (!MultiInstanceHelpers.Create(1, out NetworkManager server, out NetworkManager[] clients)) -// { -// Debug.LogError("Failed to create instances"); -// Assert.Fail("Failed to create instances"); -// } -// -// // Create playerPrefab -// GameObject playerPrefab = new GameObject("Player"); -// NetworkObject networkObject = playerPrefab.AddComponent(); -// var networkTransform = playerPrefab.AddComponent(); -// networkTransform.authority = NetworkTransform.Authority.Client; -// -// // Make it a prefab -// MultiInstanceHelpers.MakeNetworkedObjectTestPrefab(networkObject); -// -// // Set the player prefab -// server.NetworkConfig.PlayerPrefab = playerPrefab; -// -// for (int i = 0; i < clients.Length; i++) -// { -// clients[i].NetworkConfig.PlayerPrefab = playerPrefab; -// } -// -// // Start the instances -// if (!MultiInstanceHelpers.Start(true, server, clients)) -// { -// Debug.LogError("Failed to start instances"); -// Assert.Fail("Failed to start instances"); -// } -// -// // Wait for connection on client side -// yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientConnected(clients[0])); -// -// // Wait for connection on server side -// yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientConnectedToServer(server)); -// -// // This is the *SERVER VERSION* of the *CLIENT PLAYER* -// var serverClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper(); -// yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == clients[0].LocalClientId), server, serverClientPlayerResult)); -// -// // This is the *CLIENT VERSION* of the *CLIENT PLAYER* -// var clientClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper(); -// yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == clients[0].LocalClientId), clients[0], clientClientPlayerResult)); -// -// m_PlayerGhost = serverClientPlayerResult.Result; -// m_Player = clientClientPlayerResult.Result; -// } -// -// [UnityTest()] -// public IEnumerator TestMove() -// { -// Debug.Log("Testing position"); -// var playerTransform = m_Player.transform; -// playerTransform.position = new Vector3(10, 0, 0); -// Assert.AreEqual(0f, m_PlayerGhost.transform.position.x, "wrong initial value"); // sanity check -// yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => m_PlayerGhost.transform.position.x != 0 )); -// Assert.AreEqual(10, m_PlayerGhost.transform.position.x, "wrong position on ghost"); -// Debug.Log("Testing rotation"); -// -// playerTransform.rotation = Quaternion.Euler(90, 0, 0); -// Assert.AreEqual(90, playerTransform.rotation.eulerAngles.x); // sanity check -// Assert.AreEqual(0f, m_PlayerGhost.transform.rotation.x, "wrong initial value"); // sanity check -// yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => m_PlayerGhost.transform.rotation.eulerAngles.x != 0 )); -// Assert.True(Math.Abs(90 - m_PlayerGhost.transform.rotation.eulerAngles.x) < 0.05f, $"wrong rotation on ghost, expected 90, got {m_PlayerGhost.transform.rotation.eulerAngles.x}"); -// Debug.Log("Testing scale"); -// -// playerTransform.localScale = new Vector3(2, 2, 2); -// Assert.AreEqual(1f, m_PlayerGhost.transform.lossyScale.x, "wrong initial value"); // sanity check -// yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => m_PlayerGhost.transform.lossyScale.x > 1f )); -// Assert.AreEqual(2, m_PlayerGhost.transform.lossyScale.x, "wrong scale on ghost"); -// -// // todo reparent and test -// // todo add tests for authority -// // todo test all public API -// -// } -// } -// } +using System; +using System.Collections; +using System.Text.RegularExpressions; +using MLAPI.Prototyping; +using NUnit.Framework; +using UnityEngine; +using UnityEngine.TestTools; + +namespace MLAPI.RuntimeTests +{ + public class NetworkTransformTests : BaseMultiInstanceTest + { + private NetworkObject m_ClientSideClientPlayer; + private NetworkObject m_ServerSideClientPlayer; + + [UnitySetUp] + public new IEnumerator Setup() + { + base.Setup(); + + yield return StartSomeClientAndServer(nbClients: 1, updatePlayerPrefab: playerPrefab => + { + var networkTransform = playerPrefab.AddComponent(); + }); + + // This is the *SERVER VERSION* of the *CLIENT PLAYER* + var serverClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper(); + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ServerNetworkManager, serverClientPlayerResult)); + + // This is the *CLIENT VERSION* of the *CLIENT PLAYER* + var clientClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper(); + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ClientNetworkManagers[0], clientClientPlayerResult)); + + m_ServerSideClientPlayer = serverClientPlayerResult.Result; + m_ClientSideClientPlayer = clientClientPlayerResult.Result; + } + + [UnityTest] + [TestCase(true, ExpectedResult = null)] + [TestCase(false, ExpectedResult = null)] + public IEnumerator TestClientAuthoritativeTransformChangeOneAtATime(bool useLocal) + { + var clientNetworkTransform = m_ClientSideClientPlayer.GetComponent(); + clientNetworkTransform.UseLocal = useLocal; + clientNetworkTransform.SetAuthority(NetworkTransform.Authority.Client); + + var serverNetworkTransform = m_ServerSideClientPlayer.GetComponent(); + serverNetworkTransform.UseLocal = useLocal; + serverNetworkTransform.SetAuthority(NetworkTransform.Authority.Client); + + // test position + var playerTransform = m_ClientSideClientPlayer.transform; + playerTransform.position = new Vector3(10, 20, 30); + Assert.AreEqual(Vector3.zero, m_ServerSideClientPlayer.transform.position, "server side pos should be zero at first"); // sanity check + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => m_ServerSideClientPlayer.transform.position.x != 0 )); + + Assert.AreEqual(new Vector3(10, 20, 30), m_ServerSideClientPlayer.transform.position, "wrong position on ghost"); + + // test rotation + playerTransform.rotation = Quaternion.Euler(45, 40, 35); + Assert.AreEqual(Quaternion.identity, m_ServerSideClientPlayer.transform.rotation, "wrong initial value for rotation"); // sanity check + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => m_ServerSideClientPlayer.transform.rotation.eulerAngles.x != 0 )); + + Assert.LessOrEqual(Math.Abs(45 - m_ServerSideClientPlayer.transform.rotation.eulerAngles.x), 0.05f, $"wrong rotation on ghost on x, got {m_ServerSideClientPlayer.transform.rotation.eulerAngles.x}"); + Assert.LessOrEqual(Math.Abs(40 - m_ServerSideClientPlayer.transform.rotation.eulerAngles.y), 0.05f, $"wrong rotation on ghost on y, got {m_ServerSideClientPlayer.transform.rotation.eulerAngles.y}"); + Assert.LessOrEqual(Math.Abs(35 - m_ServerSideClientPlayer.transform.rotation.eulerAngles.z), 0.05f, $"wrong rotation on ghost on z, got {m_ServerSideClientPlayer.transform.rotation.eulerAngles.z}"); + + // test scale + UnityEngine.Assertions.Assert.AreApproximatelyEqual(1f, m_ServerSideClientPlayer.transform.lossyScale.x, "wrong initial value for scale"); // sanity check + UnityEngine.Assertions.Assert.AreApproximatelyEqual(1f, m_ServerSideClientPlayer.transform.lossyScale.y, "wrong initial value for scale"); // sanity check + UnityEngine.Assertions.Assert.AreApproximatelyEqual(1f, m_ServerSideClientPlayer.transform.lossyScale.z, "wrong initial value for scale"); // sanity check + playerTransform.localScale = new Vector3(2, 3, 4); + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => m_ServerSideClientPlayer.transform.lossyScale.x > 1f )); + + UnityEngine.Assertions.Assert.AreApproximatelyEqual(2f, m_ServerSideClientPlayer.transform.lossyScale.x, "wrong scale on ghost"); // sanity check + UnityEngine.Assertions.Assert.AreApproximatelyEqual(3f, m_ServerSideClientPlayer.transform.lossyScale.y, "wrong scale on ghost"); // sanity check + UnityEngine.Assertions.Assert.AreApproximatelyEqual(4f, m_ServerSideClientPlayer.transform.lossyScale.z, "wrong scale on ghost"); // sanity check + + // test can't change transform with wrong authority + // todo reparent and test + // todo add tests for authority + // todo test all public API + // test pos and rot change at once + // test with server vs with host + } + + [UnityTest] + public IEnumerator TestCantChangeClientAuthority() + { + // test server can't change client authoritative transform + var clientNetworkTransform = m_ClientSideClientPlayer.GetComponent(); + clientNetworkTransform.TransformAuthority = NetworkTransform.Authority.Client; + + var serverNetworkTransform = m_ServerSideClientPlayer.GetComponent(); + serverNetworkTransform.TransformAuthority = NetworkTransform.Authority.Client; + Assert.AreEqual(Vector3.zero, serverNetworkTransform.transform.position, "server side pos should be zero at first"); // sanity check + serverNetworkTransform.transform.position = new Vector3(4, 5, 6); + + yield return new WaitForSeconds(0); // wait one frame + + LogAssert.Expect(LogType.Error, new Regex(".*authority.*")); + + } + + // [UnityTest] + // public IEnumerator TestServerAuthority() + // { + // + // } + + [UnityTearDown] + public override IEnumerator Teardown() + { + yield return base.Teardown(); + UnityEngine.Object.Destroy(m_PlayerPrefab); + } + } +} diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/com.unity.multiplayer.mlapi.runtimetests.asmdef b/com.unity.multiplayer.mlapi/Tests/Runtime/com.unity.multiplayer.mlapi.runtimetests.asmdef index efbf850de3..ce48f347d6 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/com.unity.multiplayer.mlapi.runtimetests.asmdef +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/com.unity.multiplayer.mlapi.runtimetests.asmdef @@ -1,12 +1,24 @@ { "name": "Unity.Multiplayer.MLAPI.RuntimeTests", + "rootNamespace": "", "references": [ "Unity.Multiplayer.MLAPI.Runtime", - "Unity.Multiplayer.MLAPI.Editor" - ], - "optionalUnityReferences": [ - "TestAssemblies" + "Unity.Multiplayer.MLAPI.Editor", + "UnityEngine.TestRunner", + "UnityEditor.TestRunner", + "Unity.Multiplayer.MLAPI.Prototyping" ], "includePlatforms": [], - "excludePlatforms": [] + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": true, + "precompiledReferences": [ + "nunit.framework.dll" + ], + "autoReferenced": false, + "defineConstraints": [ + "UNITY_INCLUDE_TESTS" + ], + "versionDefines": [], + "noEngineReferences": false } \ No newline at end of file From 923b49c92a1ce8c3541fc28b443aa746c8efa9ad Mon Sep 17 00:00:00 2001 From: Samuel Bellomo Date: Fri, 21 May 2021 18:23:47 -0400 Subject: [PATCH 03/16] authority tests work --- .../Prototyping/NetworkTransform.cs | 33 ++++++++++++------- .../Tests/Runtime/NetworkTransformTests.cs | 28 ++++++++-------- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs b/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs index 90fb8f6783..59099bbd44 100644 --- a/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs +++ b/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs @@ -116,19 +116,28 @@ public void SetAuthority(Authority newAuthority) private void UpdateVarPermissions() { - if (TransformAuthority == Authority.Client) + switch (TransformAuthority) { - m_NetworkPosition.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; - m_NetworkRotation.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; - m_NetworkWorldScale.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; - m_UseLocal.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; - } - else if (TransformAuthority == Authority.Shared) - { - m_NetworkPosition.Settings.WritePermission = NetworkVariablePermission.Everyone; - m_NetworkRotation.Settings.WritePermission = NetworkVariablePermission.Everyone; - m_NetworkWorldScale.Settings.WritePermission = NetworkVariablePermission.Everyone; - m_UseLocal.Settings.WritePermission = NetworkVariablePermission.Everyone; + case Authority.Client: + m_NetworkPosition.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; + m_NetworkRotation.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; + m_NetworkWorldScale.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; + m_UseLocal.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; + break; + case Authority.Shared: + m_NetworkPosition.Settings.WritePermission = NetworkVariablePermission.Everyone; + m_NetworkRotation.Settings.WritePermission = NetworkVariablePermission.Everyone; + m_NetworkWorldScale.Settings.WritePermission = NetworkVariablePermission.Everyone; + m_UseLocal.Settings.WritePermission = NetworkVariablePermission.Everyone; + break; + case Authority.Server: + m_NetworkPosition.Settings.WritePermission = NetworkVariablePermission.ServerOnly; + m_NetworkRotation.Settings.WritePermission = NetworkVariablePermission.ServerOnly; + m_NetworkWorldScale.Settings.WritePermission = NetworkVariablePermission.ServerOnly; + m_UseLocal.Settings.WritePermission = NetworkVariablePermission.ServerOnly; + break; + default: + throw new NotImplementedException($"{TransformAuthority} is not handled"); } } diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs index 6548441988..5a63f0ea06 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs @@ -85,28 +85,26 @@ public IEnumerator TestClientAuthoritativeTransformChangeOneAtATime(bool useLoca } [UnityTest] - public IEnumerator TestCantChangeClientAuthority() + [TestCase(NetworkTransform.Authority.Client, ExpectedResult = null)] + [TestCase(NetworkTransform.Authority.Server, ExpectedResult = null)] + public IEnumerator TestCantChangeTransformFromOtherSideAuthority(NetworkTransform.Authority authorityToTest) { // test server can't change client authoritative transform - var clientNetworkTransform = m_ClientSideClientPlayer.GetComponent(); - clientNetworkTransform.TransformAuthority = NetworkTransform.Authority.Client; - var serverNetworkTransform = m_ServerSideClientPlayer.GetComponent(); - serverNetworkTransform.TransformAuthority = NetworkTransform.Authority.Client; - Assert.AreEqual(Vector3.zero, serverNetworkTransform.transform.position, "server side pos should be zero at first"); // sanity check - serverNetworkTransform.transform.position = new Vector3(4, 5, 6); + var networkTransform = (authorityToTest == NetworkTransform.Authority.Client ? m_ClientSideClientPlayer : m_ServerSideClientPlayer).GetComponent(); + networkTransform.SetAuthority(authorityToTest); - yield return new WaitForSeconds(0); // wait one frame + var otherSideNetworkTransform = (authorityToTest == NetworkTransform.Authority.Client ? m_ServerSideClientPlayer : m_ClientSideClientPlayer).GetComponent(); + otherSideNetworkTransform.SetAuthority(authorityToTest); - LogAssert.Expect(LogType.Error, new Regex(".*authority.*")); + Assert.AreEqual(Vector3.zero, otherSideNetworkTransform.transform.position, "other side pos should be zero at first"); // sanity check + otherSideNetworkTransform.transform.position = new Vector3(4, 5, 6); - } + yield return new WaitForFixedUpdate(); // wait one frame - // [UnityTest] - // public IEnumerator TestServerAuthority() - // { - // - // } + LogAssert.Expect(LogType.Error, new Regex(".*authority.*")); + Assert.AreEqual(Vector3.zero, otherSideNetworkTransform.transform.position, "got authority error, but other side still moved!"); + } [UnityTearDown] public override IEnumerator Teardown() From 3a43905775e194174c1990835c396d8739bfde12 Mon Sep 17 00:00:00 2001 From: Samuel Bellomo Date: Fri, 21 May 2021 18:29:07 -0400 Subject: [PATCH 04/16] adding server vs client authority tests --- .../Tests/Runtime/NetworkTransformTests.cs | 65 ++++++++++--------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs index 5a63f0ea06..be54a06548 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs @@ -5,6 +5,7 @@ using NUnit.Framework; using UnityEngine; using UnityEngine.TestTools; +using static MLAPI.Prototyping.NetworkTransform; namespace MLAPI.RuntimeTests { @@ -36,65 +37,65 @@ public class NetworkTransformTests : BaseMultiInstanceTest } [UnityTest] - [TestCase(true, ExpectedResult = null)] - [TestCase(false, ExpectedResult = null)] - public IEnumerator TestClientAuthoritativeTransformChangeOneAtATime(bool useLocal) + [TestCase(true, Authority.Client, ExpectedResult = null)] + [TestCase(true, Authority.Server, ExpectedResult = null)] + [TestCase(false, Authority.Client, ExpectedResult = null)] + [TestCase(false, Authority.Server, ExpectedResult = null)] + public IEnumerator TestClientAuthoritativeTransformChangeOneAtATime(bool useLocal, Authority authorityToTest) { - var clientNetworkTransform = m_ClientSideClientPlayer.GetComponent(); - clientNetworkTransform.UseLocal = useLocal; - clientNetworkTransform.SetAuthority(NetworkTransform.Authority.Client); + var networkTransform = (authorityToTest == Authority.Client ? m_ClientSideClientPlayer : m_ServerSideClientPlayer).GetComponent(); + networkTransform.UseLocal = useLocal; + networkTransform.SetAuthority(authorityToTest); - var serverNetworkTransform = m_ServerSideClientPlayer.GetComponent(); - serverNetworkTransform.UseLocal = useLocal; - serverNetworkTransform.SetAuthority(NetworkTransform.Authority.Client); + var otherSideNetworkTransform = (authorityToTest == Authority.Client ? m_ServerSideClientPlayer : m_ClientSideClientPlayer).GetComponent(); + otherSideNetworkTransform.UseLocal = useLocal; + otherSideNetworkTransform.SetAuthority(authorityToTest); // test position - var playerTransform = m_ClientSideClientPlayer.transform; + var playerTransform = networkTransform.transform; playerTransform.position = new Vector3(10, 20, 30); - Assert.AreEqual(Vector3.zero, m_ServerSideClientPlayer.transform.position, "server side pos should be zero at first"); // sanity check - yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => m_ServerSideClientPlayer.transform.position.x != 0 )); + Assert.AreEqual(Vector3.zero, otherSideNetworkTransform.transform.position, "server side pos should be zero at first"); // sanity check + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => otherSideNetworkTransform.transform.position.x != 0 )); - Assert.AreEqual(new Vector3(10, 20, 30), m_ServerSideClientPlayer.transform.position, "wrong position on ghost"); + Assert.AreEqual(new Vector3(10, 20, 30), otherSideNetworkTransform.transform.position, "wrong position on ghost"); // test rotation playerTransform.rotation = Quaternion.Euler(45, 40, 35); - Assert.AreEqual(Quaternion.identity, m_ServerSideClientPlayer.transform.rotation, "wrong initial value for rotation"); // sanity check - yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => m_ServerSideClientPlayer.transform.rotation.eulerAngles.x != 0 )); + Assert.AreEqual(Quaternion.identity, otherSideNetworkTransform.transform.rotation, "wrong initial value for rotation"); // sanity check + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => otherSideNetworkTransform.transform.rotation.eulerAngles.x != 0 )); - Assert.LessOrEqual(Math.Abs(45 - m_ServerSideClientPlayer.transform.rotation.eulerAngles.x), 0.05f, $"wrong rotation on ghost on x, got {m_ServerSideClientPlayer.transform.rotation.eulerAngles.x}"); - Assert.LessOrEqual(Math.Abs(40 - m_ServerSideClientPlayer.transform.rotation.eulerAngles.y), 0.05f, $"wrong rotation on ghost on y, got {m_ServerSideClientPlayer.transform.rotation.eulerAngles.y}"); - Assert.LessOrEqual(Math.Abs(35 - m_ServerSideClientPlayer.transform.rotation.eulerAngles.z), 0.05f, $"wrong rotation on ghost on z, got {m_ServerSideClientPlayer.transform.rotation.eulerAngles.z}"); + Assert.LessOrEqual(Math.Abs(45 - otherSideNetworkTransform.transform.rotation.eulerAngles.x), 0.05f, $"wrong rotation on ghost on x, got {otherSideNetworkTransform.transform.rotation.eulerAngles.x}"); + Assert.LessOrEqual(Math.Abs(40 - otherSideNetworkTransform.transform.rotation.eulerAngles.y), 0.05f, $"wrong rotation on ghost on y, got {otherSideNetworkTransform.transform.rotation.eulerAngles.y}"); + Assert.LessOrEqual(Math.Abs(35 - otherSideNetworkTransform.transform.rotation.eulerAngles.z), 0.05f, $"wrong rotation on ghost on z, got {otherSideNetworkTransform.transform.rotation.eulerAngles.z}"); // test scale - UnityEngine.Assertions.Assert.AreApproximatelyEqual(1f, m_ServerSideClientPlayer.transform.lossyScale.x, "wrong initial value for scale"); // sanity check - UnityEngine.Assertions.Assert.AreApproximatelyEqual(1f, m_ServerSideClientPlayer.transform.lossyScale.y, "wrong initial value for scale"); // sanity check - UnityEngine.Assertions.Assert.AreApproximatelyEqual(1f, m_ServerSideClientPlayer.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 playerTransform.localScale = new Vector3(2, 3, 4); - yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => m_ServerSideClientPlayer.transform.lossyScale.x > 1f )); + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => otherSideNetworkTransform.transform.lossyScale.x > 1f )); - UnityEngine.Assertions.Assert.AreApproximatelyEqual(2f, m_ServerSideClientPlayer.transform.lossyScale.x, "wrong scale on ghost"); // sanity check - UnityEngine.Assertions.Assert.AreApproximatelyEqual(3f, m_ServerSideClientPlayer.transform.lossyScale.y, "wrong scale on ghost"); // sanity check - UnityEngine.Assertions.Assert.AreApproximatelyEqual(4f, m_ServerSideClientPlayer.transform.lossyScale.z, "wrong scale on ghost"); // sanity check + UnityEngine.Assertions.Assert.AreApproximatelyEqual(2f, otherSideNetworkTransform.transform.lossyScale.x, "wrong scale on ghost"); // sanity check + UnityEngine.Assertions.Assert.AreApproximatelyEqual(3f, otherSideNetworkTransform.transform.lossyScale.y, "wrong scale on ghost"); // sanity check + UnityEngine.Assertions.Assert.AreApproximatelyEqual(4f, otherSideNetworkTransform.transform.lossyScale.z, "wrong scale on ghost"); // sanity check - // test can't change transform with wrong authority // todo reparent and test - // todo add tests for authority // todo test all public API // test pos and rot change at once // test with server vs with host } [UnityTest] - [TestCase(NetworkTransform.Authority.Client, ExpectedResult = null)] - [TestCase(NetworkTransform.Authority.Server, ExpectedResult = null)] - public IEnumerator TestCantChangeTransformFromOtherSideAuthority(NetworkTransform.Authority authorityToTest) + [TestCase(Authority.Client, ExpectedResult = null)] + [TestCase(Authority.Server, ExpectedResult = null)] + public IEnumerator TestCantChangeTransformFromOtherSideAuthority(Authority authorityToTest) { // test server can't change client authoritative transform - var networkTransform = (authorityToTest == NetworkTransform.Authority.Client ? m_ClientSideClientPlayer : m_ServerSideClientPlayer).GetComponent(); + var networkTransform = (authorityToTest == Authority.Client ? m_ClientSideClientPlayer : m_ServerSideClientPlayer).GetComponent(); networkTransform.SetAuthority(authorityToTest); - var otherSideNetworkTransform = (authorityToTest == NetworkTransform.Authority.Client ? m_ServerSideClientPlayer : m_ClientSideClientPlayer).GetComponent(); + var otherSideNetworkTransform = (authorityToTest == Authority.Client ? m_ServerSideClientPlayer : m_ClientSideClientPlayer).GetComponent(); otherSideNetworkTransform.SetAuthority(authorityToTest); Assert.AreEqual(Vector3.zero, otherSideNetworkTransform.transform.position, "other side pos should be zero at first"); // sanity check From 794ca2f925f1c1747c9677a2169c667de0037671 Mon Sep 17 00:00:00 2001 From: Samuel Bellomo Date: Fri, 21 May 2021 18:48:04 -0400 Subject: [PATCH 05/16] wip --- .../Runtime/MultiInstance/BaseMultiInstanceTest.cs | 6 +++--- .../Tests/Runtime/NetworkTransformTests.cs | 11 ++++++++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs index 0b4847aff4..1c1aef0dca 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs @@ -43,7 +43,7 @@ public virtual IEnumerator Teardown() /// /// Update the prefab with whatever is needed before players spawn /// - public IEnumerator StartSomeClientAndServer(int nbClients, Action updatePlayerPrefab) + public IEnumerator StartSomeClientAndServer(bool useHost, int nbClients, Action updatePlayerPrefab) { // Create multiple NetworkManager instances if (!MultiInstanceHelpers.Create(nbClients, out NetworkManager server, out NetworkManager[] clients)) @@ -73,7 +73,7 @@ public IEnumerator StartSomeClientAndServer(int nbClients, Action up } // Start the instances - if (!MultiInstanceHelpers.Start(true, server, clients)) + if (!MultiInstanceHelpers.Start(useHost, server, clients)) { Debug.LogError("Failed to start instances"); Assert.Fail("Failed to start instances"); @@ -86,7 +86,7 @@ public IEnumerator StartSomeClientAndServer(int nbClients, Action up } // Wait for connection on server side - yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnectedToServer(server, clientCount: nbClients+1)); + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnectedToServer(server, clientCount: useHost ? nbClients+1 : nbClients)); } } } diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs index be54a06548..28c8a75053 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs @@ -9,17 +9,26 @@ namespace MLAPI.RuntimeTests { + [TestFixture(true)] + [TestFixture(false)] public class NetworkTransformTests : BaseMultiInstanceTest { private NetworkObject m_ClientSideClientPlayer; private NetworkObject m_ServerSideClientPlayer; + private bool m_TestWithHost; + + public NetworkTransformTests(bool testWithHost) + { + m_TestWithHost = testWithHost; + } + [UnitySetUp] public new IEnumerator Setup() { base.Setup(); - yield return StartSomeClientAndServer(nbClients: 1, updatePlayerPrefab: playerPrefab => + yield return StartSomeClientAndServer(useHost: m_TestWithHost, nbClients: 1, updatePlayerPrefab: playerPrefab => { var networkTransform = playerPrefab.AddComponent(); }); From 914bb35766814f0aca54cc8adb8e20b807401639 Mon Sep 17 00:00:00 2001 From: Samuel Bellomo Date: Fri, 28 May 2021 19:46:37 -0400 Subject: [PATCH 06/16] Fixing issue where NetworkBehaviour had static attributes, making net var tests flaky for multi instance tests. Moving Behaviour update to it's own updater class. NetworkTransformTests now work consistently adding InitTestScene to gitignore, they are generated by test runner and can remain uncleaned if test crash before cleanup --- .../Runtime/Core/NetworkBehaviour.cs | 85 ----------------- .../Runtime/Core/NetworkBehaviourUpdater.cs | 93 +++++++++++++++++++ .../Core/NetworkBehaviourUpdater.cs.meta | 3 + .../Runtime/Core/NetworkManager.cs | 12 ++- .../MultiInstance/MultiInstanceHelpers.cs | 2 +- .../Tests/Runtime/NetworkTransformTests.cs | 61 ++++++++---- testproject/.gitignore | 2 + 7 files changed, 152 insertions(+), 106 deletions(-) create mode 100644 com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs create mode 100644 com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs.meta diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviour.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviour.cs index f1638fb95d..b3b2effb3c 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviour.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviour.cs @@ -14,9 +14,7 @@ using MLAPI.Reflection; using MLAPI.Serialization; using MLAPI.Serialization.Pooled; -using MLAPI.Spawning; using MLAPI.Transports; -using Unity.Profiling; namespace MLAPI { @@ -344,11 +342,6 @@ protected NetworkBehaviour GetNetworkBehaviour(ushort behaviourId) internal bool NetworkStartInvoked = false; internal bool InternalNetworkStartInvoked = false; - /// - /// Stores the network tick at the NetworkBehaviourUpdate time - /// This allows sending NetworkVariables not more often than once per network tick, regardless of the update rate - /// - public static ushort CurrentTick { get; private set; } /// /// Gets called when message handlers are ready to be registered and the network is setup @@ -385,7 +378,6 @@ public virtual void OnLostOwnership() { } private readonly List m_ChannelsForNetworkVariableGroups = new List(); internal readonly List NetworkVariableFields = new List(); - private static HashSet s_Touched = new HashSet(); private static Dictionary s_FieldTypes = new Dictionary(); private static FieldInfo[] GetFieldInfoForType(Type type) @@ -474,83 +466,6 @@ internal void InitializeVariables() } } -#if DEVELOPMENT_BUILD || UNITY_EDITOR - private static ProfilerMarker s_NetworkBehaviourUpdate = new ProfilerMarker($"{nameof(NetworkBehaviour)}.{nameof(NetworkBehaviourUpdate)}"); -#endif - - internal static void NetworkBehaviourUpdate(NetworkManager networkManager) - { - // Do not execute NetworkBehaviourUpdate more than once per network tick - ushort tick = networkManager.NetworkTickSystem.GetTick(); - if (tick == CurrentTick) - { - return; - } - - CurrentTick = tick; - -#if DEVELOPMENT_BUILD || UNITY_EDITOR - s_NetworkBehaviourUpdate.Begin(); -#endif - try - { - if (networkManager.IsServer) - { - s_Touched.Clear(); - for (int i = 0; i < networkManager.ConnectedClientsList.Count; i++) - { - var client = networkManager.ConnectedClientsList[i]; - var spawnedObjs = networkManager.SpawnManager.SpawnedObjectsList; - s_Touched.UnionWith(spawnedObjs); - foreach (var sobj in spawnedObjs) - { - // Sync just the variables for just the objects this client sees - for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) - { - sobj.ChildNetworkBehaviours[k].VariableUpdate(client.ClientId); - } - } - } - - // Now, reset all the no-longer-dirty variables - foreach (var sobj in s_Touched) - { - for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) - { - sobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite(); - } - } - } - else - { - // when client updates the sever, it tells it about all its objects - foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList) - { - for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) - { - sobj.ChildNetworkBehaviours[k].VariableUpdate(networkManager.ServerClientId); - } - } - - // Now, reset all the no-longer-dirty variables - foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList) - { - for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) - { - sobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite(); - } - } - } - } - finally - { -#if DEVELOPMENT_BUILD || UNITY_EDITOR - s_NetworkBehaviourUpdate.End(); -#endif - } - } - - internal void PreNetworkVariableWrite() { // reset our "which variables got written" data diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs new file mode 100644 index 0000000000..10a18d087a --- /dev/null +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs @@ -0,0 +1,93 @@ +using System.Collections.Generic; +using Unity.Profiling; + +namespace MLAPI +{ + public class NetworkBehaviourUpdater + { + private HashSet m_Touched = new HashSet(); + + /// + /// Stores the network tick at the NetworkBehaviourUpdate time + /// This allows sending NetworkVariables not more often than once per network tick, regardless of the update rate + /// + public ushort CurrentTick { get; set; } + +#if DEVELOPMENT_BUILD || UNITY_EDITOR + private ProfilerMarker s_NetworkBehaviourUpdate = new ProfilerMarker($"{nameof(NetworkBehaviour)}.{nameof(NetworkBehaviourUpdate)}"); +#endif + + internal void NetworkBehaviourUpdate(NetworkManager networkManager) + { + // Do not execute NetworkBehaviourUpdate more than once per network tick + ushort tick = networkManager.NetworkTickSystem.GetTick(); + if (tick == CurrentTick) + { + return; + } + + CurrentTick = tick; + +#if DEVELOPMENT_BUILD || UNITY_EDITOR + s_NetworkBehaviourUpdate.Begin(); +#endif + try + { + if (networkManager.IsServer) + { + m_Touched.Clear(); + for (int i = 0; i < networkManager.ConnectedClientsList.Count; i++) + { + var client = networkManager.ConnectedClientsList[i]; + var spawnedObjs = networkManager.SpawnManager.SpawnedObjectsList; + m_Touched.UnionWith(spawnedObjs); + foreach (var sobj in spawnedObjs) + { + // Sync just the variables for just the objects this client sees + for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) + { + sobj.ChildNetworkBehaviours[k].VariableUpdate(client.ClientId); + } + } + } + + // Now, reset all the no-longer-dirty variables + foreach (var sobj in m_Touched) + { + for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) + { + sobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite(); + } + } + } + else + { + // when client updates the server, it tells it about all its objects + foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList) + { + for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) + { + sobj.ChildNetworkBehaviours[k].VariableUpdate(networkManager.ServerClientId); + } + } + + // Now, reset all the no-longer-dirty variables + foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList) + { + for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) + { + sobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite(); + } + } + } + } + finally + { +#if DEVELOPMENT_BUILD || UNITY_EDITOR + s_NetworkBehaviourUpdate.End(); +#endif + } + } + + } +} diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs.meta b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs.meta new file mode 100644 index 0000000000..df9f980dac --- /dev/null +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d084c01093b446878bcb76e5d7f3221e +timeCreated: 1622225163 \ No newline at end of file diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs index 0eac75309d..2363414ca8 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs @@ -61,6 +61,7 @@ public class NetworkManager : MonoBehaviour, INetworkUpdateSystem, IProfilableTr internal NetworkTickSystem NetworkTickSystem { get; private set; } internal SnapshotSystem SnapshotSystem { get; private set; } + internal NetworkBehaviourUpdater BehaviourUpdater { get; private set; } private NetworkPrefabHandler m_PrefabHandler; public NetworkPrefabHandler PrefabHandler @@ -128,7 +129,7 @@ public NetworkPrefabHandler PrefabHandler public ulong ServerClientId => NetworkConfig.NetworkTransport?.ServerClientId ?? throw new NullReferenceException($"The transport in the active {nameof(NetworkConfig)} is null"); /// - /// The clientId the server calls the local client by, only valid for clients + /// Returns ServerClientId if IsServer or LocalClientId if IsClient /// public ulong LocalClientId { @@ -343,6 +344,8 @@ private void Init(bool server) SceneManager = new NetworkSceneManager(this); + BehaviourUpdater = new NetworkBehaviourUpdater(); + if (MessageHandler == null) { // Only create this if it's not already set (like in test cases) @@ -842,6 +845,11 @@ public void Shutdown() CustomMessagingManager = null; } + if (BehaviourUpdater != null) + { + BehaviourUpdater = null; + } + //The Transport is set during Init time, thus it is possible for the Transport to be null NetworkConfig?.NetworkTransport?.Shutdown(); } @@ -929,7 +937,7 @@ private void OnNetworkPreUpdate() if (NetworkConfig.EnableNetworkVariable) { // Do NetworkVariable updates - NetworkBehaviour.NetworkBehaviourUpdate(this); + BehaviourUpdater.NetworkBehaviourUpdate(this); } if (!IsServer && NetworkConfig.EnableMessageBuffering) diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/MultiInstanceHelpers.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/MultiInstanceHelpers.cs index 570474d34a..f835c0b5ce 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/MultiInstanceHelpers.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/MultiInstanceHelpers.cs @@ -156,7 +156,7 @@ private class CoroutineRunner : MonoBehaviour private static CoroutineRunner s_CoroutineRunner; /// - /// Runs a IEnumerator as a Coroutine on a dummy GameObject. + /// Runs a IEnumerator as a Coroutine on a dummy GameObject. Used to get exceptions coming from the coroutine /// /// The IEnumerator to run public static Coroutine Run(IEnumerator enumerator) diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs index 28c8a75053..2beeebf7fc 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs @@ -20,7 +20,7 @@ public class NetworkTransformTests : BaseMultiInstanceTest public NetworkTransformTests(bool testWithHost) { - m_TestWithHost = testWithHost; + m_TestWithHost = testWithHost; // from test fixture } [UnitySetUp] @@ -50,48 +50,74 @@ public NetworkTransformTests(bool testWithHost) [TestCase(true, Authority.Server, ExpectedResult = null)] [TestCase(false, Authority.Client, ExpectedResult = null)] [TestCase(false, Authority.Server, ExpectedResult = null)] - public IEnumerator TestClientAuthoritativeTransformChangeOneAtATime(bool useLocal, Authority authorityToTest) + public IEnumerator TestAuthoritativeTransformChangeOneAtATime(bool testLocalTransform, Authority authorityToTest) { + var waitResult = new MultiInstanceHelpers.CoroutineResultWrapper(); + var networkTransform = (authorityToTest == Authority.Client ? m_ClientSideClientPlayer : m_ServerSideClientPlayer).GetComponent(); - networkTransform.UseLocal = useLocal; networkTransform.SetAuthority(authorityToTest); var otherSideNetworkTransform = (authorityToTest == Authority.Client ? m_ServerSideClientPlayer : m_ClientSideClientPlayer).GetComponent(); - otherSideNetworkTransform.UseLocal = useLocal; otherSideNetworkTransform.SetAuthority(authorityToTest); + bool HasAuthority(NetworkTransform transform) + { + return transform.NetworkObject.NetworkManager.IsServer && transform.TransformAuthority == Authority.Server || + transform.NetworkObject.NetworkManager.IsClient && transform.TransformAuthority == Authority.Client; + } + + if (HasAuthority(networkTransform)) + { + networkTransform.UseLocal = testLocalTransform; + } + + if (HasAuthority(otherSideNetworkTransform)) + { + otherSideNetworkTransform.UseLocal = testLocalTransform; + } + + float approximation = 0.05f; + // test position var playerTransform = networkTransform.transform; playerTransform.position = new Vector3(10, 20, 30); Assert.AreEqual(Vector3.zero, otherSideNetworkTransform.transform.position, "server side pos should be zero at first"); // sanity check - yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => otherSideNetworkTransform.transform.position.x != 0 )); - - Assert.AreEqual(new Vector3(10, 20, 30), otherSideNetworkTransform.transform.position, "wrong position on ghost"); + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => otherSideNetworkTransform.transform.position.x > approximation, waitResult, maxFrames: 30)); + if (!waitResult.Result) + { + throw new Exception("timeout while waiting for position change"); + } + 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 - playerTransform.rotation = Quaternion.Euler(45, 40, 35); + playerTransform.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 MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => otherSideNetworkTransform.transform.rotation.eulerAngles.x != 0 )); - - Assert.LessOrEqual(Math.Abs(45 - otherSideNetworkTransform.transform.rotation.eulerAngles.x), 0.05f, $"wrong rotation on ghost on x, got {otherSideNetworkTransform.transform.rotation.eulerAngles.x}"); - Assert.LessOrEqual(Math.Abs(40 - otherSideNetworkTransform.transform.rotation.eulerAngles.y), 0.05f, $"wrong rotation on ghost on y, got {otherSideNetworkTransform.transform.rotation.eulerAngles.y}"); - Assert.LessOrEqual(Math.Abs(35 - otherSideNetworkTransform.transform.rotation.eulerAngles.z), 0.05f, $"wrong rotation on ghost on z, got {otherSideNetworkTransform.transform.rotation.eulerAngles.z}"); + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => otherSideNetworkTransform.transform.rotation.eulerAngles.x > approximation, waitResult, maxFrames: 30)); + if (!waitResult.Result) + { + throw new Exception("timeout while waiting for position 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}"); // 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 playerTransform.localScale = new Vector3(2, 3, 4); - yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => otherSideNetworkTransform.transform.lossyScale.x > 1f )); - + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => otherSideNetworkTransform.transform.lossyScale.x > 1f + approximation, waitResult, maxFrames: 30)); + if (!waitResult.Result) + { + throw new Exception("timeout while waiting for position change"); + } UnityEngine.Assertions.Assert.AreApproximatelyEqual(2f, otherSideNetworkTransform.transform.lossyScale.x, "wrong scale on ghost"); // sanity check UnityEngine.Assertions.Assert.AreApproximatelyEqual(3f, otherSideNetworkTransform.transform.lossyScale.y, "wrong scale on ghost"); // sanity check UnityEngine.Assertions.Assert.AreApproximatelyEqual(4f, otherSideNetworkTransform.transform.lossyScale.z, "wrong scale on ghost"); // sanity check // todo reparent and test // todo test all public API - // test pos and rot change at once - // test with server vs with host } [UnityTest] @@ -100,7 +126,6 @@ public IEnumerator TestClientAuthoritativeTransformChangeOneAtATime(bool useLoca public IEnumerator TestCantChangeTransformFromOtherSideAuthority(Authority authorityToTest) { // test server can't change client authoritative transform - var networkTransform = (authorityToTest == Authority.Client ? m_ClientSideClientPlayer : m_ServerSideClientPlayer).GetComponent(); networkTransform.SetAuthority(authorityToTest); diff --git a/testproject/.gitignore b/testproject/.gitignore index 72c27e4fe2..acbbe841e6 100644 --- a/testproject/.gitignore +++ b/testproject/.gitignore @@ -69,3 +69,5 @@ crashlytics-build.properties # Temporary auto-generated Android Assets /[Aa]ssets/[Ss]treamingAssets/aa.meta /[Aa]ssets/[Ss]treamingAssets/aa/* + +InitTestScene* From 506e1a2ad873f9855c9d553562c9c8a80495a366 Mon Sep 17 00:00:00 2001 From: Samuel Bellomo Date: Mon, 31 May 2021 11:52:13 -0400 Subject: [PATCH 07/16] # --- .../Runtime/Core/NetworkManager.cs | 2 +- .../Tests/Runtime/NetworkTransformTests.cs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs index 2363414ca8..9eeb2f64f6 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs @@ -129,7 +129,7 @@ public NetworkPrefabHandler PrefabHandler public ulong ServerClientId => NetworkConfig.NetworkTransport?.ServerClientId ?? throw new NullReferenceException($"The transport in the active {nameof(NetworkConfig)} is null"); /// - /// Returns ServerClientId if IsServer or LocalClientId if IsClient + /// Returns ServerClientId if IsServer or LocalClientId if not /// public ulong LocalClientId { diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs index 2beeebf7fc..39e5c3a19d 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs @@ -112,9 +112,9 @@ bool HasAuthority(NetworkTransform transform) { throw new Exception("timeout while waiting for position change"); } - UnityEngine.Assertions.Assert.AreApproximatelyEqual(2f, otherSideNetworkTransform.transform.lossyScale.x, "wrong scale on ghost"); // sanity check - UnityEngine.Assertions.Assert.AreApproximatelyEqual(3f, otherSideNetworkTransform.transform.lossyScale.y, "wrong scale on ghost"); // sanity check - UnityEngine.Assertions.Assert.AreApproximatelyEqual(4f, otherSideNetworkTransform.transform.lossyScale.z, "wrong scale on ghost"); // sanity check + 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 @@ -135,9 +135,9 @@ public IEnumerator TestCantChangeTransformFromOtherSideAuthority(Authority autho Assert.AreEqual(Vector3.zero, otherSideNetworkTransform.transform.position, "other side pos should be zero at first"); // sanity check otherSideNetworkTransform.transform.position = new Vector3(4, 5, 6); - yield return new WaitForFixedUpdate(); // wait one frame + yield return new WaitForFixedUpdate(); - LogAssert.Expect(LogType.Error, new Regex(".*authority.*")); + LogAssert.Expect(LogType.Error, new Regex(".*[Aa]uthority.*")); Assert.AreEqual(Vector3.zero, otherSideNetworkTransform.transform.position, "got authority error, but other side still moved!"); } From 3436084fdcbca8284e17199f92476eb72bd192e5 Mon Sep 17 00:00:00 2001 From: Samuel Bellomo Date: Mon, 31 May 2021 11:56:29 -0400 Subject: [PATCH 08/16] revert useless changes --- ...m.unity.multiplayer.mlapi.runtimetests.asmdef | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/com.unity.multiplayer.mlapi.runtimetests.asmdef b/com.unity.multiplayer.mlapi/Tests/Runtime/com.unity.multiplayer.mlapi.runtimetests.asmdef index ce48f347d6..6bea27dff4 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/com.unity.multiplayer.mlapi.runtimetests.asmdef +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/com.unity.multiplayer.mlapi.runtimetests.asmdef @@ -1,24 +1,10 @@ { "name": "Unity.Multiplayer.MLAPI.RuntimeTests", - "rootNamespace": "", "references": [ "Unity.Multiplayer.MLAPI.Runtime", "Unity.Multiplayer.MLAPI.Editor", - "UnityEngine.TestRunner", - "UnityEditor.TestRunner", "Unity.Multiplayer.MLAPI.Prototyping" ], "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": true, - "precompiledReferences": [ - "nunit.framework.dll" - ], - "autoReferenced": false, - "defineConstraints": [ - "UNITY_INCLUDE_TESTS" - ], - "versionDefines": [], - "noEngineReferences": false + "excludePlatforms": [] } \ No newline at end of file From d4b6a24b37dbf0135ffafec38c4d96bf9d4487a4 Mon Sep 17 00:00:00 2001 From: Samuel Bellomo Date: Mon, 31 May 2021 12:00:13 -0400 Subject: [PATCH 09/16] # --- .../Runtime/com.unity.multiplayer.mlapi.runtimetests.asmdef | 3 +++ 1 file changed, 3 insertions(+) diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/com.unity.multiplayer.mlapi.runtimetests.asmdef b/com.unity.multiplayer.mlapi/Tests/Runtime/com.unity.multiplayer.mlapi.runtimetests.asmdef index 6bea27dff4..da062e7cb9 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/com.unity.multiplayer.mlapi.runtimetests.asmdef +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/com.unity.multiplayer.mlapi.runtimetests.asmdef @@ -5,6 +5,9 @@ "Unity.Multiplayer.MLAPI.Editor", "Unity.Multiplayer.MLAPI.Prototyping" ], + "optionalUnityReferences": [ + "TestAssemblies" + ], "includePlatforms": [], "excludePlatforms": [] } \ No newline at end of file From 31e95a094e7ed111ce1b9c95cbed0199457d4c05 Mon Sep 17 00:00:00 2001 From: Samuel Bellomo Date: Mon, 31 May 2021 13:01:24 -0400 Subject: [PATCH 10/16] formatting --- .../Runtime/Core/NetworkBehaviourUpdater.cs | 6 +++--- .../Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs index 10a18d087a..25e0861b8b 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs @@ -14,7 +14,7 @@ public class NetworkBehaviourUpdater public ushort CurrentTick { get; set; } #if DEVELOPMENT_BUILD || UNITY_EDITOR - private ProfilerMarker s_NetworkBehaviourUpdate = new ProfilerMarker($"{nameof(NetworkBehaviour)}.{nameof(NetworkBehaviourUpdate)}"); + private ProfilerMarker m_NetworkBehaviourUpdate = new ProfilerMarker($"{nameof(NetworkBehaviour)}.{nameof(NetworkBehaviourUpdate)}"); #endif internal void NetworkBehaviourUpdate(NetworkManager networkManager) @@ -29,7 +29,7 @@ internal void NetworkBehaviourUpdate(NetworkManager networkManager) CurrentTick = tick; #if DEVELOPMENT_BUILD || UNITY_EDITOR - s_NetworkBehaviourUpdate.Begin(); + m_NetworkBehaviourUpdate.Begin(); #endif try { @@ -84,7 +84,7 @@ internal void NetworkBehaviourUpdate(NetworkManager networkManager) finally { #if DEVELOPMENT_BUILD || UNITY_EDITOR - s_NetworkBehaviourUpdate.End(); + m_NetworkBehaviourUpdate.End(); #endif } } diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs index 1c1aef0dca..4b6d50a7fb 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs @@ -86,7 +86,7 @@ public IEnumerator StartSomeClientAndServer(bool useHost, int nbClients, Action< } // Wait for connection on server side - yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnectedToServer(server, clientCount: useHost ? nbClients+1 : nbClients)); + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnectedToServer(server, clientCount: useHost ? nbClients + 1 : nbClients)); } } } From 16069f097b1b80e754bb820a28f6837b9c93cbaa Mon Sep 17 00:00:00 2001 From: Samuel Bellomo Date: Mon, 31 May 2021 13:29:25 -0400 Subject: [PATCH 11/16] adding doc --- com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs b/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs index 59099bbd44..45d42e6b08 100644 --- a/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs +++ b/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs @@ -107,6 +107,10 @@ public bool UseLocal set => m_UseLocal.Value = value; } + /// + /// Updates the NetworkTransform's authority model at runtime. + /// + /// public void SetAuthority(Authority newAuthority) { TransformAuthority = newAuthority; From 30d38a967eaeab5a0422007ab08405465dede179 Mon Sep 17 00:00:00 2001 From: Samuel Bellomo Date: Mon, 21 Jun 2021 10:28:06 -0400 Subject: [PATCH 12/16] better comments putting base for multi instance tests as abstract --- com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs | 1 + .../Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs b/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs index 45d42e6b08..6a292449bd 100644 --- a/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs +++ b/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs @@ -97,6 +97,7 @@ public enum Authority /// /// Sets whether this transform should sync local or world properties. This is important to set since reparenting this transform /// could have issues if using world position (depending on who gets synced first: the parent or the child) + /// Having a child always at position 0,0,0 for example will have less possibilities of desync than when using world positions /// [SerializeField, Tooltip("Sets whether this transform should sync local or world properties. This should be set if reparenting.")] private NetworkVariableBool m_UseLocal = new NetworkVariableBool(); diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs index 4b6d50a7fb..d1b1577d4d 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/BaseMultiInstanceTest.cs @@ -5,7 +5,7 @@ namespace MLAPI.RuntimeTests { - public class BaseMultiInstanceTest + public abstract class BaseMultiInstanceTest { private int m_OriginalTargetFrameRate; From f0a7755a8b668fcbae3606f7fcad265885251b49 Mon Sep 17 00:00:00 2001 From: Samuel Bellomo Date: Mon, 21 Jun 2021 11:16:37 -0400 Subject: [PATCH 13/16] cleanup --- .../Prototyping/NetworkTransform.cs | 24 +++++++++---------- .../Tests/Runtime/BaseMultiInstanceTest.cs | 17 +------------ .../Tests/Runtime/NetworkTransformTests.cs | 6 ++--- 3 files changed, 14 insertions(+), 33 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs b/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs index 4f044ebc8f..f856da1db5 100644 --- a/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs +++ b/com.unity.multiplayer.mlapi/Prototyping/NetworkTransform.cs @@ -111,37 +111,35 @@ public void SetAuthority(Authority newAuthority) // todo this should be synced with the other side. let's wait for a more final solution before adding more code here } - private void UpdateVarPermissions() + private void UpdateOneVarPermission(NetworkVariable varToUpdate) { switch (TransformAuthority) { case Authority.Client: - m_NetworkPosition.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; - m_NetworkRotation.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; - m_NetworkWorldScale.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; - m_UseLocal.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; + varToUpdate.Settings.WritePermission = NetworkVariablePermission.OwnerOnly; break; case Authority.Shared: - m_NetworkPosition.Settings.WritePermission = NetworkVariablePermission.Everyone; - m_NetworkRotation.Settings.WritePermission = NetworkVariablePermission.Everyone; - m_NetworkWorldScale.Settings.WritePermission = NetworkVariablePermission.Everyone; - m_UseLocal.Settings.WritePermission = NetworkVariablePermission.Everyone; + varToUpdate.Settings.WritePermission = NetworkVariablePermission.Everyone; break; case Authority.Server: m_NetworkPosition.Settings.WritePermission = NetworkVariablePermission.ServerOnly; - m_NetworkRotation.Settings.WritePermission = NetworkVariablePermission.ServerOnly; - m_NetworkWorldScale.Settings.WritePermission = NetworkVariablePermission.ServerOnly; - m_UseLocal.Settings.WritePermission = NetworkVariablePermission.ServerOnly; break; default: throw new NotImplementedException($"{TransformAuthority} is not handled"); } } + private void UpdateVarPermissions() + { + UpdateOneVarPermission(m_NetworkPosition); + UpdateOneVarPermission(m_NetworkRotation); + UpdateOneVarPermission(m_NetworkWorldScale); + UpdateOneVarPermission(m_UseLocal); + } + private NetworkVariableVector3 m_NetworkPosition = new NetworkVariableVector3(); private NetworkVariableQuaternion m_NetworkRotation = new NetworkVariableQuaternion(); private NetworkVariableVector3 m_NetworkWorldScale = new NetworkVariableVector3(); - // private NetworkTransform m_NetworkParent; // TODO handle this here? private Transform m_Transform; diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/BaseMultiInstanceTest.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/BaseMultiInstanceTest.cs index d1b1577d4d..20909236d7 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/BaseMultiInstanceTest.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/BaseMultiInstanceTest.cs @@ -14,26 +14,11 @@ public abstract class BaseMultiInstanceTest protected NetworkManager m_ServerNetworkManager; protected NetworkManager[] m_ClientNetworkManagers; - public virtual void Setup() - { - // Just always track the current target frame rate (will be re-applied upon TearDown) - m_OriginalTargetFrameRate = Application.targetFrameRate; - - // Since we use frame count as a metric, we need to assure it runs at a "common update rate" - // between platforms (i.e. Ubuntu seems to run at much higher FPS when set to -1) - if (Application.targetFrameRate < 0 || Application.targetFrameRate > 120) - { - Application.targetFrameRate = 120; - } - } - public virtual IEnumerator Teardown() { // Shutdown and clean up both of our NetworkManager instances MultiInstanceHelpers.Destroy(); - // Set the application's target frame rate back to its original value - Application.targetFrameRate = m_OriginalTargetFrameRate; yield return new WaitForSeconds(0); // wait for next frame so everything is destroyed, so following tests can execute from clean environment } @@ -43,7 +28,7 @@ public virtual IEnumerator Teardown() /// /// Update the prefab with whatever is needed before players spawn /// - public IEnumerator StartSomeClientAndServer(bool useHost, int nbClients, Action updatePlayerPrefab) + public IEnumerator StartSomeClientsAndServer(bool useHost, int nbClients, Action updatePlayerPrefab) { // Create multiple NetworkManager instances if (!MultiInstanceHelpers.Create(nbClients, out NetworkManager server, out NetworkManager[] clients)) diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs index 39e5c3a19d..afb7b55659 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs @@ -24,11 +24,9 @@ public NetworkTransformTests(bool testWithHost) } [UnitySetUp] - public new IEnumerator Setup() + public IEnumerator Setup() { - base.Setup(); - - yield return StartSomeClientAndServer(useHost: m_TestWithHost, nbClients: 1, updatePlayerPrefab: playerPrefab => + yield return StartSomeClientsAndServer(useHost: m_TestWithHost, nbClients: 1, updatePlayerPrefab: playerPrefab => { var networkTransform = playerPrefab.AddComponent(); }); From d134e89ed243a940de41afd99b590f2733f58f04 Mon Sep 17 00:00:00 2001 From: Samuel Bellomo Date: Mon, 21 Jun 2021 13:16:13 -0400 Subject: [PATCH 14/16] reverting change to move to a separate PR --- .../Runtime/Core/NetworkBehaviour.cs | 84 +++++++++++++++++ .../Runtime/Core/NetworkBehaviourUpdater.cs | 93 ------------------- .../Core/NetworkBehaviourUpdater.cs.meta | 3 - .../Runtime/Core/NetworkManager.cs | 10 +- 4 files changed, 85 insertions(+), 105 deletions(-) delete mode 100644 com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs delete mode 100644 com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs.meta diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviour.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviour.cs index a250e4a64e..6742e69330 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviour.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviour.cs @@ -13,6 +13,7 @@ using MLAPI.Serialization; using MLAPI.Serialization.Pooled; using MLAPI.Transports; +using Unity.Profiling; namespace MLAPI { @@ -296,6 +297,11 @@ protected NetworkBehaviour GetNetworkBehaviour(ushort behaviourId) /// public ulong OwnerClientId => NetworkObject.OwnerClientId; + /// + /// Stores the network tick at the NetworkBehaviourUpdate time + /// This allows sending NetworkVariables not more often than once per network tick, regardless of the update rate + /// + public static ushort CurrentTick { get; private set; } /// /// Gets called when message handlers are ready to be registered and the network is setup @@ -347,6 +353,7 @@ public virtual void OnNetworkObjectParentChanged(NetworkObject parentNetworkObje private readonly List m_ChannelsForNetworkVariableGroups = new List(); internal readonly List NetworkVariableFields = new List(); + private static HashSet s_Touched = new HashSet(); private static Dictionary s_FieldTypes = new Dictionary(); private static FieldInfo[] GetFieldInfoForType(Type type) @@ -439,6 +446,83 @@ internal void InitializeVariables() } } +#if DEVELOPMENT_BUILD || UNITY_EDITOR + private static ProfilerMarker s_NetworkBehaviourUpdate = new ProfilerMarker($"{nameof(NetworkBehaviour)}.{nameof(NetworkBehaviourUpdate)}"); +#endif + + internal static void NetworkBehaviourUpdate(NetworkManager networkManager) + { + // Do not execute NetworkBehaviourUpdate more than once per network tick + ushort tick = networkManager.NetworkTickSystem.GetTick(); + if (tick == CurrentTick) + { + return; + } + + CurrentTick = tick; + +#if DEVELOPMENT_BUILD || UNITY_EDITOR + s_NetworkBehaviourUpdate.Begin(); +#endif + try + { + if (networkManager.IsServer) + { + s_Touched.Clear(); + for (int i = 0; i < networkManager.ConnectedClientsList.Count; i++) + { + var client = networkManager.ConnectedClientsList[i]; + var spawnedObjs = networkManager.SpawnManager.SpawnedObjectsList; + s_Touched.UnionWith(spawnedObjs); + foreach (var sobj in spawnedObjs) + { + // Sync just the variables for just the objects this client sees + for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) + { + sobj.ChildNetworkBehaviours[k].VariableUpdate(client.ClientId); + } + } + } + + // Now, reset all the no-longer-dirty variables + foreach (var sobj in s_Touched) + { + for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) + { + sobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite(); + } + } + } + else + { + // when client updates the sever, it tells it about all its objects + foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList) + { + for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) + { + sobj.ChildNetworkBehaviours[k].VariableUpdate(networkManager.ServerClientId); + } + } + + // Now, reset all the no-longer-dirty variables + foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList) + { + for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) + { + sobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite(); + } + } + } + } + finally + { +#if DEVELOPMENT_BUILD || UNITY_EDITOR + s_NetworkBehaviourUpdate.End(); +#endif + } + } + + internal void PreNetworkVariableWrite() { // reset our "which variables got written" data diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs deleted file mode 100644 index 25e0861b8b..0000000000 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Collections.Generic; -using Unity.Profiling; - -namespace MLAPI -{ - public class NetworkBehaviourUpdater - { - private HashSet m_Touched = new HashSet(); - - /// - /// Stores the network tick at the NetworkBehaviourUpdate time - /// This allows sending NetworkVariables not more often than once per network tick, regardless of the update rate - /// - public ushort CurrentTick { get; set; } - -#if DEVELOPMENT_BUILD || UNITY_EDITOR - private ProfilerMarker m_NetworkBehaviourUpdate = new ProfilerMarker($"{nameof(NetworkBehaviour)}.{nameof(NetworkBehaviourUpdate)}"); -#endif - - internal void NetworkBehaviourUpdate(NetworkManager networkManager) - { - // Do not execute NetworkBehaviourUpdate more than once per network tick - ushort tick = networkManager.NetworkTickSystem.GetTick(); - if (tick == CurrentTick) - { - return; - } - - CurrentTick = tick; - -#if DEVELOPMENT_BUILD || UNITY_EDITOR - m_NetworkBehaviourUpdate.Begin(); -#endif - try - { - if (networkManager.IsServer) - { - m_Touched.Clear(); - for (int i = 0; i < networkManager.ConnectedClientsList.Count; i++) - { - var client = networkManager.ConnectedClientsList[i]; - var spawnedObjs = networkManager.SpawnManager.SpawnedObjectsList; - m_Touched.UnionWith(spawnedObjs); - foreach (var sobj in spawnedObjs) - { - // Sync just the variables for just the objects this client sees - for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) - { - sobj.ChildNetworkBehaviours[k].VariableUpdate(client.ClientId); - } - } - } - - // Now, reset all the no-longer-dirty variables - foreach (var sobj in m_Touched) - { - for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) - { - sobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite(); - } - } - } - else - { - // when client updates the server, it tells it about all its objects - foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList) - { - for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) - { - sobj.ChildNetworkBehaviours[k].VariableUpdate(networkManager.ServerClientId); - } - } - - // Now, reset all the no-longer-dirty variables - foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList) - { - for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) - { - sobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite(); - } - } - } - } - finally - { -#if DEVELOPMENT_BUILD || UNITY_EDITOR - m_NetworkBehaviourUpdate.End(); -#endif - } - } - - } -} diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs.meta b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs.meta deleted file mode 100644 index df9f980dac..0000000000 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: d084c01093b446878bcb76e5d7f3221e -timeCreated: 1622225163 \ No newline at end of file diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs index ae01e294bf..6f26ebc762 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs @@ -59,7 +59,6 @@ public class NetworkManager : MonoBehaviour, INetworkUpdateSystem, IProfilableTr internal NetworkTickSystem NetworkTickSystem { get; private set; } internal SnapshotSystem SnapshotSystem { get; private set; } - internal NetworkBehaviourUpdater BehaviourUpdater { get; private set; } private NetworkPrefabHandler m_PrefabHandler; public NetworkPrefabHandler PrefabHandler @@ -349,8 +348,6 @@ private void Initialize(bool server) SceneManager = new NetworkSceneManager(this); - BehaviourUpdater = new NetworkBehaviourUpdater(); - // Only create this if it's not already set (like in test cases) MessageHandler ??= CreateMessageHandler(); @@ -847,11 +844,6 @@ public void Shutdown() CustomMessagingManager = null; } - if (BehaviourUpdater != null) - { - BehaviourUpdater = null; - } - //The Transport is set during Init time, thus it is possible for the Transport to be null NetworkConfig?.NetworkTransport?.Shutdown(); } @@ -939,7 +931,7 @@ private void OnNetworkPreUpdate() if (NetworkConfig.EnableNetworkVariable) { // Do NetworkVariable updates - BehaviourUpdater.NetworkBehaviourUpdate(this); + NetworkBehaviour.NetworkBehaviourUpdate(this); } if (!IsServer && NetworkConfig.EnableMessageBuffering) From b3d89cde452046b471ba5d019053d08d9181b329 Mon Sep 17 00:00:00 2001 From: Samuel Bellomo Date: Mon, 21 Jun 2021 13:36:39 -0400 Subject: [PATCH 15/16] moving this to a separate PR --- .../Tests/Runtime/BaseMultiInstanceTest.cs | 77 ------------------- .../Runtime/BaseMultiInstanceTest.cs.meta | 3 - 2 files changed, 80 deletions(-) delete mode 100644 com.unity.multiplayer.mlapi/Tests/Runtime/BaseMultiInstanceTest.cs delete mode 100644 com.unity.multiplayer.mlapi/Tests/Runtime/BaseMultiInstanceTest.cs.meta diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/BaseMultiInstanceTest.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/BaseMultiInstanceTest.cs deleted file mode 100644 index 20909236d7..0000000000 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/BaseMultiInstanceTest.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.Collections; -using NUnit.Framework; -using UnityEngine; - -namespace MLAPI.RuntimeTests -{ - public abstract class BaseMultiInstanceTest - { - private int m_OriginalTargetFrameRate; - - protected GameObject m_PlayerPrefab; - - protected NetworkManager m_ServerNetworkManager; - protected NetworkManager[] m_ClientNetworkManagers; - - public virtual IEnumerator Teardown() - { - // Shutdown and clean up both of our NetworkManager instances - MultiInstanceHelpers.Destroy(); - - yield return new WaitForSeconds(0); // wait for next frame so everything is destroyed, so following tests can execute from clean environment - } - - /// - /// Utility to spawn some clients and a server and set them up - /// - /// - /// Update the prefab with whatever is needed before players spawn - /// - public IEnumerator StartSomeClientsAndServer(bool useHost, int nbClients, Action updatePlayerPrefab) - { - // Create multiple NetworkManager instances - if (!MultiInstanceHelpers.Create(nbClients, out NetworkManager server, out NetworkManager[] clients)) - { - Debug.LogError("Failed to create instances"); - Assert.Fail("Failed to create instances"); - } - - m_ClientNetworkManagers = clients; - m_ServerNetworkManager = server; - - // Create playerPrefab - m_PlayerPrefab = new GameObject("Player"); - NetworkObject networkObject = m_PlayerPrefab.AddComponent(); - - // Make it a prefab - MultiInstanceHelpers.MakeNetworkedObjectTestPrefab(networkObject); - - updatePlayerPrefab(m_PlayerPrefab); // update player prefab with whatever is needed before players are spawned - - // Set the player prefab - server.NetworkConfig.PlayerPrefab = m_PlayerPrefab; - - for (int i = 0; i < clients.Length; i++) - { - clients[i].NetworkConfig.PlayerPrefab = m_PlayerPrefab; - } - - // Start the instances - if (!MultiInstanceHelpers.Start(useHost, server, clients)) - { - Debug.LogError("Failed to start instances"); - Assert.Fail("Failed to start instances"); - } - - // Wait for connection on client side - for (int i = 0; i < clients.Length; i++) - { - yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientConnected(clients[i])); - } - - // Wait for connection on server side - yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnectedToServer(server, clientCount: useHost ? nbClients + 1 : nbClients)); - } - } -} diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/BaseMultiInstanceTest.cs.meta b/com.unity.multiplayer.mlapi/Tests/Runtime/BaseMultiInstanceTest.cs.meta deleted file mode 100644 index 94eb21978a..0000000000 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/BaseMultiInstanceTest.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 789a3189410645aca48f11a51c823418 -timeCreated: 1621620979 \ No newline at end of file From ac53d385d303678472e0f74b1c661dc5ce712b5d Mon Sep 17 00:00:00 2001 From: Samuel Bellomo Date: Mon, 21 Jun 2021 15:57:37 -0400 Subject: [PATCH 16/16] updating for base changes --- .../Tests/Runtime/NetworkTransformTests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs index afb7b55659..9d1fa450d9 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkTransformTests.cs @@ -23,10 +23,12 @@ public NetworkTransformTests(bool testWithHost) m_TestWithHost = testWithHost; // from test fixture } + protected override int NbClients => 1; + [UnitySetUp] - public IEnumerator Setup() + public override IEnumerator Setup() { - yield return StartSomeClientsAndServer(useHost: m_TestWithHost, nbClients: 1, updatePlayerPrefab: playerPrefab => + yield return StartSomeClientsAndServerWithPlayers(useHost: m_TestWithHost, nbClients: NbClients, updatePlayerPrefab: playerPrefab => { var networkTransform = playerPrefab.AddComponent(); });