官方文档有个MonoBehaviour的字典序列化,但不能用。 ??????UnityEngine.ISerializationCallbackReceiver - Unity 脚本 API
using UnityEngine;
using System;
using System.Collections.Generic;
public class SerializationCallbackScript : MonoBehaviour, ISerializationCallbackReceiver
{
public List<int> _keys = new List<int> { 3, 4, 5 };
public List<string> _values = new List<string> { "I", "Love", "Unity" };
//Unity doesn't know how to serialize a Dictionary
public Dictionary<int, string> _myDictionary = new Dictionary<int, string>();
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<int, string>();
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<int> _keys = new List<int> { 3, 4, 5 };
public List<string> _values = new List<string> { "I", "Love", "Unity" };
//Unity doesn't know how to serialize a Dictionary
public Dictionary<int, string> _myDictionary = new Dictionary<int, string>();
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<int> _keys = new List<int>();
[SerializeField]
private List<string> _values = new List<string>();
//Unity doesn't know how to serialize a Dictionary
private Dictionary<int, string> _myDictionary = new Dictionary<int, string>();
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>("ScriptDict");
Debug.LogError(sd[0]);
}
// Update is called once per frame
void Update()
{
}
}
|