From 90cf5631c95b3ef5c82185856c9b8cbada72d688 Mon Sep 17 00:00:00 2001 From: Fatih Mar Date: Fri, 24 Feb 2023 19:06:28 +0300 Subject: [PATCH 1/3] fix: register public networkvariable fields of derived networkbehaviour classes --- .../Runtime/Core/NetworkBehaviour.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs index b532a786ca..a254e8c78b 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs @@ -570,13 +570,10 @@ private static FieldInfo[] GetFieldInfoForTypeRecursive(Type type, List(); - list.AddRange(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)); - } - else - { - list.AddRange(type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)); } + list.AddRange(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)); + if (type.BaseType != null && type.BaseType != typeof(NetworkBehaviour)) { return GetFieldInfoForTypeRecursive(type.BaseType, list); From daa0ce5e31b11f1e0e2b64fb2970074edc7ada49 Mon Sep 17 00:00:00 2001 From: Fatih Mar Date: Fri, 24 Feb 2023 19:11:16 +0300 Subject: [PATCH 2/3] update changelog --- com.unity.netcode.gameobjects/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index bad40daedc..b281f613bd 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -22,6 +22,7 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Fixed +- Fixed registry of public `NetworkVariable`s in derived `NetworkBehaviour`s (#2423) - Fixed issue where changes to a layer's weight would not synchronize unless a state transition was occurring.(#2399) - Fixed issue where `NetworkManager.LocalClientId` was returning the `NetworkTransport.ServerClientId` as opposed to the `NetworkManager.m_LocalClientId`. (#2398) - Fixed issue where a dynamically spawned `NetworkObject` parented under an in-scene placed `NetworkObject` would have its `InScenePlaced` value changed to `true`. This would result in a soft synchronization error for late joining clients. (#2396) From b8864491eaf4bb42f3894e50ef9ac1e034c8e764 Mon Sep 17 00:00:00 2001 From: Fatih Mar Date: Sat, 25 Feb 2023 00:21:32 +0300 Subject: [PATCH 3/3] implement tests --- .editorconfig | 1 + .../Tests/Runtime/NetworkVariableTests.cs | 141 ++++++++++++++++++ 2 files changed, 142 insertions(+) diff --git a/.editorconfig b/.editorconfig index a7454ebef4..d5858086a3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -2,6 +2,7 @@ root = true [*] charset = utf-8 +max_line_length = off [*.cs] # spacing rules diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariableTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariableTests.cs index dfc7a0f7d1..7bab89d30e 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariableTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariableTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Linq; using UnityEngine.TestTools; using NUnit.Framework; using Unity.Collections; @@ -1377,4 +1378,144 @@ public NetworkListTestPredicate(NetworkVariableTest player1OnServer, NetworkVari } } } + + [TestFixtureSource(nameof(TestDataSource))] + public class NetworkVariableInheritanceTests : NetcodeIntegrationTest + { + public NetworkVariableInheritanceTests(HostOrServer hostOrServer) + : base(hostOrServer) + { + } + + protected override int NumberOfClients => 2; + + public static IEnumerable TestDataSource() => + Enum.GetValues(typeof(HostOrServer)).OfType().Select(x => new TestFixtureData(x)); + + public class ComponentA : NetworkBehaviour + { + public NetworkVariable PublicFieldA = new NetworkVariable(1); + protected NetworkVariable m_ProtectedFieldA = new NetworkVariable(2); + private NetworkVariable m_PrivateFieldA = new NetworkVariable(3); + + public void ChangeValuesA(int pub, int pro, int pri) + { + PublicFieldA.Value = pub; + m_ProtectedFieldA.Value = pro; + m_PrivateFieldA.Value = pri; + } + + public bool CompareValuesA(ComponentA other) + { + return PublicFieldA.Value == other.PublicFieldA.Value && + m_ProtectedFieldA.Value == other.m_ProtectedFieldA.Value && + m_PrivateFieldA.Value == other.m_PrivateFieldA.Value; + } + } + + public class ComponentB : ComponentA + { + public NetworkVariable PublicFieldB = new NetworkVariable(11); + protected NetworkVariable m_ProtectedFieldB = new NetworkVariable(22); + private NetworkVariable m_PrivateFieldB = new NetworkVariable(33); + + public void ChangeValuesB(int pub, int pro, int pri) + { + PublicFieldB.Value = pub; + m_ProtectedFieldB.Value = pro; + m_PrivateFieldB.Value = pri; + } + + public bool CompareValuesB(ComponentB other) + { + return PublicFieldB.Value == other.PublicFieldB.Value && + m_ProtectedFieldB.Value == other.m_ProtectedFieldB.Value && + m_PrivateFieldB.Value == other.m_PrivateFieldB.Value; + } + } + + public class ComponentC : ComponentB + { + public NetworkVariable PublicFieldC = new NetworkVariable(111); + protected NetworkVariable m_ProtectedFieldC = new NetworkVariable(222); + private NetworkVariable m_PrivateFieldC = new NetworkVariable(333); + + public void ChangeValuesC(int pub, int pro, int pri) + { + PublicFieldC.Value = pub; + m_ProtectedFieldA.Value = pro; + m_PrivateFieldC.Value = pri; + } + + public bool CompareValuesC(ComponentC other) + { + return PublicFieldC.Value == other.PublicFieldC.Value && + m_ProtectedFieldC.Value == other.m_ProtectedFieldC.Value && + m_PrivateFieldC.Value == other.m_PrivateFieldC.Value; + } + } + + private GameObject m_TestObjectPrefab; + private ulong m_TestObjectId = 0; + + protected override void OnServerAndClientsCreated() + { + m_TestObjectPrefab = CreateNetworkObjectPrefab($"[{nameof(NetworkVariableInheritanceTests)}.{nameof(m_TestObjectPrefab)}]"); + m_TestObjectPrefab.AddComponent(); + m_TestObjectPrefab.AddComponent(); + m_TestObjectPrefab.AddComponent(); + } + + protected override IEnumerator OnServerAndClientsConnected() + { + var serverTestObject = SpawnObject(m_TestObjectPrefab, m_ServerNetworkManager).GetComponent(); + m_TestObjectId = serverTestObject.NetworkObjectId; + + var serverTestComponentA = serverTestObject.GetComponent(); + var serverTestComponentB = serverTestObject.GetComponent(); + var serverTestComponentC = serverTestObject.GetComponent(); + + serverTestComponentA.ChangeValuesA(1000, 2000, 3000); + serverTestComponentB.ChangeValuesA(1000, 2000, 3000); + serverTestComponentB.ChangeValuesB(1100, 2200, 3300); + serverTestComponentC.ChangeValuesA(1000, 2000, 3000); + serverTestComponentC.ChangeValuesB(1100, 2200, 3300); + serverTestComponentC.ChangeValuesC(1110, 2220, 3330); + + yield return WaitForTicks(m_ServerNetworkManager, 2); + } + + private bool CheckTestObjectComponentValuesOnAll() + { + var serverTestObject = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjectId]; + var serverTestComponentA = serverTestObject.GetComponent(); + var serverTestComponentB = serverTestObject.GetComponent(); + var serverTestComponentC = serverTestObject.GetComponent(); + foreach (var clientNetworkManager in m_ClientNetworkManagers) + { + var clientTestObject = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjectId]; + var clientTestComponentA = clientTestObject.GetComponent(); + var clientTestComponentB = clientTestObject.GetComponent(); + var clientTestComponentC = clientTestObject.GetComponent(); + if (!serverTestComponentA.CompareValuesA(clientTestComponentA) || + !serverTestComponentB.CompareValuesA(clientTestComponentB) || + !serverTestComponentB.CompareValuesB(clientTestComponentB) || + !serverTestComponentC.CompareValuesA(clientTestComponentC) || + !serverTestComponentC.CompareValuesB(clientTestComponentC) || + !serverTestComponentC.CompareValuesC(clientTestComponentC)) + { + return false; + } + } + + return true; + } + + [UnityTest] + public IEnumerator TestInheritedFields() + { + yield return WaitForConditionOrTimeOut(CheckTestObjectComponentValuesOnAll); + Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, nameof(CheckTestObjectComponentValuesOnAll)); + } + } }