Serialization depth limit 7 exceeded

To later simplify some things for my current project I am first creating a custom EditorWindow tool. Since I want to be able to save its current state (to make it survive entering/leaving play-mode or restarting Unity without always resetting) I have created a settings-object that gets saved and is supposed to hold all the data.

However, it seems that my current implementation results in the warning “Serialization depth limit 7 exceeded”. The data structure looks like this: alt text (Hierarchy on the left for inheritance, arrows for references to instances of a type)

Basically when opening the TilesetEditor it loads the TilesetEditorSettings object. In there is a list of 1-n TilesetEditorPanels which each have their own few references to some PanelElements (e.g. Grid, Texture, Zoom). Since some PanelEements need to access data from other elements (e.g. Texture needs to be scaled according to Zoom) they have a reference to their containing Panel (lower upward-travelling arrow). Also it will later be necessary to acess other Panels (e.g. to check if a drag started in a different Panel than the one it ended in) which is why there is a referene to the TilesetEditor in order to get to the Settings (upper upward-travelling arrow).

From my understanding of the serializaton manual page those upward-travelling references are the problem, since they lead to endless loops when deserializing (which then get interrupted by the warning).

The question is how to best resolve this.

I suppose one way would be to derive my TilesetEditorElement class from ScriptableObject as well, since apparently references to those types can be resolved properly. The downsize though would be that apart from the Settings object I’d also need to save all objects which then derive from TilesetEditorElement into an Assets folder, which could get a bit messy. Also it means that I couldnt use a normal constructor with parameters anymore so I’d need to use the ScriptableObject.Instantiate method and a custom Init method to set up the parameters.

Or is there maybe a better approach?

Well, the solution is to flatten the hierarchy of your TilesetEditorElements. That means yout TilesetEditorSettings class would simple store a linear list of TilesetEditorElements which will include all elements in a linear list. You can still use your current setup, just make sure all those references are not serialized. Instead your classes can implement the “ISerializationCallbackReceiver” interface which allows you to pre / post process your class instance when serialized / deserialized. So you can still handle your objects in a hierarchical structure at “runtime” which is not serialized. Inside “OnBeforeSerialize” you will actually iterate your whole tree structure and place each TilesetEditorElement in a linear List which will be serialized. Of course you also need to add a way to restore the parent element for each item. For this you can use a simple integer variable which stores the index into your linear list.

In “OnAfterDeserialize” you just have to reverse the process. Iterate through the list and restore the actual references between the classes.

The back reference to the editor shouldn’t be serialized at all. As i have understood your setup the TilesetEditorSettings class is meant to be stored as asset. However an editorwindow shouldn’t be stored in an asset and therefore can’t be referenced from your TilesetEditorSettings asset. Since you usually only have one TilesetEditor window open you may use a static singleton reference for the editor window reference if you need it.