Skip to content

Commit 0b29662

Browse files
authored
fix: NetworkVariable subclasses not generating serialization code (#2421)
1 parent d70dcbb commit 0b29662

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed

com.unity.netcode.gameobjects/Editor/CodeGen/NetworkBehaviourILPP.cs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,58 @@ private void GetAllFieldsAndResolveGenerics(TypeDefinition type, ref List<TypeRe
837837
GetAllFieldsAndResolveGenerics(resolved, ref fieldTypes, genericParams);
838838
}
839839

840+
private void GetAllBaseTypesAndResolveGenerics(TypeDefinition type, ref List<TypeReference> baseTypes, Dictionary<string, TypeReference> genericParameters)
841+
{
842+
843+
if (type.BaseType == null || type.BaseType.Name == "Object")
844+
{
845+
return;
846+
}
847+
848+
var baseType = type.BaseType;
849+
850+
var genericParams = new Dictionary<string, TypeReference>();
851+
852+
if (baseType.IsGenericInstance)
853+
{
854+
var genericType = (GenericInstanceType)baseType;
855+
var newGenericType = new GenericInstanceType(baseType.Resolve());
856+
for (var i = 0; i < genericType.GenericArguments.Count; ++i)
857+
{
858+
var argument = genericType.GenericArguments[i];
859+
860+
if (genericParameters != null && genericParameters.ContainsKey(argument.Name))
861+
{
862+
newGenericType.GenericArguments.Add(genericParameters[argument.Name]);
863+
genericParams[baseType.Resolve().GenericParameters[newGenericType.GenericArguments.Count - 1].Name] = genericParameters[argument.Name];
864+
}
865+
else
866+
{
867+
newGenericType.GenericArguments.Add(argument);
868+
}
869+
}
870+
baseTypes.Add(newGenericType);
871+
}
872+
else
873+
{
874+
baseTypes.Add(baseType);
875+
}
876+
877+
var resolved = type.BaseType.Resolve();
878+
if (type.BaseType.IsGenericInstance)
879+
{
880+
var genericType = (GenericInstanceType)type.BaseType;
881+
for (var i = 0; i < genericType.GenericArguments.Count; ++i)
882+
{
883+
if (!genericParams.ContainsKey(resolved.GenericParameters[i].Name))
884+
{
885+
genericParams[resolved.GenericParameters[i].Name] = genericType.GenericArguments[i];
886+
}
887+
}
888+
}
889+
GetAllBaseTypesAndResolveGenerics(resolved, ref baseTypes, genericParams);
890+
}
891+
840892
private void ProcessNetworkBehaviour(TypeDefinition typeDefinition, string[] assemblyDefines)
841893
{
842894
var rpcHandlers = new List<(uint RpcMethodId, MethodDefinition RpcHandler)>();
@@ -898,6 +950,34 @@ private void ProcessNetworkBehaviour(TypeDefinition typeDefinition, string[] ass
898950
}
899951
}
900952
}
953+
{
954+
var baseTypes = new List<TypeReference>();
955+
956+
var genericParams = new Dictionary<string, TypeReference>();
957+
var resolved = type.Resolve();
958+
if (type.IsGenericInstance)
959+
{
960+
var genericType = (GenericInstanceType)type;
961+
for (var i = 0; i < genericType.GenericArguments.Count; ++i)
962+
{
963+
genericParams[resolved.GenericParameters[i].Name] = genericType.GenericArguments[i];
964+
}
965+
}
966+
967+
GetAllBaseTypesAndResolveGenerics(type.Resolve(), ref baseTypes, genericParams);
968+
foreach (var baseType in baseTypes)
969+
{
970+
if (baseType.Resolve().Name == typeof(NetworkVariable<>).Name || baseType.Resolve().Name == typeof(NetworkList<>).Name)
971+
{
972+
var genericInstanceType = (GenericInstanceType)baseType;
973+
var wrappedType = genericInstanceType.GenericArguments[0];
974+
if (!m_WrappedNetworkVariableTypes.Contains(wrappedType))
975+
{
976+
m_WrappedNetworkVariableTypes.Add(wrappedType);
977+
}
978+
}
979+
}
980+
}
901981
}
902982
}
903983

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,22 @@ public class NetVarPermTestComp : NetworkBehaviour
1818
public NetworkVariable<Vector3> OwnerReadWrite_Position = new NetworkVariable<Vector3>(Vector3.one, NetworkVariableReadPermission.Owner, NetworkVariableWritePermission.Owner);
1919
}
2020

21+
public class NetworkVariableMiddleclass<TMiddleclassName> : NetworkVariable<TMiddleclassName>
22+
{
23+
24+
}
25+
26+
public class NetworkVariableSubclass<TSubclassName> : NetworkVariableMiddleclass<TSubclassName>
27+
{
28+
29+
}
30+
31+
public struct TemplatedValueOnlyReferencedByNetworkVariableSubclass<T> : INetworkSerializeByMemcpy
32+
where T : unmanaged
33+
{
34+
public T Value;
35+
}
36+
2137
// The ILPP code for NetworkVariables to determine how to serialize them relies on them existing as fields of a NetworkBehaviour to find them.
2238
// Some of the tests below create NetworkVariables on the stack, so this class is here just to make sure the relevant types are all accounted for.
2339
public class NetVarILPPClassForTests : NetworkBehaviour
@@ -26,6 +42,7 @@ public class NetVarILPPClassForTests : NetworkBehaviour
2642
public NetworkVariable<ManagedNetworkSerializableType> ManagedNetworkSerializableTypeVar;
2743
public NetworkVariable<string> StringVar;
2844
public NetworkVariable<Guid> GuidVar;
45+
public NetworkVariableSubclass<TemplatedValueOnlyReferencedByNetworkVariableSubclass<int>> SubclassVar;
2946
}
3047

3148
public class TemplateNetworkBehaviourType<T> : NetworkBehaviour
@@ -1097,6 +1114,21 @@ public void TestUnsupportedUnmanagedTypesThrowExceptions()
10971114
});
10981115
}
10991116

1117+
[Test]
1118+
public void TestTypesReferencedInSubclassSerializeSuccessfully()
1119+
{
1120+
var variable = new NetworkVariableSubclass<TemplatedValueOnlyReferencedByNetworkVariableSubclass<int>>();
1121+
using var writer = new FastBufferWriter(1024, Allocator.Temp);
1122+
var value = new TemplatedValueOnlyReferencedByNetworkVariableSubclass<int> { Value = 12345 };
1123+
variable.Value = value;
1124+
variable.WriteField(writer);
1125+
variable.Value = new TemplatedValueOnlyReferencedByNetworkVariableSubclass<int> { Value = 54321 };
1126+
1127+
using var reader = new FastBufferReader(writer, Allocator.None);
1128+
variable.ReadField(reader);
1129+
Assert.AreEqual(value.Value, variable.Value.Value);
1130+
}
1131+
11001132
[Test]
11011133
public void TestUnsupportedUnmanagedTypesWithUserSerializationDoNotThrowExceptions()
11021134
{

0 commit comments

Comments
 (0)