Editor Script, Index Out of Range Exception after Play

Can somebody explain me why a CustomEditor based script is working fine in Editor Mode, but when I switch to PlayMode it throws me back a Index Out of Range Exception?


    IndexOutOfRangeException: Array index is out of range.
TerrainPrototypesGroupManagerEDITOR.OnInspectorGUI () (at Assets/Editor/TerrainPrototypesGroupManagerEDITOR.cs:50)
UnityEditor.InspectorWindow.DrawEditor (UnityEditor.Editor[] editors, Int32 editorIndex, Boolean rebuildOptimizedGUIBlock, System.Boolean& showImportedObjectBarNext, UnityEngine.Rect& importedObjectBarRect) (at /Users/builduser/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:1374)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
     
     //my struct, where the error appears. 
         [System.Serializable]public struct list_TreeInstances {[SerializeField]public List < TreeInstance > m_TreeInstances;}

I’ve got a second struct which is kind of identical, but uses a GameObject instead of TreeInstance, where I don’t have the null reference. Could this be because its properly used with a SerializedProperty in Inspector? like:



 //_GO_Groups is an Array ( list_GameObject[] _GO_Groups = new list_GameObject[0];)
 SerializedProperty s_GO_Groups = serializedObject.FindProperty("_GO_Groups");
     
     // example
      SerializedProperty s0 = s_GO_Groups.GetArrayElementAtIndex(master).FindPropertyRelative("m_GameObjects");
                 for(int i = 0; i<s0.arraySize;i++){
                     SerializedProperty s1 = s0.GetArrayElementAtIndex(i);
                         if(s1.objectReferenceValue != null){
                             EditorGUILayout.PropertyField(s1,new GUIContent(_TPGM._GO_Groups[master].m_GameObjects*.name));*

}
----------
Well final and important Question, whats the best way to find the Source of causing this trouble?
Sorry to tag you but, I know you both are Genius in this @JVene @Bunny83
----------
full code is [here][1] if needed
[1]: GitHub - danwipf/TerrainPrototypeGroupManager: Source Code of TPGM

Unity’s TreeInstance struct is not serializable. The TerrainData class is implemented in native code and is serialized in native code. The managed class is just a wrapper of the serialized native data.

When you read the treeInstances property you actually call a native method which returns the instances from native code.

So since the struct isn’t marked with the Serializable attribute it’s not a managed type that the Unity serializer can serialize. Therefore the List<TreeInstance> is not a serializable type either. That means whenever your data needs to be serialized / deserialized this will not be included. When you enter playmode everything gets serialized and reloaded from serialized data. That means your List will be null since it can’t be serialized. You may need to create a wrapper type that can be serialized which holds the same information as the TreeInstance struct and copy the data as needed.

edit

As i said in the comment below, i would implement the conversion inside your wrapper struct. Since this is only for serialization i would use a constructor for the creation of the wrapper and an implicit conversion operator to turn our wrapper back to a TreeInstance value.

[System.Serializable]
public struct TreeInstanceArray
{
    public Vector3 position;
    public float widthScale;
    public float heightScale;
    public float rotation;
    public Color32 color;
    public Color32 lightmapColor;
    public int prototypeIndex;
    public TreeInstanceArray(TreeInstance aTree)
    {
        position = aTree.position;
        widthScale = aTree.widthScale;
        heightScale = aTree.heightScale;
        rotation = aTree.rotation;
        color = aTree.color;
        lightmapColor = aTree.lightmapColor;
        prototypeIndex = aTree.prototypeIndex;
    }
    public static implicit operator TreeInstance (TreeInstanceArray aTree)
    {
        TreeInstance inst = new TreeInstance;
        inst.position = aTree.position;
        inst.widthScale = aTree.widthScale;
        inst.heightScale = aTree.heightScale;
        inst.rotation = aTree.rotation;
        inst.color = aTree.color;
        inst.lightmapColor = aTree.lightmapColor;
        inst.prototypeIndex = aTree.prototypeIndex;
        return inst;
    }
}

Now if you have a “TreeInstanceArray” value you can simply assign or use it where a TreeInstance value would be required.

TreeInstanceArray serializedValue = new TreeInstanceArray();

// this will trigger the implicit conversion
TreeInstance tree = serializedValue;

List<TreeInstance> trees;
// this will also trigger the implicit conversion
trees.Add(serializedValue);

To turn a TreeInstance into a “TreeInstanceArray”, just use the constructor:

TreeInstanceArray serializedValue = new TreeInstanceArray(someTreeInstance);