Weirdness with serializing classes

Issue #204 resolved
Steamroller Studios created an issue

Code

using System;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using Sirenix.Serialization;

[Serializable]
public class Nested
{
    [ShowInInspector]
    // Tried [SerializeField] and [OdinSerialize]
    public Dictionary<string, object> nested;
}

public class Test : SerializedMonoBehaviour
{
    public Dictionary<string, object> foo;
    public Nested bar;
}

Results

NestedDictionary.png

When trying to include a class as a variable on my Test class i get some weird behavior.

  • Its able to draw the dictionary properly on the Test class but not the Nested classes dictionary
  • If you try and add this to a GameObject then try and make it a prefab, the object in the scene will lose the entire nested dictionary
  • If you then make a dictionary on the nested dictionary in the prefab and then drag the prefab into the scene, It will lose it there too.

Please let me know if there is something I'm doing wrong or if this simply cant be done.

Comments (2)

  1. Tor Esa Vestergaard

    Odin is scarce in its serialization - on the root level, on the actual component, Odin will pick and choose which things to serialize, to serialize as little as possible and leave the rest to Unity. When it does this, it will skip over anything that it knows Unity will serialize. This is both in the interests of performance and avoiding unnecessary serialization work, and in the interests of backwards compatibility, so that adding Odin serialization to a component of yours doesn't change the serialization of your pre-existing data, instead just adding extra options to it.

    However, since what is being serialized is decided on the root level, the nested dictionary will never be serialized, since Odin determines that the "bar" field is of type "Nested" which Unity can serialize - which means it will be serialized by Unity - and proceeds to leave it alone.

    As a rule of thumb, if you have to use [ShowInInspector] to make something show up in the inspector, that is because it is not being serialized. [ShowInInspector], by the way, will only cause something to be shown. It does not cause anything to be serialized. That's why, despite being shown, the dictionary value is reset every time you reload, instantiate the object, etc.

    There are a variety of solutions - you can remove [Serializable] from the Nested class, preventing Unity from serializing it, so that Odin takes over (Odin has no such requirement). You could mark the bar field with [OdinSerialize], forcing Odin to serialize it regardless of whether Unity will or not. See this FAQ answer for a thorough list of examples of how Odin's serialization picks and chooses.

  2. Log in to comment