Skip to content

Commit a17d8bb

Browse files
authored
fix: registry of public NetworkVariables in derived NetworkBehaviours (#2423)
1 parent 86889a3 commit a17d8bb

File tree

4 files changed

+145
-5
lines changed

4 files changed

+145
-5
lines changed

.editorconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ root = true
22

33
[*]
44
charset = utf-8
5+
max_line_length = off
56

67
[*.cs]
78
# spacing rules

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
2222

2323
### Fixed
2424

25+
- Fixed registry of public `NetworkVariable`s in derived `NetworkBehaviour`s (#2423)
2526
- Fixed issue where changes to a layer's weight would not synchronize unless a state transition was occurring.(#2399)
2627
- Fixed issue where `NetworkManager.LocalClientId` was returning the `NetworkTransport.ServerClientId` as opposed to the `NetworkManager.m_LocalClientId`. (#2398)
2728
- 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)

com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -570,13 +570,10 @@ private static FieldInfo[] GetFieldInfoForTypeRecursive(Type type, List<FieldInf
570570
if (list == null)
571571
{
572572
list = new List<FieldInfo>();
573-
list.AddRange(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
574-
}
575-
else
576-
{
577-
list.AddRange(type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
578573
}
579574

575+
list.AddRange(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
576+
580577
if (type.BaseType != null && type.BaseType != typeof(NetworkBehaviour))
581578
{
582579
return GetFieldInfoForTypeRecursive(type.BaseType, list);

com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariableTests.cs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4+
using System.Linq;
45
using UnityEngine.TestTools;
56
using NUnit.Framework;
67
using Unity.Collections;
@@ -1377,4 +1378,144 @@ public NetworkListTestPredicate(NetworkVariableTest player1OnServer, NetworkVari
13771378
}
13781379
}
13791380
}
1381+
1382+
[TestFixtureSource(nameof(TestDataSource))]
1383+
public class NetworkVariableInheritanceTests : NetcodeIntegrationTest
1384+
{
1385+
public NetworkVariableInheritanceTests(HostOrServer hostOrServer)
1386+
: base(hostOrServer)
1387+
{
1388+
}
1389+
1390+
protected override int NumberOfClients => 2;
1391+
1392+
public static IEnumerable<TestFixtureData> TestDataSource() =>
1393+
Enum.GetValues(typeof(HostOrServer)).OfType<HostOrServer>().Select(x => new TestFixtureData(x));
1394+
1395+
public class ComponentA : NetworkBehaviour
1396+
{
1397+
public NetworkVariable<int> PublicFieldA = new NetworkVariable<int>(1);
1398+
protected NetworkVariable<int> m_ProtectedFieldA = new NetworkVariable<int>(2);
1399+
private NetworkVariable<int> m_PrivateFieldA = new NetworkVariable<int>(3);
1400+
1401+
public void ChangeValuesA(int pub, int pro, int pri)
1402+
{
1403+
PublicFieldA.Value = pub;
1404+
m_ProtectedFieldA.Value = pro;
1405+
m_PrivateFieldA.Value = pri;
1406+
}
1407+
1408+
public bool CompareValuesA(ComponentA other)
1409+
{
1410+
return PublicFieldA.Value == other.PublicFieldA.Value &&
1411+
m_ProtectedFieldA.Value == other.m_ProtectedFieldA.Value &&
1412+
m_PrivateFieldA.Value == other.m_PrivateFieldA.Value;
1413+
}
1414+
}
1415+
1416+
public class ComponentB : ComponentA
1417+
{
1418+
public NetworkVariable<int> PublicFieldB = new NetworkVariable<int>(11);
1419+
protected NetworkVariable<int> m_ProtectedFieldB = new NetworkVariable<int>(22);
1420+
private NetworkVariable<int> m_PrivateFieldB = new NetworkVariable<int>(33);
1421+
1422+
public void ChangeValuesB(int pub, int pro, int pri)
1423+
{
1424+
PublicFieldB.Value = pub;
1425+
m_ProtectedFieldB.Value = pro;
1426+
m_PrivateFieldB.Value = pri;
1427+
}
1428+
1429+
public bool CompareValuesB(ComponentB other)
1430+
{
1431+
return PublicFieldB.Value == other.PublicFieldB.Value &&
1432+
m_ProtectedFieldB.Value == other.m_ProtectedFieldB.Value &&
1433+
m_PrivateFieldB.Value == other.m_PrivateFieldB.Value;
1434+
}
1435+
}
1436+
1437+
public class ComponentC : ComponentB
1438+
{
1439+
public NetworkVariable<int> PublicFieldC = new NetworkVariable<int>(111);
1440+
protected NetworkVariable<int> m_ProtectedFieldC = new NetworkVariable<int>(222);
1441+
private NetworkVariable<int> m_PrivateFieldC = new NetworkVariable<int>(333);
1442+
1443+
public void ChangeValuesC(int pub, int pro, int pri)
1444+
{
1445+
PublicFieldC.Value = pub;
1446+
m_ProtectedFieldA.Value = pro;
1447+
m_PrivateFieldC.Value = pri;
1448+
}
1449+
1450+
public bool CompareValuesC(ComponentC other)
1451+
{
1452+
return PublicFieldC.Value == other.PublicFieldC.Value &&
1453+
m_ProtectedFieldC.Value == other.m_ProtectedFieldC.Value &&
1454+
m_PrivateFieldC.Value == other.m_PrivateFieldC.Value;
1455+
}
1456+
}
1457+
1458+
private GameObject m_TestObjectPrefab;
1459+
private ulong m_TestObjectId = 0;
1460+
1461+
protected override void OnServerAndClientsCreated()
1462+
{
1463+
m_TestObjectPrefab = CreateNetworkObjectPrefab($"[{nameof(NetworkVariableInheritanceTests)}.{nameof(m_TestObjectPrefab)}]");
1464+
m_TestObjectPrefab.AddComponent<ComponentA>();
1465+
m_TestObjectPrefab.AddComponent<ComponentB>();
1466+
m_TestObjectPrefab.AddComponent<ComponentC>();
1467+
}
1468+
1469+
protected override IEnumerator OnServerAndClientsConnected()
1470+
{
1471+
var serverTestObject = SpawnObject(m_TestObjectPrefab, m_ServerNetworkManager).GetComponent<NetworkObject>();
1472+
m_TestObjectId = serverTestObject.NetworkObjectId;
1473+
1474+
var serverTestComponentA = serverTestObject.GetComponent<ComponentA>();
1475+
var serverTestComponentB = serverTestObject.GetComponent<ComponentB>();
1476+
var serverTestComponentC = serverTestObject.GetComponent<ComponentC>();
1477+
1478+
serverTestComponentA.ChangeValuesA(1000, 2000, 3000);
1479+
serverTestComponentB.ChangeValuesA(1000, 2000, 3000);
1480+
serverTestComponentB.ChangeValuesB(1100, 2200, 3300);
1481+
serverTestComponentC.ChangeValuesA(1000, 2000, 3000);
1482+
serverTestComponentC.ChangeValuesB(1100, 2200, 3300);
1483+
serverTestComponentC.ChangeValuesC(1110, 2220, 3330);
1484+
1485+
yield return WaitForTicks(m_ServerNetworkManager, 2);
1486+
}
1487+
1488+
private bool CheckTestObjectComponentValuesOnAll()
1489+
{
1490+
var serverTestObject = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjectId];
1491+
var serverTestComponentA = serverTestObject.GetComponent<ComponentA>();
1492+
var serverTestComponentB = serverTestObject.GetComponent<ComponentB>();
1493+
var serverTestComponentC = serverTestObject.GetComponent<ComponentC>();
1494+
foreach (var clientNetworkManager in m_ClientNetworkManagers)
1495+
{
1496+
var clientTestObject = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjectId];
1497+
var clientTestComponentA = clientTestObject.GetComponent<ComponentA>();
1498+
var clientTestComponentB = clientTestObject.GetComponent<ComponentB>();
1499+
var clientTestComponentC = clientTestObject.GetComponent<ComponentC>();
1500+
if (!serverTestComponentA.CompareValuesA(clientTestComponentA) ||
1501+
!serverTestComponentB.CompareValuesA(clientTestComponentB) ||
1502+
!serverTestComponentB.CompareValuesB(clientTestComponentB) ||
1503+
!serverTestComponentC.CompareValuesA(clientTestComponentC) ||
1504+
!serverTestComponentC.CompareValuesB(clientTestComponentC) ||
1505+
!serverTestComponentC.CompareValuesC(clientTestComponentC))
1506+
{
1507+
return false;
1508+
}
1509+
}
1510+
1511+
return true;
1512+
}
1513+
1514+
[UnityTest]
1515+
public IEnumerator TestInheritedFields()
1516+
{
1517+
yield return WaitForConditionOrTimeOut(CheckTestObjectComponentValuesOnAll);
1518+
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, nameof(CheckTestObjectComponentValuesOnAll));
1519+
}
1520+
}
13801521
}

0 commit comments

Comments
 (0)