Weird Bug: Properties in Class are skipped in for loop.

In the Editor it works perfectly. Building for Windows/Steam it breaks in a weird way.

I store the game config in an XML file and on start I load the data into a configuration class. This works fine in the editor when I play the game. But building a Debug build, the loop skips “id” and several other properties from other config classes as well.

Debug build, Code compiled as debug in player settings. il2cpp and net 2.0.

Here is one of the classes that hold the game data. I know I could have used a Struct…

public class CharacterData
{
    public int id { get; set; }
    public string prefab { get; set; }
    public string name { get; set; }
    public int currency { get; set; }
    public int price { get; set; }
    public int strength { get; set; }
    public int thrown { get; set; }
    public string special { get; set; }
    public string biography { get; set; }
}

And a snippet where the error happens. This works in Editor. Basically I store the properties in a temporary Dictionary for fast lookup later on when I parse the XML.

// This section serializes the XML into a class that is of an unknown type and unknown members.
        // Loop through properties to get class information into a lookup table.
        foreach (PropertyInfo property in properties)
        {
            Debug.Log("property Name: " + property.Name);
            propertyLookup[property.Name] = property; // <--- THIS FAILS RANDOMLY FOR WINDOWS BUILD
        }

        // Since all the XML elements should be identical.
        foreach (XmlElement node in baseNode.ChildNodes)
        {
            TRECORD tmpClass = new TRECORD();
            foreach (XmlAttribute attrib in node.Attributes)
            {
                Debug.Log("XML Attribute Name: " + attrib.Name);
                if (propertyLookup.ContainsKey(attrib.Name))
                    classType.GetProperty(attrib.Name).SetValue(tmpClass, Convert.ChangeType(attrib.Value, propertyLookup[attrib.Name].PropertyType)); // lots of stuff just to assign an unknown variable and type.
                else
                    Debug.LogError("Property not found: " + attrib.Name);
            }
            Debug.Log(keyName + " " + (TKEY)classType.GetProperty(keyName).GetValue(tmpClass) + " " + node.Name);
            dictRecord[(TKEY)classType.GetProperty(keyName).GetValue(tmpClass)] = tmpClass;
        }

Here’s the Unity Log snippet from Windows:

ClassType Name: CharacterData
UnityEngine.Logger:Log(LogType, Object)
UnityEngine.Debug:Log(Object)
d__432:MoveNext() UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr) <InitConfig>d__28:MoveNext() UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr) ConfigManager:Awake() property Name: prefab UnityEngine.Logger:Log(LogType, Object) UnityEngine.Debug:Log(Object) <SerializeXMLData>d__432:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
d__28:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
ConfigManager:Awake()
property Name: name
UnityEngine.Logger:Log(LogType, Object)
UnityEngine.Debug:Log(Object)
d__432:MoveNext() UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr) <InitConfig>d__28:MoveNext() UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr) ConfigManager:Awake() ... ... ... XML Attribute Name: id UnityEngine.Logger:Log(LogType, Object) UnityEngine.Debug:Log(Object) <SerializeXMLData>d__432:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
d__28:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
ConfigManager:Awake()
Property not found: id
0x00007fffc1ddbf1c (UnityPlayer)
0x00007fffc1de1639 (UnityPlayer)
0x00007fffc1dc24e8 (UnityPlayer)

Could be a code stripping thing? If those properties aren’t used maybe IL2CPP is stripping them.

That was the solution. Stripping was set to High. I changed it to low.

I also added a directive to the top of my code per Unity docs. Since I’m dealing with “reflection” and accessing the class as a “TRECORD”, The compiler thought several properties were not used. “id” was used as the key to the dictionary of classes.

I’m a coder, yet compiler stuff is still a grand mystery to me, since I just let it do it’s thing and it usually just works.

using UnityEngine.Scripting;

[assembly: Preserve]