【问题标题】:How to serialise Object to JSON in Unity如何在 Unity 中将对象序列化为 JSON
【发布时间】:2019-01-23 12:32:52
【问题描述】:

我正在尝试用嵌套类、AudioClip 和 texture2D 序列化一个巨大的类。我实现了 ISerializable 接口并用 SerializableAttribute 标记了所有类。我使用 JsonUtility 转换为 Json 并返回。

除了 Textures2D、Textures2D[] 和 AudioClip 之外,一切都运行良好。 ISerializable 方法的实现如下:

[Serializable]
public class Illustration : ISerializable
{
    public Texture2D Image = new Texture2D(256, 256);

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue(nameof(Image), Image.EncodeToPNG(), typeof(byte[]));
    }

    private Illustration(SerializationInfo info, StreamingContext context)
    {
        Image.LoadImage(info.GetValue(nameof(Image), typeof(byte[])) as byte[]);
    }
}

[Serializable]
public class CustomAnimation : ISerializable
{
    public Texture2D[] Images;

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue(nameof(Images), Images.Select(x => x.EncodeToPNG()).ToArray(), typeof(byte[][]));
    }

    private CustomAnimation(SerializationInfo info, StreamingContext context)
    {
        var textures = info.GetValue(nameof(Images), typeof(byte[][])) as byte[][];
        if (textures != null)
        {
            var imagesAndTextures = Images.Zip(textures, (i, t) => new {Images = i, textures = t});
            foreach (var it in imagesAndTextures)
            {
                it.Images.LoadImage(it.textures);
            }
        }
    }
}

我希望这段代码能用纹理的字节数组创建一个 JSON,但我明白了:

"Illustrations": [
                {
                    "Image": {
                        "instanceID": 34540
                    }
                }
]

为什么我有这个 instanceID?然后我需要二进制纹理将其保存在文本文件中。它不是运行时对象。

【问题讨论】:

  • 我在这个答案中举了一个例子link

标签: c# unity3d serialization json-serialization


【解决方案1】:

将纹理作为字节数组存储在json中不是一个好主意,没有人这样做,这一定是有原因的。

如果你真的需要,那么你需要纹理中的字节数组,很可能是 jpeg,所以它更小:

byte [] tex = texture.EncodeToJpg();
var str = System.Text.Encoding.Default.GetString(tex);
JsonObject json = new JsonObject();   // pseudo code for a json parser
json.Add("Illustration", str);

反之亦然:

string str = json.GetString("Illustration");
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(str);

但实际上做的方式,json只包含图片的url。

将纹理存储为字符串化字节数组几乎没有什么目的,因为 jpg 已经是一个 txt 文件,其中包含最有可能作为二进制的字节数组。因此,使用第二种方法,您将拆分 json 并使其真正可读。

【讨论】:

    【解决方案2】:

    我认为您无法序列化图像本身。已加载到内存中,图片为参考。

    另一件事是,如果您更改纹理的任何属性,它会生成一个新的,也会失去原来的参考。

    您可以做的是创建另一个具有纹理名称的数组,然后在加载 JSon 时应用。

    【讨论】:

      【解决方案3】:

      您的方法看起来不错 - 我认为它失败是因为 UnityEngine 的内部工作原理,其中部分数据位于托管/c# 端,部分位于本机/c++ 端。纹理变得更加复杂,如果它们被标记为可读,它们可以存在于 GPU 上,也可以同时存在于 Ram/GPU 中。最奇怪的情况是渲染纹理,它完美地存在于边缘,并且有一些奇怪的行为(即,即使您失去参考,它们也不会被垃圾收集)。

      解决方法似乎很简单——创建一个可序列化的 byte[] 字段,用编码纹理(或你所做的 zip)填充它——甚至可以提前(在你序列化之前)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-09-08
        • 2013-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多