Search Unity

Bug NetworkVariables fail to initialize for inherited ancestor classes

Discussion in 'Netcode for GameObjects' started by KingKRoecks, Jan 21, 2023.

  1. KingKRoecks

    KingKRoecks

    Joined:
    Jul 28, 2013
    Posts:
    155
    example:

    public class A : NetworkBehavior {
    NetworkVariable<int> someValA = new();
    }

    public class B : class A {
    NetworkVariable<int> someValB = new();
    }


    When the NetworkBehavior Initializes variables, it don't check the nested classes.

    Code (CSharp):
    1. var sortedFields = GetFieldInfoForType(GetType());
    2.             for (int i = 0; i < sortedFields.Length; i++)
    3.             {
    4.                 var fieldType = sortedFields[i].FieldType;
    5.                 if (fieldType.IsSubclassOf(typeof(NetworkVariableBase)))
    6.                 {
    7.                     var instance = (NetworkVariableBase)sortedFields[i].GetValue(this);
    8.  
    9.                     if (instance == null)
    10.                     {
    11.                         throw new Exception($"{GetType().FullName}.{sortedFields[i].Name} cannot be null. All {nameof(NetworkVariableBase)} instances must be initialized.");
    12.                     }
    13.                    
    14.                     instance.Initialize(this);
    15.  
    16.                     var instanceNameProperty = fieldType.GetProperty(nameof(NetworkVariableBase.Name));
    17.                     var sanitizedVariableName = sortedFields[i].Name.Replace("<", string.Empty).Replace(">k__BackingField", string.Empty);
    18.                     instanceNameProperty?.SetValue(instance, sanitizedVariableName);
    19.  
    20.                     NetworkVariableFields.Add(instance);
    21.                 }
    22.             }

    The "GetType" is getting the reflected fields for just that type. If there's an inheritance structure, it won't get the other classes between the Type and NetworkBehavior.

    I solved it by making a while loop and iterating up the class hierarchy until the NetworkBehavior class is reached:
    Code (CSharp):
    1. var curType = GetType();
    2.             while (curType != typeof(NetworkBehaviour))
    3.             {
    4.                 var sortedFields = GetFieldInfoForType(curType);
    5.                 for (int i = 0; i < sortedFields.Length; i++)
    6.                 {
    7.                     var fieldType = sortedFields[i].FieldType;
    8.                     if (fieldType.IsSubclassOf(typeof(NetworkVariableBase)))
    9.                     {
    10.                         var instance = (NetworkVariableBase)sortedFields[i].GetValue(this);
    11.  
    12.                         if (instance == null)
    13.                         {
    14.                             throw new Exception($"{GetType().FullName}.{sortedFields[i].Name} cannot be null. All {nameof(NetworkVariableBase)} instances must be initialized.");
    15.                         }
    16.  
    17.                         instance.Initialize(this);
    18.  
    19.                         Debug.Log($"InitializeVariables {name} {curType} - {instance}");
    20.  
    21.                         var instanceNameProperty = fieldType.GetProperty(nameof(NetworkVariableBase.Name));
    22.                         var sanitizedVariableName = sortedFields[i].Name.Replace("<", string.Empty).Replace(">k__BackingField", string.Empty);
    23.                         instanceNameProperty?.SetValue(instance, sanitizedVariableName);
    24.  
    25.                         NetworkVariableFields.Add(instance);
    26.                     }
    27.                 }
    28.  
    29.                 curType = curType.BaseType;
    30.             }
     
  2. RikuTheFuffs-U

    RikuTheFuffs-U

    Unity Technologies

    Joined:
    Feb 20, 2020
    Posts:
    440
    Hi @KingKRoecks , thanks for highlighting the issue and sharing the code. Would it be possible for you to open a bug report here? In this way, the team behind Netcode For GameObject will be able to prioritize your fix, and you'll be automatically updated about its status.