簡體   English   中英

如何在 Unity 中將對象序列化為 JSON

[英]How to serialise Object to JSON in Unity

我正在嘗試使用嵌套類、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? 然后我需要二進制紋理將其保存在文本文件中。 它不是運行時對象。

將紋理作為字節數組存儲在 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 並使其真正可讀。

我認為你不能序列化圖像本身。 它已加載到內存中,圖像是參考。

另一件事是,如果您更改紋理的任何屬性,它將生成一個新的,也會失去原始紋理的參考。

您可以做的是使用紋理名稱創建另一個數組,然后在加載 JSon 時應用。

您的方法看起來不錯 - 我認為它失敗是因為 UnityEngine 的內部工作原理,其中部分數據位於托管/c# 端,部分位於本機/c++ 端。 紋理變得更加復雜,如果它們被標記為可讀,則它們可以存在於 GPU 上,也可以同時存在於 Ram/GPU 中。 最奇怪的情況是渲染紋理,它完美地生活在邊緣,並且有一些奇怪的行為(即,即使您丟失引用,它們也不會被垃圾收集)。

解決方法似乎很簡單 - 制作一個可序列化的 byte[] 字段,用編碼紋理(或您所做的 zip)填充它 - 甚至可能提前(在您序列化之前)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM