官方文档有个MonoBehaviour的字典序列化,但不能用。
UnityEngine.ISerializationCallbackReceiver - Unity 脚本 API
using UnityEngine;
using System;
using System.Collections.Generic;
public class SerializationCallbackScript : MonoBehaviour, ISerializationCallbackReceiver
{
public List _keys = new List { 3, 4, 5 };
public List _values = new List { "I", "Love", "Unity" };
//Unity doesn't know how to serialize a Dictionary
public Dictionary _myDictionary = new Dictionary();
public void OnBeforeSerialize()
{
_keys.Clear();
_values.Clear();
foreach (var kvp in _myDictionary)
{
_keys.Add(kvp.Key);
_values.Add(kvp.Value);
}
}
public void OnAfterDeserialize()
{
_myDictionary = new Dictionary();
for (int i = 0; i != Math.Min(_keys.Count, _values.Count); i++)
_myDictionary.Add(_keys[i], _values[i]);
}
void OnGUI()
{
foreach (var kvp in _myDictionary)
GUILayout.Label("Key: " + kvp.Key + " value: " + kvp.Value);
}
}
自己改写了一版能用的。
using UnityEngine;
using System;
using System.Collections.Generic;
public class SerializationCallbackScript : MonoBehaviour, ISerializationCallbackReceiver
{
public List _keys = new List { 3, 4, 5 };
public List _values = new List { "I", "Love", "Unity" };
//Unity doesn't know how to serialize a Dictionary
public Dictionary _myDictionary = new Dictionary();
public void OnBeforeSerialize()
{
foreach (var kvp in _myDictionary)
{
if (!_keys.Contains(kvp.Key))
{
_keys.Add(kvp.Key);
_values.Add(kvp.Value);
}
else
{
int idx = _keys.IndexOf(kvp.Key);
if (idx >= _values.Count)
{
_values.Add(kvp.Value);
}
else
{
_values[idx] = kvp.Value;
}
}
}
}
public void OnAfterDeserialize()
{
_myDictionary.Clear();
int count = Math.Min(_keys.Count, _values.Count);
for (int i = 0; i < count; i++)
{
_myDictionary[_keys[i]] = _values[i];
}
}
void OnGUI()
{
foreach (var kvp in _myDictionary)
GUILayout.Label("Key: " + kvp.Key + " value: " + kvp.Value);
}
}
顺便写了一版ScriptableObject的
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(menuName = "CreateScriptableObject/Dict")]
public class ScriptDict : ScriptableObject, ISerializationCallbackReceiver
{
[SerializeField]
private List _keys = new List();
[SerializeField]
private List _values = new List();
//Unity doesn't know how to serialize a Dictionary
private Dictionary _myDictionary = new Dictionary();
public void OnBeforeSerialize()
{
// _keys.Clear();
// _values.Clear();
foreach (var kvp in _myDictionary)
{
if (!_keys.Contains(kvp.Key))
{
_keys.Add(kvp.Key);
_values.Add(kvp.Value);
}
else
{
int idx = _keys.IndexOf(kvp.Key);
if (idx >= _values.Count)
{
_values.Add(kvp.Value);
}
else
{
_values[idx] = kvp.Value;
}
}
}
}
public void OnAfterDeserialize()
{
_myDictionary.Clear();
int count = Math.Min(_keys.Count, _values.Count);
for (int i = 0; i < count; i++)
{
_myDictionary[_keys[i]] = _values[i];
}
}
public string this[int k]
{
get
{
string v = string.Empty;
_myDictionary.TryGetValue(k, out v);
return v;
}
set
{
_myDictionary[k] = value;
}
}
}
测试加载代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestLoadScript : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
var sd = Resources.Load("ScriptDict");
Debug.LogError(sd[0]);
}
// Update is called once per frame
void Update()
{
}
}



