using System; using System.Linq; using NUnit.Framework; using Unity.Collections; using Unity.Netcode.TestHelpers.Runtime; using UnityEngine; using Quaternion = UnityEngine.Quaternion; using Vector2 = UnityEngine.Vector2; using Vector3 = UnityEngine.Vector3; using Vector4 = UnityEngine.Vector4; namespace Unity.Netcode.RuntimeTests { public class RpcTypeSerializationTests : NetcodeIntegrationTest { public RpcTypeSerializationTests() { m_UseHost = false; } protected override bool m_EnableTimeTravel => true; protected override bool m_SetupIsACoroutine => true; protected override bool m_TearDownIsACoroutine => true; public class RpcTestNB : NetworkBehaviour { public delegate void OnReceivedDelegate(object obj); public OnReceivedDelegate OnReceived; [ClientRpc] public void ByteClientRpc(byte value) { OnReceived(value); } [ClientRpc] public void ByteArrayClientRpc(byte[] value) { OnReceived(value); } [ClientRpc] public void ByteNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void ByteNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void SbyteClientRpc(sbyte value) { OnReceived(value); } [ClientRpc] public void SbyteArrayClientRpc(sbyte[] value) { OnReceived(value); } [ClientRpc] public void SbyteNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void SbyteNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void ShortClientRpc(short value) { OnReceived(value); } [ClientRpc] public void ShortArrayClientRpc(short[] value) { OnReceived(value); } [ClientRpc] public void ShortNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void ShortNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void UshortClientRpc(ushort value) { OnReceived(value); } [ClientRpc] public void UshortArrayClientRpc(ushort[] value) { OnReceived(value); } [ClientRpc] public void UshortNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void UshortNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void IntClientRpc(int value) { OnReceived(value); } [ClientRpc] public void IntArrayClientRpc(int[] value) { OnReceived(value); } [ClientRpc] public void IntNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void IntNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void UintClientRpc(uint value) { OnReceived(value); } [ClientRpc] public void UintArrayClientRpc(uint[] value) { OnReceived(value); } [ClientRpc] public void UintNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void UintNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void LongClientRpc(long value) { OnReceived(value); } [ClientRpc] public void LongArrayClientRpc(long[] value) { OnReceived(value); } [ClientRpc] public void LongNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void LongNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void UlongClientRpc(ulong value) { OnReceived(value); } [ClientRpc] public void UlongArrayClientRpc(ulong[] value) { OnReceived(value); } [ClientRpc] public void UlongNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void UlongNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void BoolClientRpc(bool value) { OnReceived(value); } [ClientRpc] public void BoolArrayClientRpc(bool[] value) { OnReceived(value); } [ClientRpc] public void BoolNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void BoolNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void CharClientRpc(char value) { OnReceived(value); } [ClientRpc] public void CharArrayClientRpc(char[] value) { OnReceived(value); } [ClientRpc] public void CharNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void CharNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void FloatClientRpc(float value) { OnReceived(value); } [ClientRpc] public void FloatArrayClientRpc(float[] value) { OnReceived(value); } [ClientRpc] public void FloatNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void FloatNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void DoubleClientRpc(double value) { OnReceived(value); } [ClientRpc] public void DoubleArrayClientRpc(double[] value) { OnReceived(value); } [ClientRpc] public void DoubleNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void DoubleNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void ByteEnumClientRpc(ByteEnum value) { OnReceived(value); } [ClientRpc] public void ByteEnumArrayClientRpc(ByteEnum[] value) { OnReceived(value); } [ClientRpc] public void ByteEnumNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void ByteEnumNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void SByteEnumClientRpc(SByteEnum value) { OnReceived(value); } [ClientRpc] public void SByteEnumArrayClientRpc(SByteEnum[] value) { OnReceived(value); } [ClientRpc] public void SByteEnumNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void SByteEnumNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void ShortEnumClientRpc(ShortEnum value) { OnReceived(value); } [ClientRpc] public void ShortEnumArrayClientRpc(ShortEnum[] value) { OnReceived(value); } [ClientRpc] public void ShortEnumNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void ShortEnumNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void UShortEnumClientRpc(UShortEnum value) { OnReceived(value); } [ClientRpc] public void UShortEnumArrayClientRpc(UShortEnum[] value) { OnReceived(value); } [ClientRpc] public void UShortEnumNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void UShortEnumNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void IntEnumClientRpc(IntEnum value) { OnReceived(value); } [ClientRpc] public void IntEnumArrayClientRpc(IntEnum[] value) { OnReceived(value); } [ClientRpc] public void IntEnumNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void IntEnumNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void UIntEnumClientRpc(UIntEnum value) { OnReceived(value); } [ClientRpc] public void UIntEnumArrayClientRpc(UIntEnum[] value) { OnReceived(value); } [ClientRpc] public void UIntEnumNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void UIntEnumNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void LongEnumClientRpc(LongEnum value) { OnReceived(value); } [ClientRpc] public void LongEnumArrayClientRpc(LongEnum[] value) { OnReceived(value); } [ClientRpc] public void LongEnumNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void LongEnumNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void ULongEnumClientRpc(ULongEnum value) { OnReceived(value); } [ClientRpc] public void ULongEnumArrayClientRpc(ULongEnum[] value) { OnReceived(value); } [ClientRpc] public void ULongEnumNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void ULongEnumNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void Vector2ClientRpc(Vector2 value) { OnReceived(value); } [ClientRpc] public void Vector2ArrayClientRpc(Vector2[] value) { OnReceived(value); } [ClientRpc] public void Vector2NativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void Vector2NativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void Vector3ClientRpc(Vector3 value) { OnReceived(value); } [ClientRpc] public void Vector3ArrayClientRpc(Vector3[] value) { OnReceived(value); } [ClientRpc] public void Vector3NativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void Vector3NativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void Vector2IntClientRpc(Vector2Int value) { OnReceived(value); } [ClientRpc] public void Vector2IntArrayClientRpc(Vector2Int[] value) { OnReceived(value); } [ClientRpc] public void Vector2IntNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void Vector2IntNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void Vector3IntClientRpc(Vector3Int value) { OnReceived(value); } [ClientRpc] public void Vector3IntArrayClientRpc(Vector3Int[] value) { OnReceived(value); } [ClientRpc] public void Vector3IntNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void Vector3IntNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void Vector4ClientRpc(Vector4 value) { OnReceived(value); } [ClientRpc] public void Vector4ArrayClientRpc(Vector4[] value) { OnReceived(value); } [ClientRpc] public void Vector4NativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void Vector4NativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void QuaternionClientRpc(Quaternion value) { OnReceived(value); } [ClientRpc] public void QuaternionArrayClientRpc(Quaternion[] value) { OnReceived(value); } [ClientRpc] public void QuaternionNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void QuaternionNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void ColorClientRpc(Color value) { OnReceived(value); } [ClientRpc] public void ColorArrayClientRpc(Color[] value) { OnReceived(value); } [ClientRpc] public void ColorNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void ColorNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void Color32ClientRpc(Color32 value) { OnReceived(value); } [ClientRpc] public void Color32ArrayClientRpc(Color32[] value) { OnReceived(value); } [ClientRpc] public void Color32NativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void Color32NativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void RayClientRpc(Ray value) { OnReceived(value); } [ClientRpc] public void RayArrayClientRpc(Ray[] value) { OnReceived(value); } [ClientRpc] public void RayNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void RayNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void Ray2DClientRpc(Ray2D value) { OnReceived(value); } [ClientRpc] public void Ray2DArrayClientRpc(Ray2D[] value) { OnReceived(value); } [ClientRpc] public void Ray2DNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void Ray2DNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void NetworkVariableTestStructClientRpc(NetworkVariableTestStruct value) { OnReceived(value); } [ClientRpc] public void NetworkVariableTestStructArrayClientRpc(NetworkVariableTestStruct[] value) { OnReceived(value); } [ClientRpc] public void NetworkVariableTestStructNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void NetworkVariableTestStructNativeListClientRpc(NativeList value) { OnReceived(value); } #endif [ClientRpc] public void FixedString32BytesClientRpc(FixedString32Bytes value) { OnReceived(value); } [ClientRpc] public void FixedString32BytesArrayClientRpc(FixedString32Bytes[] value) { OnReceived(value); } [ClientRpc] public void FixedString32BytesNativeArrayClientRpc(NativeArray value) { OnReceived(value); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [ClientRpc] public void FixedString32BytesNativeListClientRpc(NativeList value) { OnReceived(value); } #endif } protected override int NumberOfClients => 1; protected override void OnCreatePlayerPrefab() { m_PlayerPrefab.AddComponent(); } public void TestValueType(T firstTest, T secondTest) where T : unmanaged { var methods = typeof(RpcTestNB).GetMethods(); foreach (var method in methods) { var parms = method.GetParameters(); if (parms.Length != 1) { continue; } if (parms[0].ParameterType == typeof(T) && method.Name.EndsWith("ClientRpc")) { object receivedValue = null; // This is the *SERVER VERSION* of the *CLIENT PLAYER* RpcTestNB component var serverObject = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); // This is the *CLIENT VERSION* of the *CLIENT PLAYER* RpcTestNB component var clientObject = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); clientObject.OnReceived = o => { receivedValue = o; Debug.Log($"Received value {o}"); }; Debug.Log($"Sending first RPC with {firstTest}"); method.Invoke(serverObject, new object[] { firstTest }); WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); Assert.IsNotNull(receivedValue); Assert.AreEqual(receivedValue.GetType(), typeof(T)); var value = (T)receivedValue; Assert.IsTrue(NetworkVariableSerialization.AreEqual(ref value, ref firstTest)); receivedValue = null; Debug.Log($"Sending second RPC with {secondTest}"); method.Invoke(serverObject, new object[] { secondTest }); WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); Assert.IsNotNull(receivedValue); Assert.AreEqual(receivedValue.GetType(), typeof(T)); value = (T)receivedValue; Assert.IsTrue(NetworkVariableSerialization.AreEqual(ref value, ref secondTest)); return; } } Assert.Fail($"Could not find RPC function for {typeof(T).Name}"); } public void TestValueTypeArray(T[] firstTest, T[] secondTest) where T : unmanaged { var methods = typeof(RpcTestNB).GetMethods(); foreach (var method in methods) { var parms = method.GetParameters(); if (parms.Length != 1) { continue; } if (parms[0].ParameterType == typeof(T[]) && method.Name.EndsWith("ClientRpc")) { object receivedValue = null; // This is the *SERVER VERSION* of the *CLIENT PLAYER* RpcTestNB component var serverObject = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); // This is the *CLIENT VERSION* of the *CLIENT PLAYER* RpcTestNB component var clientObject = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); clientObject.OnReceived = o => { receivedValue = o; Debug.Log($"Received value {o}"); }; Debug.Log($"Sending first RPC with {firstTest}"); method.Invoke(serverObject, new object[] { firstTest }); WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); Assert.IsNotNull(receivedValue); Assert.AreEqual(receivedValue.GetType(), typeof(T[])); var value = (T[])receivedValue; Assert.AreEqual(value, firstTest); receivedValue = null; Debug.Log($"Sending second RPC with {secondTest}"); method.Invoke(serverObject, new object[] { secondTest }); WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); Assert.IsNotNull(receivedValue); Assert.AreEqual(receivedValue.GetType(), typeof(T[])); value = (T[])receivedValue; Assert.AreEqual(value, secondTest); method.Invoke(serverObject, new object[] { null }); WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); Assert.IsNull(receivedValue); return; } } Assert.Fail($"Could not find RPC function for {typeof(T).Name}"); } public void TestValueTypeNativeArray(NativeArray firstTest, NativeArray secondTest) where T : unmanaged { var methods = typeof(RpcTestNB).GetMethods(); foreach (var method in methods) { var parms = method.GetParameters(); if (parms.Length != 1) { continue; } if (parms[0].ParameterType == typeof(NativeArray) && method.Name.EndsWith("ClientRpc")) { var receivedValue = new NativeArray(); // This is the *SERVER VERSION* of the *CLIENT PLAYER* RpcTestNB component var serverObject = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); // This is the *CLIENT VERSION* of the *CLIENT PLAYER* RpcTestNB component var clientObject = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); clientObject.OnReceived = o => { Assert.AreEqual(o.GetType(), typeof(NativeArray)); var oAsArray = (NativeArray)o; receivedValue = new NativeArray(oAsArray, Allocator.Persistent); Debug.Log($"Received value {o}"); }; Debug.Log($"Sending first RPC with {firstTest}"); method.Invoke(serverObject, new object[] { firstTest }); WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); Assert.IsTrue(receivedValue.IsCreated); Assert.IsTrue(NetworkVariableSerialization>.AreEqual(ref receivedValue, ref firstTest)); receivedValue.Dispose(); firstTest.Dispose(); receivedValue = new NativeArray(); Debug.Log($"Sending second RPC with {secondTest}"); method.Invoke(serverObject, new object[] { secondTest }); WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); Assert.IsTrue(receivedValue.IsCreated); Assert.IsTrue(NetworkVariableSerialization>.AreEqual(ref receivedValue, ref secondTest)); receivedValue.Dispose(); secondTest.Dispose(); return; } } Assert.Fail($"Could not find RPC function for {typeof(T).Name}"); } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT public void TestValueTypeNativeList(NativeList firstTest, NativeList secondTest) where T : unmanaged { var methods = typeof(RpcTestNB).GetMethods(); foreach (var method in methods) { var parms = method.GetParameters(); if (parms.Length != 1) { continue; } if (parms[0].ParameterType == typeof(NativeList) && method.Name.EndsWith("ClientRpc")) { var receivedValue = new NativeList(); // This is the *SERVER VERSION* of the *CLIENT PLAYER* RpcTestNB component var serverObject = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); // This is the *CLIENT VERSION* of the *CLIENT PLAYER* RpcTestNB component var clientObject = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); clientObject.OnReceived = o => { Assert.AreEqual(o.GetType(), typeof(NativeList)); var oAsList = (NativeList)o; receivedValue = new NativeList(oAsList.Length, Allocator.Persistent); foreach (var item in oAsList) { receivedValue.Add(item); } Debug.Log($"Received value {o}"); }; Debug.Log($"Sending first RPC with {firstTest}"); method.Invoke(serverObject, new object[] { firstTest }); WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); Assert.IsTrue(receivedValue.IsCreated); Assert.IsTrue(NetworkVariableSerialization>.AreEqual(ref receivedValue, ref firstTest)); receivedValue.Dispose(); firstTest.Dispose(); receivedValue = new NativeList(); Debug.Log($"Sending second RPC with {secondTest}"); method.Invoke(serverObject, new object[] { secondTest }); WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); Assert.IsTrue(receivedValue.IsCreated); Assert.IsTrue(NetworkVariableSerialization>.AreEqual(ref receivedValue, ref secondTest)); receivedValue.Dispose(); secondTest.Dispose(); return; } } Assert.Fail($"Could not find RPC function for {typeof(T).Name}"); } #endif [Test] public void WhenSendingAValueTypeOverAnRpc_ValuesAreSerializedCorrectly( [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(NetworkVariableTestStruct), typeof(FixedString32Bytes))] Type testType) { if (testType == typeof(byte)) { TestValueType(byte.MinValue + 5, byte.MaxValue); } else if (testType == typeof(sbyte)) { TestValueType(sbyte.MinValue + 5, sbyte.MaxValue); } else if (testType == typeof(short)) { TestValueType(short.MinValue + 5, short.MaxValue); } else if (testType == typeof(ushort)) { TestValueType(ushort.MinValue + 5, ushort.MaxValue); } else if (testType == typeof(int)) { TestValueType(int.MinValue + 5, int.MaxValue); } else if (testType == typeof(uint)) { TestValueType(uint.MinValue + 5, uint.MaxValue); } else if (testType == typeof(long)) { TestValueType(long.MinValue + 5, long.MaxValue); } else if (testType == typeof(ulong)) { TestValueType(ulong.MinValue + 5, ulong.MaxValue); } else if (testType == typeof(bool)) { TestValueType(true, false); } else if (testType == typeof(char)) { TestValueType('z', ' '); } else if (testType == typeof(float)) { TestValueType(float.MinValue + 5.12345678f, float.MaxValue); } else if (testType == typeof(double)) { TestValueType(double.MinValue + 5.12345678, double.MaxValue); } else if (testType == typeof(ByteEnum)) { TestValueType(ByteEnum.B, ByteEnum.C); } else if (testType == typeof(SByteEnum)) { TestValueType(SByteEnum.B, SByteEnum.C); } else if (testType == typeof(ShortEnum)) { TestValueType(ShortEnum.B, ShortEnum.C); } else if (testType == typeof(UShortEnum)) { TestValueType(UShortEnum.B, UShortEnum.C); } else if (testType == typeof(IntEnum)) { TestValueType(IntEnum.B, IntEnum.C); } else if (testType == typeof(UIntEnum)) { TestValueType(UIntEnum.B, UIntEnum.C); } else if (testType == typeof(LongEnum)) { TestValueType(LongEnum.B, LongEnum.C); } else if (testType == typeof(ULongEnum)) { TestValueType(ULongEnum.B, ULongEnum.C); } else if (testType == typeof(Vector2)) { TestValueType( new Vector2(5, 10), new Vector2(15, 20)); } else if (testType == typeof(Vector3)) { TestValueType( new Vector3(5, 10, 15), new Vector3(20, 25, 30)); } else if (testType == typeof(Vector2Int)) { TestValueType( new Vector2Int(5, 10), new Vector2Int(15, 20)); } else if (testType == typeof(Vector3Int)) { TestValueType( new Vector3Int(5, 10, 15), new Vector3Int(20, 25, 30)); } else if (testType == typeof(Vector4)) { TestValueType( new Vector4(5, 10, 15, 20), new Vector4(25, 30, 35, 40)); } else if (testType == typeof(Quaternion)) { TestValueType( new Quaternion(5, 10, 15, 20), new Quaternion(25, 30, 35, 40)); } else if (testType == typeof(Color)) { TestValueType( new Color(1, 0, 0), new Color(0, 1, 1)); } else if (testType == typeof(Color32)) { TestValueType( new Color32(255, 0, 0, 128), new Color32(0, 255, 255, 255)); } else if (testType == typeof(Ray)) { TestValueType( new Ray(new Vector3(0, 1, 2), new Vector3(3, 4, 5)), new Ray(new Vector3(6, 7, 8), new Vector3(9, 10, 11))); } else if (testType == typeof(Ray2D)) { TestValueType( new Ray2D(new Vector2(0, 1), new Vector2(2, 3)), new Ray2D(new Vector2(4, 5), new Vector2(6, 7))); } else if (testType == typeof(NetworkVariableTestStruct)) { TestValueType(NetworkVariableTestStruct.GetTestStruct(), NetworkVariableTestStruct.GetTestStruct()); } else if (testType == typeof(FixedString32Bytes)) { TestValueType(new FixedString32Bytes("foobar"), new FixedString32Bytes("12345678901234567890123456789")); } } [Test] public void WhenSendingAnArrayOfValueTypesOverAnRpc_ValuesAreSerializedCorrectly( [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(NetworkVariableTestStruct), typeof(FixedString32Bytes))] Type testType) { if (testType == typeof(byte)) { TestValueTypeArray( new byte[] { byte.MinValue + 5, byte.MaxValue }, new byte[] { 0, byte.MinValue + 10, byte.MaxValue - 10 }); } else if (testType == typeof(sbyte)) { TestValueTypeArray( new sbyte[] { sbyte.MinValue + 5, sbyte.MaxValue }, new sbyte[] { 0, sbyte.MinValue + 10, sbyte.MaxValue - 10 }); } else if (testType == typeof(short)) { TestValueTypeArray( new short[] { short.MinValue + 5, short.MaxValue }, new short[] { 0, short.MinValue + 10, short.MaxValue - 10 }); } else if (testType == typeof(ushort)) { TestValueTypeArray( new ushort[] { ushort.MinValue + 5, ushort.MaxValue }, new ushort[] { 0, ushort.MinValue + 10, ushort.MaxValue - 10 }); } else if (testType == typeof(int)) { TestValueTypeArray( new int[] { int.MinValue + 5, int.MaxValue }, new int[] { 0, int.MinValue + 10, int.MaxValue - 10 }); } else if (testType == typeof(uint)) { TestValueTypeArray( new uint[] { uint.MinValue + 5, uint.MaxValue }, new uint[] { 0, uint.MinValue + 10, uint.MaxValue - 10 }); } else if (testType == typeof(long)) { TestValueTypeArray( new long[] { long.MinValue + 5, long.MaxValue }, new long[] { 0, long.MinValue + 10, long.MaxValue - 10 }); } else if (testType == typeof(ulong)) { TestValueTypeArray( new ulong[] { ulong.MinValue + 5, ulong.MaxValue }, new ulong[] { 0, ulong.MinValue + 10, ulong.MaxValue - 10 }); } else if (testType == typeof(bool)) { TestValueTypeArray( new bool[] { true, false, true }, new bool[] { false, true, false, true, false }); } else if (testType == typeof(char)) { TestValueTypeArray( new char[] { 'z', ' ', '?' }, new char[] { 'n', 'e', 'w', ' ', 'v', 'a', 'l', 'u', 'e' }); } else if (testType == typeof(float)) { TestValueTypeArray( new float[] { float.MinValue + 5.12345678f, float.MaxValue }, new float[] { 0, float.MinValue + 10.987654321f, float.MaxValue - 10.135792468f }); } else if (testType == typeof(double)) { TestValueTypeArray( new double[] { double.MinValue + 5.12345678, double.MaxValue }, new double[] { 0, double.MinValue + 10.987654321, double.MaxValue - 10.135792468 }); } else if (testType == typeof(ByteEnum)) { TestValueTypeArray( new ByteEnum[] { ByteEnum.C, ByteEnum.B, ByteEnum.A }, new ByteEnum[] { ByteEnum.B, ByteEnum.C, ByteEnum.B, ByteEnum.A, ByteEnum.C }); } else if (testType == typeof(SByteEnum)) { TestValueTypeArray( new SByteEnum[] { SByteEnum.C, SByteEnum.B, SByteEnum.A }, new SByteEnum[] { SByteEnum.B, SByteEnum.C, SByteEnum.B, SByteEnum.A, SByteEnum.C }); } else if (testType == typeof(ShortEnum)) { TestValueTypeArray( new ShortEnum[] { ShortEnum.C, ShortEnum.B, ShortEnum.A }, new ShortEnum[] { ShortEnum.B, ShortEnum.C, ShortEnum.B, ShortEnum.A, ShortEnum.C }); } else if (testType == typeof(UShortEnum)) { TestValueTypeArray( new UShortEnum[] { UShortEnum.C, UShortEnum.B, UShortEnum.A }, new UShortEnum[] { UShortEnum.B, UShortEnum.C, UShortEnum.B, UShortEnum.A, UShortEnum.C }); } else if (testType == typeof(IntEnum)) { TestValueTypeArray( new IntEnum[] { IntEnum.C, IntEnum.B, IntEnum.A }, new IntEnum[] { IntEnum.B, IntEnum.C, IntEnum.B, IntEnum.A, IntEnum.C }); } else if (testType == typeof(UIntEnum)) { TestValueTypeArray( new UIntEnum[] { UIntEnum.C, UIntEnum.B, UIntEnum.A }, new UIntEnum[] { UIntEnum.B, UIntEnum.C, UIntEnum.B, UIntEnum.A, UIntEnum.C }); } else if (testType == typeof(LongEnum)) { TestValueTypeArray( new LongEnum[] { LongEnum.C, LongEnum.B, LongEnum.A }, new LongEnum[] { LongEnum.B, LongEnum.C, LongEnum.B, LongEnum.A, LongEnum.C }); } else if (testType == typeof(ULongEnum)) { TestValueTypeArray( new ULongEnum[] { ULongEnum.C, ULongEnum.B, ULongEnum.A }, new ULongEnum[] { ULongEnum.B, ULongEnum.C, ULongEnum.B, ULongEnum.A, ULongEnum.C }); } else if (testType == typeof(Vector2)) { TestValueTypeArray( new Vector2[] { new Vector2(5, 10), new Vector2(15, 20) }, new Vector2[] { new Vector2(25, 30), new Vector2(35, 40), new Vector2(45, 50) }); } else if (testType == typeof(Vector3)) { TestValueTypeArray( new Vector3[] { new Vector3(5, 10, 15), new Vector3(20, 25, 30) }, new Vector3[] { new Vector3(35, 40, 45), new Vector3(50, 55, 60), new Vector3(65, 70, 75) }); } else if (testType == typeof(Vector2Int)) { TestValueTypeArray( new Vector2Int[] { new Vector2Int(5, 10), new Vector2Int(15, 20) }, new Vector2Int[] { new Vector2Int(25, 30), new Vector2Int(35, 40), new Vector2Int(45, 50) }); } else if (testType == typeof(Vector3Int)) { TestValueTypeArray( new Vector3Int[] { new Vector3Int(5, 10, 15), new Vector3Int(20, 25, 30) }, new Vector3Int[] { new Vector3Int(35, 40, 45), new Vector3Int(50, 55, 60), new Vector3Int(65, 70, 75) }); } else if (testType == typeof(Vector4)) { TestValueTypeArray( new Vector4[] { new Vector4(5, 10, 15, 20), new Vector4(25, 30, 35, 40) }, new Vector4[] { new Vector4(45, 50, 55, 60), new Vector4(65, 70, 75, 80), new Vector4(85, 90, 95, 100) }); } else if (testType == typeof(Quaternion)) { TestValueTypeArray( new Quaternion[] { new Quaternion(5, 10, 15, 20), new Quaternion(25, 30, 35, 40) }, new Quaternion[] { new Quaternion(45, 50, 55, 60), new Quaternion(65, 70, 75, 80), new Quaternion(85, 90, 95, 100) }); } else if (testType == typeof(Color)) { TestValueTypeArray( new Color[] { new Color(.5f, .10f, .15f), new Color(.20f, .25f, .30f) }, new Color[] { new Color(.35f, .40f, .45f), new Color(.50f, .55f, .60f), new Color(.65f, .70f, .75f) }); } else if (testType == typeof(Color32)) { TestValueTypeArray( new Color32[] { new Color32(5, 10, 15, 20), new Color32(25, 30, 35, 40) }, new Color32[] { new Color32(45, 50, 55, 60), new Color32(65, 70, 75, 80), new Color32(85, 90, 95, 100) }); } else if (testType == typeof(Ray)) { TestValueTypeArray( new Ray[] { new Ray(new Vector3(0, 1, 2), new Vector3(3, 4, 5)), new Ray(new Vector3(6, 7, 8), new Vector3(9, 10, 11)), }, new Ray[] { new Ray(new Vector3(12, 13, 14), new Vector3(15, 16, 17)), new Ray(new Vector3(18, 19, 20), new Vector3(21, 22, 23)), new Ray(new Vector3(24, 25, 26), new Vector3(27, 28, 29)), }); } else if (testType == typeof(Ray2D)) { TestValueTypeArray( new Ray2D[] { new Ray2D(new Vector2(0, 1), new Vector2(3, 4)), new Ray2D(new Vector2(6, 7), new Vector2(9, 10)), }, new Ray2D[] { new Ray2D(new Vector2(12, 13), new Vector2(15, 16)), new Ray2D(new Vector2(18, 19), new Vector2(21, 22)), new Ray2D(new Vector2(24, 25), new Vector2(27, 28)), }); } else if (testType == typeof(NetworkVariableTestStruct)) { TestValueTypeArray( new NetworkVariableTestStruct[] { NetworkVariableTestStruct.GetTestStruct(), NetworkVariableTestStruct.GetTestStruct() }, new NetworkVariableTestStruct[] { NetworkVariableTestStruct.GetTestStruct(), NetworkVariableTestStruct.GetTestStruct(), NetworkVariableTestStruct.GetTestStruct() }); } else if (testType == typeof(FixedString32Bytes)) { TestValueTypeArray( new FixedString32Bytes[] { new FixedString32Bytes("foobar"), new FixedString32Bytes("12345678901234567890123456789") }, new FixedString32Bytes[] { new FixedString32Bytes("BazQux"), new FixedString32Bytes("98765432109876543210987654321"), new FixedString32Bytes("FixedString32Bytes") }); } } [Test] public void WhenSendingANativeArrayOfValueTypesOverAnRpc_ValuesAreSerializedCorrectly( [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(NetworkVariableTestStruct), typeof(FixedString32Bytes))] Type testType) { if (testType == typeof(byte)) { TestValueTypeNativeArray( new NativeArray(new byte[] { byte.MinValue + 5, byte.MaxValue }, Allocator.Persistent), new NativeArray(new byte[] { 0, byte.MinValue + 10, byte.MaxValue - 10 }, Allocator.Persistent)); } else if (testType == typeof(sbyte)) { TestValueTypeNativeArray( new NativeArray(new sbyte[] { sbyte.MinValue + 5, sbyte.MaxValue }, Allocator.Persistent), new NativeArray(new sbyte[] { 0, sbyte.MinValue + 10, sbyte.MaxValue - 10 }, Allocator.Persistent)); } else if (testType == typeof(short)) { TestValueTypeNativeArray( new NativeArray(new short[] { short.MinValue + 5, short.MaxValue }, Allocator.Persistent), new NativeArray(new short[] { 0, short.MinValue + 10, short.MaxValue - 10 }, Allocator.Persistent)); } else if (testType == typeof(ushort)) { TestValueTypeNativeArray( new NativeArray(new ushort[] { ushort.MinValue + 5, ushort.MaxValue }, Allocator.Persistent), new NativeArray(new ushort[] { 0, ushort.MinValue + 10, ushort.MaxValue - 10 }, Allocator.Persistent)); } else if (testType == typeof(int)) { TestValueTypeNativeArray( new NativeArray(new int[] { int.MinValue + 5, int.MaxValue }, Allocator.Persistent), new NativeArray(new int[] { 0, int.MinValue + 10, int.MaxValue - 10 }, Allocator.Persistent)); } else if (testType == typeof(uint)) { TestValueTypeNativeArray( new NativeArray(new uint[] { uint.MinValue + 5, uint.MaxValue }, Allocator.Persistent), new NativeArray(new uint[] { 0, uint.MinValue + 10, uint.MaxValue - 10 }, Allocator.Persistent)); } else if (testType == typeof(long)) { TestValueTypeNativeArray( new NativeArray(new long[] { long.MinValue + 5, long.MaxValue }, Allocator.Persistent), new NativeArray(new long[] { 0, long.MinValue + 10, long.MaxValue - 10 }, Allocator.Persistent)); } else if (testType == typeof(ulong)) { TestValueTypeNativeArray( new NativeArray(new ulong[] { ulong.MinValue + 5, ulong.MaxValue }, Allocator.Persistent), new NativeArray(new ulong[] { 0, ulong.MinValue + 10, ulong.MaxValue - 10 }, Allocator.Persistent)); } else if (testType == typeof(bool)) { TestValueTypeNativeArray( new NativeArray(new bool[] { true, false, true }, Allocator.Persistent), new NativeArray(new bool[] { false, true, false, true, false }, Allocator.Persistent)); } else if (testType == typeof(char)) { TestValueTypeNativeArray( new NativeArray(new char[] { 'z', ' ', '?' }, Allocator.Persistent), new NativeArray(new char[] { 'n', 'e', 'w', ' ', 'v', 'a', 'l', 'u', 'e' }, Allocator.Persistent)); } else if (testType == typeof(float)) { TestValueTypeNativeArray( new NativeArray(new float[] { float.MinValue + 5.12345678f, float.MaxValue }, Allocator.Persistent), new NativeArray(new float[] { 0, float.MinValue + 10.987654321f, float.MaxValue - 10.135792468f }, Allocator.Persistent)); } else if (testType == typeof(double)) { TestValueTypeNativeArray( new NativeArray(new double[] { double.MinValue + 5.12345678, double.MaxValue }, Allocator.Persistent), new NativeArray(new double[] { 0, double.MinValue + 10.987654321, double.MaxValue - 10.135792468 }, Allocator.Persistent)); } else if (testType == typeof(ByteEnum)) { TestValueTypeNativeArray( new NativeArray(new ByteEnum[] { ByteEnum.C, ByteEnum.B, ByteEnum.A }, Allocator.Persistent), new NativeArray(new ByteEnum[] { ByteEnum.B, ByteEnum.C, ByteEnum.B, ByteEnum.A, ByteEnum.C }, Allocator.Persistent)); } else if (testType == typeof(SByteEnum)) { TestValueTypeNativeArray( new NativeArray(new SByteEnum[] { SByteEnum.C, SByteEnum.B, SByteEnum.A }, Allocator.Persistent), new NativeArray(new SByteEnum[] { SByteEnum.B, SByteEnum.C, SByteEnum.B, SByteEnum.A, SByteEnum.C }, Allocator.Persistent)); } else if (testType == typeof(ShortEnum)) { TestValueTypeNativeArray( new NativeArray(new ShortEnum[] { ShortEnum.C, ShortEnum.B, ShortEnum.A }, Allocator.Persistent), new NativeArray(new ShortEnum[] { ShortEnum.B, ShortEnum.C, ShortEnum.B, ShortEnum.A, ShortEnum.C }, Allocator.Persistent)); } else if (testType == typeof(UShortEnum)) { TestValueTypeNativeArray( new NativeArray(new UShortEnum[] { UShortEnum.C, UShortEnum.B, UShortEnum.A }, Allocator.Persistent), new NativeArray(new UShortEnum[] { UShortEnum.B, UShortEnum.C, UShortEnum.B, UShortEnum.A, UShortEnum.C }, Allocator.Persistent)); } else if (testType == typeof(IntEnum)) { TestValueTypeNativeArray( new NativeArray(new IntEnum[] { IntEnum.C, IntEnum.B, IntEnum.A }, Allocator.Persistent), new NativeArray(new IntEnum[] { IntEnum.B, IntEnum.C, IntEnum.B, IntEnum.A, IntEnum.C }, Allocator.Persistent)); } else if (testType == typeof(UIntEnum)) { TestValueTypeNativeArray( new NativeArray(new UIntEnum[] { UIntEnum.C, UIntEnum.B, UIntEnum.A }, Allocator.Persistent), new NativeArray(new UIntEnum[] { UIntEnum.B, UIntEnum.C, UIntEnum.B, UIntEnum.A, UIntEnum.C }, Allocator.Persistent)); } else if (testType == typeof(LongEnum)) { TestValueTypeNativeArray( new NativeArray(new LongEnum[] { LongEnum.C, LongEnum.B, LongEnum.A }, Allocator.Persistent), new NativeArray(new LongEnum[] { LongEnum.B, LongEnum.C, LongEnum.B, LongEnum.A, LongEnum.C }, Allocator.Persistent)); } else if (testType == typeof(ULongEnum)) { TestValueTypeNativeArray( new NativeArray(new ULongEnum[] { ULongEnum.C, ULongEnum.B, ULongEnum.A }, Allocator.Persistent), new NativeArray(new ULongEnum[] { ULongEnum.B, ULongEnum.C, ULongEnum.B, ULongEnum.A, ULongEnum.C }, Allocator.Persistent)); } else if (testType == typeof(Vector2)) { TestValueTypeNativeArray( new NativeArray(new Vector2[] { new Vector2(5, 10), new Vector2(15, 20) }, Allocator.Persistent), new NativeArray(new Vector2[] { new Vector2(25, 30), new Vector2(35, 40), new Vector2(45, 50) }, Allocator.Persistent)); } else if (testType == typeof(Vector3)) { TestValueTypeNativeArray( new NativeArray(new Vector3[] { new Vector3(5, 10, 15), new Vector3(20, 25, 30) }, Allocator.Persistent), new NativeArray(new Vector3[] { new Vector3(35, 40, 45), new Vector3(50, 55, 60), new Vector3(65, 70, 75) }, Allocator.Persistent)); } else if (testType == typeof(Vector2Int)) { TestValueTypeNativeArray( new NativeArray(new Vector2Int[] { new Vector2Int(5, 10), new Vector2Int(15, 20) }, Allocator.Persistent), new NativeArray(new Vector2Int[] { new Vector2Int(25, 30), new Vector2Int(35, 40), new Vector2Int(45, 50) }, Allocator.Persistent)); } else if (testType == typeof(Vector3Int)) { TestValueTypeNativeArray( new NativeArray(new Vector3Int[] { new Vector3Int(5, 10, 15), new Vector3Int(20, 25, 30) }, Allocator.Persistent), new NativeArray(new Vector3Int[] { new Vector3Int(35, 40, 45), new Vector3Int(50, 55, 60), new Vector3Int(65, 70, 75) }, Allocator.Persistent)); } else if (testType == typeof(Vector4)) { TestValueTypeNativeArray( new NativeArray(new Vector4[] { new Vector4(5, 10, 15, 20), new Vector4(25, 30, 35, 40) }, Allocator.Persistent), new NativeArray(new Vector4[] { new Vector4(45, 50, 55, 60), new Vector4(65, 70, 75, 80), new Vector4(85, 90, 95, 100) }, Allocator.Persistent)); } else if (testType == typeof(Quaternion)) { TestValueTypeNativeArray( new NativeArray(new Quaternion[] { new Quaternion(5, 10, 15, 20), new Quaternion(25, 30, 35, 40) }, Allocator.Persistent), new NativeArray(new Quaternion[] { new Quaternion(45, 50, 55, 60), new Quaternion(65, 70, 75, 80), new Quaternion(85, 90, 95, 100) }, Allocator.Persistent)); } else if (testType == typeof(Color)) { TestValueTypeNativeArray( new NativeArray(new Color[] { new Color(.5f, .10f, .15f), new Color(.20f, .25f, .30f) }, Allocator.Persistent), new NativeArray(new Color[] { new Color(.35f, .40f, .45f), new Color(.50f, .55f, .60f), new Color(.65f, .70f, .75f) }, Allocator.Persistent)); } else if (testType == typeof(Color32)) { TestValueTypeNativeArray( new NativeArray(new Color32[] { new Color32(5, 10, 15, 20), new Color32(25, 30, 35, 40) }, Allocator.Persistent), new NativeArray(new Color32[] { new Color32(45, 50, 55, 60), new Color32(65, 70, 75, 80), new Color32(85, 90, 95, 100) }, Allocator.Persistent)); } else if (testType == typeof(Ray)) { TestValueTypeNativeArray( new NativeArray(new Ray[] { new Ray(new Vector3(0, 1, 2), new Vector3(3, 4, 5)), new Ray(new Vector3(6, 7, 8), new Vector3(9, 10, 11)), }, Allocator.Persistent), new NativeArray(new Ray[] { new Ray(new Vector3(12, 13, 14), new Vector3(15, 16, 17)), new Ray(new Vector3(18, 19, 20), new Vector3(21, 22, 23)), new Ray(new Vector3(24, 25, 26), new Vector3(27, 28, 29)), }, Allocator.Persistent)); } else if (testType == typeof(Ray2D)) { TestValueTypeNativeArray( new NativeArray(new Ray2D[] { new Ray2D(new Vector2(0, 1), new Vector2(3, 4)), new Ray2D(new Vector2(6, 7), new Vector2(9, 10)), }, Allocator.Persistent), new NativeArray(new Ray2D[] { new Ray2D(new Vector2(12, 13), new Vector2(15, 16)), new Ray2D(new Vector2(18, 19), new Vector2(21, 22)), new Ray2D(new Vector2(24, 25), new Vector2(27, 28)), }, Allocator.Persistent)); } else if (testType == typeof(NetworkVariableTestStruct)) { TestValueTypeNativeArray( new NativeArray(new NetworkVariableTestStruct[] { NetworkVariableTestStruct.GetTestStruct(), NetworkVariableTestStruct.GetTestStruct() }, Allocator.Persistent), new NativeArray(new NetworkVariableTestStruct[] { NetworkVariableTestStruct.GetTestStruct(), NetworkVariableTestStruct.GetTestStruct(), NetworkVariableTestStruct.GetTestStruct() }, Allocator.Persistent)); } else if (testType == typeof(FixedString32Bytes)) { TestValueTypeNativeArray( new NativeArray(new FixedString32Bytes[] { new FixedString32Bytes("foobar"), new FixedString32Bytes("12345678901234567890123456789") }, Allocator.Persistent), new NativeArray(new FixedString32Bytes[] { new FixedString32Bytes("BazQux"), new FixedString32Bytes("98765432109876543210987654321"), new FixedString32Bytes("FixedString32Bytes") }, Allocator.Persistent)); } } #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT [Test] public void WhenSendingANativeListOfValueTypesOverAnRpc_ValuesAreSerializedCorrectly( [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(NetworkVariableTestStruct), typeof(FixedString32Bytes))] Type testType) { if (testType == typeof(byte)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { byte.MinValue + 5, byte.MaxValue }, new NativeList(Allocator.Persistent) { 0, byte.MinValue + 10, byte.MaxValue - 10 }); } else if (testType == typeof(sbyte)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { sbyte.MinValue + 5, sbyte.MaxValue }, new NativeList(Allocator.Persistent) { 0, sbyte.MinValue + 10, sbyte.MaxValue - 10 }); } else if (testType == typeof(short)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { short.MinValue + 5, short.MaxValue }, new NativeList(Allocator.Persistent) { 0, short.MinValue + 10, short.MaxValue - 10 }); } else if (testType == typeof(ushort)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { ushort.MinValue + 5, ushort.MaxValue }, new NativeList(Allocator.Persistent) { 0, ushort.MinValue + 10, ushort.MaxValue - 10 }); } else if (testType == typeof(int)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { int.MinValue + 5, int.MaxValue }, new NativeList(Allocator.Persistent) { 0, int.MinValue + 10, int.MaxValue - 10 }); } else if (testType == typeof(uint)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { uint.MinValue + 5, uint.MaxValue }, new NativeList(Allocator.Persistent) { 0, uint.MinValue + 10, uint.MaxValue - 10 }); } else if (testType == typeof(long)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { long.MinValue + 5, long.MaxValue }, new NativeList(Allocator.Persistent) { 0, long.MinValue + 10, long.MaxValue - 10 }); } else if (testType == typeof(ulong)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { ulong.MinValue + 5, ulong.MaxValue }, new NativeList(Allocator.Persistent) { 0, ulong.MinValue + 10, ulong.MaxValue - 10 }); } else if (testType == typeof(bool)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { true, false, true }, new NativeList(Allocator.Persistent) { false, true, false, true, false }); } else if (testType == typeof(char)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { 'z', ' ', '?' }, new NativeList(Allocator.Persistent) { 'n', 'e', 'w', ' ', 'v', 'a', 'l', 'u', 'e' }); } else if (testType == typeof(float)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { float.MinValue + 5.12345678f, float.MaxValue }, new NativeList(Allocator.Persistent) { 0, float.MinValue + 10.987654321f, float.MaxValue - 10.135792468f }); } else if (testType == typeof(double)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { double.MinValue + 5.12345678, double.MaxValue }, new NativeList(Allocator.Persistent) { 0, double.MinValue + 10.987654321, double.MaxValue - 10.135792468 }); } else if (testType == typeof(ByteEnum)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { ByteEnum.C, ByteEnum.B, ByteEnum.A }, new NativeList(Allocator.Persistent) { ByteEnum.B, ByteEnum.C, ByteEnum.B, ByteEnum.A, ByteEnum.C }); } else if (testType == typeof(SByteEnum)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { SByteEnum.C, SByteEnum.B, SByteEnum.A }, new NativeList(Allocator.Persistent) { SByteEnum.B, SByteEnum.C, SByteEnum.B, SByteEnum.A, SByteEnum.C }); } else if (testType == typeof(ShortEnum)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { ShortEnum.C, ShortEnum.B, ShortEnum.A }, new NativeList(Allocator.Persistent) { ShortEnum.B, ShortEnum.C, ShortEnum.B, ShortEnum.A, ShortEnum.C }); } else if (testType == typeof(UShortEnum)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { UShortEnum.C, UShortEnum.B, UShortEnum.A }, new NativeList(Allocator.Persistent) { UShortEnum.B, UShortEnum.C, UShortEnum.B, UShortEnum.A, UShortEnum.C }); } else if (testType == typeof(IntEnum)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { IntEnum.C, IntEnum.B, IntEnum.A }, new NativeList(Allocator.Persistent) { IntEnum.B, IntEnum.C, IntEnum.B, IntEnum.A, IntEnum.C }); } else if (testType == typeof(UIntEnum)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { UIntEnum.C, UIntEnum.B, UIntEnum.A }, new NativeList(Allocator.Persistent) { UIntEnum.B, UIntEnum.C, UIntEnum.B, UIntEnum.A, UIntEnum.C }); } else if (testType == typeof(LongEnum)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { LongEnum.C, LongEnum.B, LongEnum.A }, new NativeList(Allocator.Persistent) { LongEnum.B, LongEnum.C, LongEnum.B, LongEnum.A, LongEnum.C }); } else if (testType == typeof(ULongEnum)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { ULongEnum.C, ULongEnum.B, ULongEnum.A }, new NativeList(Allocator.Persistent) { ULongEnum.B, ULongEnum.C, ULongEnum.B, ULongEnum.A, ULongEnum.C }); } else if (testType == typeof(Vector2)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { new Vector2(5, 10), new Vector2(15, 20) }, new NativeList(Allocator.Persistent) { new Vector2(25, 30), new Vector2(35, 40), new Vector2(45, 50) }); } else if (testType == typeof(Vector3)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { new Vector3(5, 10, 15), new Vector3(20, 25, 30) }, new NativeList(Allocator.Persistent) { new Vector3(35, 40, 45), new Vector3(50, 55, 60), new Vector3(65, 70, 75) }); } else if (testType == typeof(Vector2Int)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { new Vector2Int(5, 10), new Vector2Int(15, 20) }, new NativeList(Allocator.Persistent) { new Vector2Int(25, 30), new Vector2Int(35, 40), new Vector2Int(45, 50) }); } else if (testType == typeof(Vector3Int)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { new Vector3Int(5, 10, 15), new Vector3Int(20, 25, 30) }, new NativeList(Allocator.Persistent) { new Vector3Int(35, 40, 45), new Vector3Int(50, 55, 60), new Vector3Int(65, 70, 75) }); } else if (testType == typeof(Vector4)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { new Vector4(5, 10, 15, 20), new Vector4(25, 30, 35, 40) }, new NativeList(Allocator.Persistent) { new Vector4(45, 50, 55, 60), new Vector4(65, 70, 75, 80), new Vector4(85, 90, 95, 100) }); } else if (testType == typeof(Quaternion)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { new Quaternion(5, 10, 15, 20), new Quaternion(25, 30, 35, 40) }, new NativeList(Allocator.Persistent) { new Quaternion(45, 50, 55, 60), new Quaternion(65, 70, 75, 80), new Quaternion(85, 90, 95, 100) }); } else if (testType == typeof(Color)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { new Color(.5f, .10f, .15f), new Color(.20f, .25f, .30f) }, new NativeList(Allocator.Persistent) { new Color(.35f, .40f, .45f), new Color(.50f, .55f, .60f), new Color(.65f, .70f, .75f) }); } else if (testType == typeof(Color32)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { new Color32(5, 10, 15, 20), new Color32(25, 30, 35, 40) }, new NativeList(Allocator.Persistent) { new Color32(45, 50, 55, 60), new Color32(65, 70, 75, 80), new Color32(85, 90, 95, 100) }); } else if (testType == typeof(Ray)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { new Ray(new Vector3(0, 1, 2), new Vector3(3, 4, 5)), new Ray(new Vector3(6, 7, 8), new Vector3(9, 10, 11)), }, new NativeList(Allocator.Persistent) { new Ray(new Vector3(12, 13, 14), new Vector3(15, 16, 17)), new Ray(new Vector3(18, 19, 20), new Vector3(21, 22, 23)), new Ray(new Vector3(24, 25, 26), new Vector3(27, 28, 29)), }); } else if (testType == typeof(Ray2D)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { new Ray2D(new Vector2(0, 1), new Vector2(3, 4)), new Ray2D(new Vector2(6, 7), new Vector2(9, 10)), }, new NativeList(Allocator.Persistent) { new Ray2D(new Vector2(12, 13), new Vector2(15, 16)), new Ray2D(new Vector2(18, 19), new Vector2(21, 22)), new Ray2D(new Vector2(24, 25), new Vector2(27, 28)), }); } else if (testType == typeof(NetworkVariableTestStruct)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { NetworkVariableTestStruct.GetTestStruct(), NetworkVariableTestStruct.GetTestStruct() }, new NativeList(Allocator.Persistent) { NetworkVariableTestStruct.GetTestStruct(), NetworkVariableTestStruct.GetTestStruct(), NetworkVariableTestStruct.GetTestStruct() }); } else if (testType == typeof(FixedString32Bytes)) { TestValueTypeNativeList( new NativeList(Allocator.Persistent) { new FixedString32Bytes("foobar"), new FixedString32Bytes("12345678901234567890123456789") }, new NativeList(Allocator.Persistent) { new FixedString32Bytes("BazQux"), new FixedString32Bytes("98765432109876543210987654321"), new FixedString32Bytes("FixedString32Bytes") }); } } #endif } }