Skip to content

Instantly share code, notes, and snippets.

@bellicapax
Last active February 23, 2023 21:35
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bellicapax/0838bfa4cff863d07baf78644a6a6b9b to your computer and use it in GitHub Desktop.
Save bellicapax/0838bfa4cff863d07baf78644a6a6b9b to your computer and use it in GitHub Desktop.
Serializable Dictionary base for Unity
using UnityEngine;
namespace System.Collections.Generic
{
[Serializable]
public abstract class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
{
protected abstract List<SerializableKeyValuePair<TKey, TValue>> _keyValuePairs { get; set; }
// save the dictionary to lists
public void OnBeforeSerialize()
{
_keyValuePairs.Clear();
foreach (KeyValuePair<TKey, TValue> pair in this)
{
_keyValuePairs.Add(new SerializableKeyValuePair<TKey, TValue>(pair.Key, pair.Value));
}
}
// load dictionary from lists
public void OnAfterDeserialize()
{
this.Clear();
for (int i = 0; i < _keyValuePairs.Count; i++)
{
this[_keyValuePairs[i].Key] = _keyValuePairs[i].Value;
}
}
}
// Based on SerializableTuple from https://github.com/neuecc/SerializableDictionary
[Serializable]
public class SerializableKeyValuePair<TKey, TValue> : IEquatable<SerializableKeyValuePair<TKey, TValue>>
{
[SerializeField]
TKey _key;
public TKey Key { get { return _key; } }
[SerializeField]
TValue _value;
public TValue Value { get { return _value; } }
public SerializableKeyValuePair()
{
}
public SerializableKeyValuePair(TKey key, TValue value)
{
this._key = key;
this._value = value;
}
public bool Equals(SerializableKeyValuePair<TKey, TValue> other)
{
var comparer1 = EqualityComparer<TKey>.Default;
var comparer2 = EqualityComparer<TValue>.Default;
return comparer1.Equals(_key, other._key) &&
comparer2.Equals(_value, other._value);
}
public override int GetHashCode()
{
var comparer1 = EqualityComparer<TKey>.Default;
var comparer2 = EqualityComparer<TValue>.Default;
int h0;
h0 = comparer1.GetHashCode(_key);
h0 = (h0 << 5) + h0 ^ comparer2.GetHashCode(_value);
return h0;
}
public override string ToString()
{
return String.Format("(Key: {0}, Value: {1})", _key, _value);
}
}
}
@juanitogan
Copy link

Note that borrowing the System.Collections.Generic namespace works while running in the editor, it crashes builds (at least with Unity 2017.4) with the following unhelpful log lines:

...
<RI> Initializing input.

<RI> Input initialized.

<RI> Initialized touch support.

The file 'C:/Unity/grits-win64/GRITS Racing demo/grits_Data/level0' is corrupted! Remove it and launch unity again!
[Position out of bounds!]
 
(Filename:  Line: 221)

Crash!!!
...

Using a unique namespace (like namespace SerializableCollections like neuecc uses) fixes it.

Otherwise, thank you for this. It has been super helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment