• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
Question by rwhalt · Jan 05 at 04:32 AM · serializationdictionaryserializeserializablekeys

How to use OnBeforeSerialize() and OnAfterDeserialize() to convert Dictionaries

So how do I use OnBeforeSerialize() and OnAfterDeserialize() on a dictionary? I know that I have to convert it to an array of keys and an array of what I want to be serialized, but how would I use this? Wouldn't it just say that you can't convert a dictionary to two arrays when I'll try to use it? Please explain to me how this works. Thank you! I'm sorry if I sound impatient.

Comment

People who like this

0 Show 0
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

  • Sort: 
avatar image
Best Answer

Answer by Bunny83 · Jan 06 at 07:25 AM

OnBeforeSerialize and OnAfterDeserialize should simply do the opposite from each other. So in OnBeforeSerialize you would copy the data from the actual dictionary into the structure that can actually be serialized so when Unity does serialized the object afterwards, the actual data is preserved in that extra structure. In OnAfterDeserialize you would do the opposite. That means you copy the data back from your structure that was serialized by Untiy back into the dictionary. That's all. You would still use your dictionary just as it is.


ps: I would not recommend using two seperate arrays or Lists for the keys and the values. It would make more sense when you use your own key-value pair struct or class and create one List or array of that type. Of course that class / struct needs to be serializable. Using one array / List makes it easier to reconstruct the dictionary from that list as you just have to go through the list and you always have the key and value paired properly. With seierate arrays things can easily go wrong when you for example delete one key in the inspector.


Specifically you can do something like this:

 [System.Serializable]
 public class DictionaryWrapper<TKey, TValue> : ISerializationCallbackReceiver
 {
     [System.Serializable]
     public class KeyValue
     {
         public TKey key;
         public TValue value;
     }
 
     private Dictionary<TKey, TValue> m_Dict = new Dictionary<TKey, TValue>();
     public Dictionary<TKey, TValue> Dict => m_Dict;
 
     [SerializeField]
     private List<KeyValue> m_Data = new List<KeyValue>();
 
     public void OnAfterDeserialize()
     {
         m_Dict.Clear();
         foreach(var kv  in m_Data)
             m_Dict.Add(kv.key, kv.value);
     }
 
     public void OnBeforeSerialize()
     {
         m_Data.Clear();
         foreach (var kv in m_Dict)
             m_Data.Add(new KeyValue { key = kv.Key, value = kv.Value });
     }
 }

You can use this class instead of a Dictionary in a MonoBehaviour or ScriptableObject. Just access the "Dict" property of the class and use it like a dictionary. Of course you can simply edit the serialized entries in the inspector which is there just a List of "KeyValue" instances.


Regardless of this, there's rarely really a usecase for serializing a dictionary. A lot don't seem to really understand when to use a dictionary. A Dictionary is a data structure for a fast look ups at runtime.

Comment
rwhalt

People who like this

1 Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image rwhalt · Jan 06 at 02:10 PM 0
Share

Thank you so much! I haven't tested it yet, but it looks like it might work. I'll comment again if it doesn't, but I gave you 5 points, whatever those do.

avatar image rwhalt · Jan 07 at 01:22 AM 0
Share

And yes, I am using it in a case I feel is essential. I have a dictionary of serializable Vector3s for a Minecraft-like game, and this is the chest system. Each time a chest is created, a list of items in the chest are put into a dictionary with the chest position, and if people were to place thousands of chests, it would have loop through all of them otherwise, which would not be efficient, especially on a server.

avatar image

Answer by rwhalt · Jan 07 at 01:56 AM

Bro, I was messing around with @Bunny83 's code and discovered how to look at the code for system classes, and copying some of that, I was able to add a little to his code. Hope it helps!

 [System.Serializable]
 public class DictionaryWrapper<TKey, TValue> : ISerializationCallbackReceiver
 {
     [System.Serializable]
     public class KeyValue
     {
         public TKey key;
         public TValue value;
     }
 
     private Dictionary<TKey, TValue> m_Dict = new Dictionary<TKey, TValue>();
     public Dictionary<TKey, TValue> Dict => m_Dict;
 
     public bool ContainsKey(TKey kay)
     {
         return m_Dict.ContainsKey(kay);
     }
 
     public void Add(TKey kay, TValue val)
     {
         m_Dict.Add(kay, val);
     }
 
     public TValue this[TKey index] { get => m_Dict[index]; }
 
     [SerializeField]
     private List<KeyValue> m_Data = new List<KeyValue>();
 
     public void OnAfterDeserialize()
     {
         m_Dict.Clear();
         foreach (var kv in m_Data)
             m_Dict.Add(kv.key, kv.value);
     }
 
     public void OnBeforeSerialize()
     {
         m_Data.Clear();
         foreach (var kv in m_Dict)
             m_Data.Add(new KeyValue { key = kv.Key, value = kv.Value });
     }
 }
Comment

People who like this

0 Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image rwhalt · Jan 07 at 04:46 PM 0
Share

@DearUnityPleaseAddSerializableDictionaries I think you should see this

avatar image DearUnityPleaseAddSerializableDictionaries · Jan 07 at 07:40 PM 1
Share

@rwhalt pog

Unity Answers is in Read-Only mode

Unity Answers content will be migrated to a new Community platform and we are aiming to launch a public beta by June 9. Please note, Unity Answers is now in read-only so we can prepare for the final data migration.

For more information and updates, please read our full announcement thread in the Unity Forum.

Follow this Question

Answers Answers and Comments

157 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

PublicKeyToken=null' is not marked as serializable 1 Answer

Dictionary serialization woes 2 Answers

Save and Load all spawned objects in their position using array 1 Answer

Private Variables Serialised By Default 2 Answers

Serialize a Dictionary 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges