如何在Unity中序列化和反序列化包含Gameobject和Vector2的字典 [英] How to Serialize and Deserialize a Dictionary Containing Gameobject and a Vector2 in Unity

查看:173
本文介绍了如何在Unity中序列化和反序列化包含Gameobject和Vector2的字典的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为一款可以在单位编辑模式下编辑关卡的游戏制作关卡编辑器.最终它可以保存进度,可以在游戏运行时将其加载回去,但是事实证明,您无法统一地序列化Unity的Gameobject或任何自定义C#对象(即使如此).我能够序列化大多数内容,但是卡在一个Dictionary对象中.

现在,这是问题所在.

[HideInInspector]公共字典< GameObject,Vector2>居住者;

其中包含GameObject和Vector2的字典(Vector 2是2d网格中的位置,而不是2d空间中的位置).没有一个可以通过常规方法序列化的.

 公共静态无效SaveDataValues(DataValuesToSave dataValues,字符串级别){BinaryFormatter formatter = new BinaryFormatter();字符串路径= Application.persistentDataPath +级别+".dat";FileStream流=新的FileStream(path,FileMode.Create);DataValuesToSave data = dataValues;formatter.Serialize(流,数据);stream.Close();} 

如何序列化此词典?任何建议,将不胜感激.

解决方案

一般而言:

I am making a Level Editor for a game that can edit levels in unity's edit mode. It saves progress in the end which can be loaded back when the game is running, but turns out you cannot serialize Unity's Gameobject or any custom C# object by unity (Even if it says so). I was able to serialize most of the stuff but stuck with one Dictionary object.

Now, here is the problem.

[HideInInspector] public Dictionary<GameObject, Vector2> occupants;

This Contains a Dictionary of a GameObject and a Vector2 (Vector 2 is the position in 2d grid and not 2d space). None of it is serializable by the normal method.

 public static void SaveDataValues(DataValuesToSave dataValues, string level)
 {
     BinaryFormatter formatter = new BinaryFormatter();
     string path = Application.persistentDataPath + level + ".dat";
     FileStream stream = new FileStream(path, FileMode.Create);

     DataValuesToSave data = dataValues;

     formatter.Serialize(stream, data);
     stream.Close();
 }

How can I serialize this Dictionary? Any suggestions would be appreciated.

解决方案

Just in general: You shouldn't use BinaryFormatter anymore at all!


You can build a wrapper class implementing the ISerializationCallbackReceiver interface. In their example there is even almost your exact use case!

A slightly modified solution could look like e.g.

[Serializable]
public class YourDictionary: Dictionary<GameObject, Vector2>, ISerializationCallbackReceiver
{
    [HideInInspector][SerializeField] private List<GameObject> _keys = new List<GameObject>();
    [HideInInspector][SerializeField] private List<Vector2> _values = new List<Vector2>();

    public void OnBeforeSerialize()
    {
        _keys.Clear();
        _values.Clear();
    
        foreach (var kvp in this)
        {
            _keys.Add(kvp.Key);
            _values.Add(kvp.Value);
        }
    }
    
    public void OnAfterDeserialize()
    {
        Clear();
    
        for (var i = 0; i != Math.Min(_keys.Count, _values.Count); i++)
        {
            Add(_keys[i], _values[i]);
        }
    }
}

this way you keep the entire functionality of the dictionary and its interfaces but simply add the serialization on top.

and then in your other scripts you use

[HideInInspector] public YourDictionary occupants;

and use it just like a Dictionary<GameObject, Vector2> (I mean Add, Remove, Clear, foreach etc).


And here it is in action. I just used this simple test script

public class NewBehaviourScript : MonoBehaviour
{
    public GameObject obj;
    
    [HideInInspector] public YourDictionary occupants;

    [ContextMenu(nameof(Add))]
    private void Add()
    {
        Vector2 vec = obj.transform.position;
        occupants.Add(obj, vec);
    }

    [ContextMenu(nameof(Apply))]
    private void Apply()
    {
        foreach (var kvp in occupants)
        {
            kvp.Key.transform.position = kvp.Value;
        }
    }

    [ContextMenu(nameof(Remove))]
    private void Remove()
    {
        occupants.Remove(obj);
    }
}

and can now happily store, remove and apply positions for objects in the scene ;)

  • I first store 4 objects' positions.
  • Then I move them somewhere else and save the scene
  • I unload the scene and create a new empty scene
  • I load back the original scene
  • Result after hitting Apply all objects are back in position, which means that the dictionary was successfully (de)serialized ;)

这篇关于如何在Unity中序列化和反序列化包含Gameobject和Vector2的字典的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆