- Home /
Serialization depth limit 7 exceeded with linked-list-like data structure
I'm working on a custom editor window that has a node that connects to another node and so on.
I save and load from a file with serialization(system.serializable) and I don't have any problem with this part until now.
The problem came up when I made a recursive function to draw lines between nodes. This recursion loops through a list of next nodes from a node to draw lines and continue until reaches null terminations. The warning message came up in Unity like this :
Serialization depth limit 7 exceeded at '~~~::~~~.<~~~>k__BackingField'. There may be an object composition cycle in one or more of your serialized classes.
Serialization hierarchy: 8: ~~~.~~~::~~~.k_BackingField 7: ~~~.~~~::~~~.k_BackingField 6: ~~~.~~~::~~~.NextNodes 5: ~~~.~~~::~~~.NextNodes 4: ~~~.~~~::~~~.NextNodes 3: ~~~.~~~::~~~.NextNodes 2: ~~~.~~~::~~~.NextNodes 1: ~~~.~~~::~~~.NextNodes 0: ~~~.~~~::~~~.StartingNode
My question is what does this warning mean?
Can I ignore this warning? Will there be a problem in recursion itself?
Thank you in advance.
Answer by Adam-Mechtley · Aug 14, 2017 at 09:22 AM
The problem is that Unity's serializer cannot handle potentially infinitely deep data. Imagine something like this:
[Serializable]
class Node
{
[SerializeField]
List<Node> m_Children = new List<Node>();
}
Each of those children could keep having children, so Unity enforces an artificial serialization depth limit of 7. This warning is basically telling you that your data layout is not robust.
The way to work around it is to instead serialize some kind of identifier. For example:
[Serializable]
class Node
{
[SerializeField]
int m_ID;
[SerializeField]
List<int> m_ChildrenIDs = new List<int>();
}
Thank you. I did exactly that, using ID ins$$anonymous$$d of referencing classes, and warning message is gone. It gives me a question, though. Why did warning came up only when I used my data structure in a recursion and not before? Also my recursive method doesn't serialize or deserialize(save&load from db). It just gets values to draw lines. Shouldn't this be irrelevant to serialization?
There are a lot of factors at play so it is hard to say without knowing more details. I suggest referring to the documentation page on script serialization. For example, if you also added some private Node or List<Node> field on your EditorWindow, it would be subject to this rule:
When reloading scripts, Unity restores all variables - including private variables - that fulfill the requirements for serialization, even if a variable has no SerializeField attribute. In some cases, you specifically need to prevent private variables from being restored: For example, if you want a reference to be null after reloading from scripts. In this case, use the NonSerializable attribute.
I've read that before but your explanation made me better understand it now. I somehow thought Unity had nothing to do with it. Thank you again. This has been a good study.
Answer by mkgame · Nov 06, 2017 at 05:30 PM
But at all, if you make this workaround, the situation is the same, endless recursion can be made. Recursion for a node system is normal. I would recommend Unity developers to remove the warnings, or let us supress the warning in Unity settings and let give us a recursion limit. If this will be exceeded runtime, then a warning or error is appropriate. At least, let us supress the warning. I can remember me having similar issue in Java for a node system, where the call-stack buffer grew over 512 MB, but this was okay, it was necessary.
That's not possible. Unity's serialization system need to know the size of the serialized data ahead of time. That's the main reason why it doesn't support polymorphism and doesn't allow recursive structures to be serialized. In the beginning a structure like this had actually crashed Unity. Since then they implemented this sanity check. When they first implemented this limit there was no warning and tons of people complained that it simply stops working without any notice. Now it always displays the warning as you actually did something that isn't supported.
Don't get me wrong. There's no problem creating a node based recursive system in Unity. You just can't make it serializable.
I suggest you read the script serialization documentation carefully. You may also read through this forum thread.
If you need serializable nodes you have to do cross references like $$anonymous$$showed in his answer (by using IDs ins$$anonymous$$d of references). This way you have a single array with all nodes. Another way is to actually use either a $$anonymous$$onoBehaviour or ScriptableObject derived class as "Node". Those are / can be serialized as seperate assets and cross references are actually serialized correctly.
Answer by Aggressor · May 13, 2018 at 03:01 PM
For future reference you can use Odin Serializer:
http://www.sirenix.net/odininspector/manual/introduction/serialize-anything
Look at "Avoiding Unity's Infinite Depth Warning"
The one hangup is all your classes must extend from a SerializedScriptableObject which can be annoying for classes that are simple primitives and you now have to create extra objects for them. But its a better trade off to actually get rid of this issue.
Your answer
Follow this Question
Related Questions
Recursive serialization manual limit 1 Answer
Can a GameObject be serialized? 1 Answer