解释如何在Unity中处理JSON [Json Utility]

如果您是一名程序员,则可能知道或听说过JSON数据的格式。但是,由于在很多情况下都使用了它,所以将库用于不同的语言和环境往往是一个好主意。此外,某些库还存在诸如不支持功能之类的陷阱。因此,这次,我将解释如何处理由Unity正式支持的Json Utility,注意事项和补救措施。

什么是JSON

施工

JSON:Javascript对象表示法的缩写,实际上是基于javascript数据结构。
JSON将键和值作为一个集合保存,但是由于您可以在该值中嵌套一个数组或一个互锁数组,因此可以在结构上拥有数据。
让我们看一下Json的每个元素。

关联数组

{}是一个关联数组,以key:value的形式描述数据。如果有多个此类数据,请用逗号(,)将其连接。

{
    HP:10,
    ATK:29,
    name: "enemy1"
},
{
    HP:13,
    ATK:43,
    name: "enemy2"
}

数组

[]以保留顺序保存数组中相同类型的数据。如果有多个数据,请将它们与(,)连接。

[1,2,3]

组合

JSON仅具有上述结构。因此,很难记住,
通过组合以上内容,可以分层地描述复杂信息。
例如,让我们用JSON表示多个敌人的信息。

{
    enemies:[
        {
            name: "enemy1"
            HP:10,
            ATK:29,
        },
        {
            name: "enemy2"
            HP:13,
            ATK:43,
        }
    ]
}

上面是敌人信息的JSON表示形式。

JSON的好处

现在,您已经对JSON有了一个概述,您可能会认为CSV(如果您不了解,可以考虑一下Excell)就可以了。
确实如此。但是,JSON的最大优点是,即使具有不规则结构的数据也可以轻松表示。
例如,在CSV的情况下,由于简单地按顺序排列数据,因此不描述这些关系。
如果特定元素丢失或奇怪,则无法检测到。
例如,它看起来像这样

name,flag
enemy1,on
enemy2,off
enemy3

上面是敌人及其标志的CSV描述。
如果设置了标志,则将其打开;如果未设置,则将其设置为关闭。我不敢在敌人3的旗帜上写任何东西。
以这样的速度,我不知道敌人3的标志是什么,但这对csv的描述很好。
但是,当将其作为游戏数据传递时,情况就不同了。直到执行并加载数据后,才知道此数据丢失。结果,如果发生错误并停止错误会更好,但是如果出现问题,则需要大量时间来查找原因。如您所见,在CSV中,\”flag\”由于它没有对应于开/关的信息,因此它可能会意外移动。

JSON相对于上面的优势在于它可以表示数据的结构。
您可以通过将键和值作为一组来描述关系。
因此,如果没有任何价值,您可以放心结构已损坏,并且会立即引发错误。

如何在Untiy中使用Json Utility

现在,您已经对JSON有了一个概述,让我们看一下如何在Untiy中使用JSON。
Unity官员提供了处理JSON的对象杰森公司使用。
这很快,但是它有一些局限性和不足的功能。让我们看看这些与实际用法。

类到JSON的转换

首先,让我们看看如何将类转换为JSON格式。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class jsonClass : MonoBehaviour {

    // Use this for initialization
    public int HP = 1;
    public int ATK = 3;
    public string name = "hello";

	void Start () {
        Debug.Log(JsonUtility.ToJson(this));
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}

这是整个代码。

    public int HP = 1;
    public int ATK = 3;
    public string name = \"hello\";

这部分定义了类的字段。您说过JSON有一个键和一个值作为集合。
对于JsonUtility,变量名称:存储在变量中的值
通过该方法进行转换。

    Debug.Log(JsonUtility.ToJson(this));

上面的JsonUtility.ToJson是一个将类转换为Json并将该类的实例作为参数的函数。
在这种情况下,实际运行的jsonClass会在该类内部进行转换,因此它会以此方式传递。

为了确认这一点,我使用Debug.log将其输出到控制台屏幕。

尝试将此脚本粘贴到合适的对象中并运行它。

从杰森上课

从Json转换为类有两种方法。这也有一些烦人的问题。
让我们用实际的例子来解释。

生成类并返回实例

jsonUtility类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using JsonData;



public class JsonClass : MonoBehaviour {

    // Use this for initialization
    public int HP = 1;
    public int ATK = 3;
    public string name = "hello";

	void Start () {
        JsonDataClass jsonDataClass;

        string jsonString = "{\"HP\":12,\"ATK\":6,\"name\":\"asdf\"}";
        jsonDataClass = 杰森公司.FromJson<JsonDataClass>(jsonString);
        
        Debug.Log(jsonDataClass.ATK);
        Debug.Log(jsonDataClass.name);
        Debug.Log(jsonDataClass.HP);
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}

资料储存类别

namespace JsonData
{
    public class JsonDataClass
    {
        public int HP;
        public int ATK;
        public string name;
    }
}

它采用json格式的字符串,并创建其类的新实例。
首先,作为前提,这次我们将根据json生成一个类,因此让我们首先定义一个专用于Json数据存储的类。
就是这个JsonDataClass。

让我们实际看一下代码。请参阅jsonUtility使用的类。

        string jsonString = "{\"HP\":12,\"ATK\":6,\"name\":\"asdf\"}";

首先,创建一个Json字符串。我存储了价值,

        jsonDataClass = 杰森公司.FromJson<JsonDataClass>(jsonString);

C#只能先定义类型,所以
您必须提供要生成的类的类型信息。
因此,给出泛型生成的类的类型信息。然后将json字符串作为参数传递,以将值放入生成的类中。
请检查debug.log作为试用版。您可以看到该值已存储。

但是,此功能存在严重缺陷。
最重要的是,如果创建类实例的目标继承自MonoBehavior,类生成失败。
我将省略它,因为详细解释很长,但是在使用Unity函数时,必须继承MonoBehavior,并且这种继承会导致各种限制。
例如,当尝试创建实例或读取数据时,该操作将因此失败。

这可能有点令人困惑,但是问题是“立即上新班级”。因此,由于它已经生成或超出范围,所以即使您在上一个示例或以下示例中将MonoBehaivor定位为目标,它也可以正常工作。

覆盖现有变量

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class JsonClass : MonoBehaviour {

    // Use this for initialization
    public int HP = 1;
    public int ATK = 3;
    public string name = "hello";

	void Start () {
        //JsonClass jsonClass = Instantiate(JsonClass);
        string jsonString = "{\"HP\":12,\"ATK\":6,\"name\":\"asdf\"}";
        杰森公司.FromJsonOverwrite(jsonString, this);
        Debug.Log(this.ATK);
        Debug.Log(this.name);
        Debug.Log(this.HP);
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}

作为Overwrite的名称,它存储从json提取的第二个参数的数据。
换句话说,它将通过覆盖现有变量的值来实现。

        string jsonString = "{\"HP\":12,\"ATK\":6,\"name\":\"asdf\"}";
        杰森公司.FromJsonOverwrite(jsonString, this);

我像以前一样制作了一个json字符串,但是这次我将覆盖现有的json字符串而不创建一个新的json字符串。所以我没有在泛型中指定类型
相反,它包含覆盖Json字符串的类的实例。
当执行此函数时,它不返回返回值,而是通过引用传递来重写第二个参数的实例。
请尝试检查Debug.log的内容。它已被更改。

如果不转换为Json

到目前为止,我已经解释了一般用法,但是我还将介绍一些注意事项,例如无法将其转换为json时。最大的警告是,即使无法将类中的字段转换为Json
杰森公司不会引发错误并忽略它。结果,它无意地表现并导致错误,并且非常麻烦,因为除非执行它才能确定。
因此,我将说明不进行转换的情况。

最重要的是,如果变量无法序列化,则无法转换。
我将省略对序列化的解释,因为它会很长,但是简单来说,可以将其视为将类的数据(二进制)转换为可以存储数据的形式(文本)。
详细规格
//docs.unity3d.com/ja/current/Manual/script-Serialization.html
//docs.unity3d.com/ja/current/Manual/JSONSerialization.html

请阅读以上两个。但是,这很麻烦,因此我将至少列出那些移动的对象。
粗略地说,如果满足以下条件,它将不会转换。

  • 私人的(例外)
  • const
  • 静态的
  • 非序列化字段
  • 只读
  • 字典
  • 抽象类
  • 等等

但是,对于私有,您可以通过添加[SerializeField]来序列化该字段。
检查要点如下。

    1.访问级别
    2.类型可序列化吗?
    3.如果使用ToJson函数,是否继承自MonoBehavior?

是重点。如果它不能转换为Json,请检查以上内容。

其他图书馆

无论多快,都有一些限制很烦人。特别地,根据情况使用诸如字典的数据类型是困难的。
我还将介绍另一个Json库。

Json.NET
一个用于处理C#中著名的Json的库。
这是字典也可以使用因此,如果遇到麻烦,可以选择它。
处理速度本身比Json Utility慢,但是我认为您可以正常使用它,除非您在需要性能的环境中。

实际例子

最后,让我们考虑一个简单游戏的实现。在这种情况下,请考虑一款新颖的游戏。
这次,让我们考虑一下这些因素。

  • 站立图片
  • 对话
  • 背景

考虑一个JSON,它包含一个动作(每次加载背景,站立图片和对话)的每条信息。
首先要考虑的是拥有什么信息以及采用什么形式。
例如
我在本地具有背景,那么为什么不指向本地文件名呢?
让我们对站立图片上的信息进行相同的操作。
让我们按原样加载行
让我们考虑一下您拥有什么样的信息,以及如何接收和处理它。

因此,此类和JSON的结构为

资料储存类别

    // ローカルの背景ファイル名
    public string background;
    // ローカルの立ち絵ファイル名
    public string standChara;
    // 对话の文字列
    public string[] serif;

比方说

让我们考虑一个实际使用该数据的类。
必须继承MonoBehavior,因为该类实际上反映了Unity中的数据。
最重要的是,您可以访问Ui和图像等对象,因此

使用的班级

    // 对话表示用のゲームオブジェクト例
    public GameObject UIText
    // 背景表示用のゲームオブジェクト例
    public GameObject UIImage
    // 站立图片キャラのゲームオブジェクト例
    public GameObject UIChara

    void Start () {
        string jsonString = "{\"background\":\"normal\",\"standChara\":[\"chara_plate\"],\"serif\":[\"hello\",\"test\"]}";
        NovelData novelData = 杰森公司.FromJson<NovelData>(jsonString);
        // 画像を変更したり・・・・ 
	}

就像那样。

我要考虑的是

string jsonString = "{\"background\":\"normal\",\"standChara\":[\"chara_plate\"],\"serif\":[\"hello\",\"test\"]}";

这是其中的一部分。在此类中一个接一个地编写json是一件愚蠢的事,因此您必须考虑加载或生成Json。换句话说,您可以自己创建一个新颖的游戏引擎。

如何加载JSON数据

最后,我将解释如何加载json。
其中有几种,但是这次我们将介绍将数据放置在服务器上和本地的典型示例。

API

JSON是REST API。当您点击URL时,REST API将以JSON格式返回结果。因此,在上述新颖游戏引擎的示例中,数据存储在另一台服务器上,并通过API以json格式获取。
如您所见,这假定您正在与服务器上的数据进行通信。
另外,由于这种结构很重要,因此有许多示例。
如果您想与服务器通信,则可以在练习后尝试使其与服务器通信。

本地文件

第二种方法是将JSON作为文件存储在本地并读取。但是,即使JSON可以在结构上处理数据,但手动无休止地编辑JSON还是很麻烦的。因此,存在一种以人类易于处理的数据格式编辑数据并将其最终转换为JSON的方法。最著名的示例是将在Excel中以CSV格式编辑的文件转换为json格式。这样做的好处是可以在本地完成,因此轻松进行测试和编辑就不会麻烦。如果要决定设计和功能,让我们在本地进行实验。

概要

怎么样。 JSON是一种非常易于使用的数据处理工具。但是,这就是为什么JSON结构的设计以及应该使用它的部分变得非常重要的原因。顺便说一下,实现示例的新颖游戏的示例是我上大学时由作者制作的。如果按原样放置,它将被加载很多次,并且有些部分可能是反复试验的结果,因此,让我们通过根据自己的游戏重复进行练习来获得最佳实践。

撰写本文的人

assa

我是京都的工程师。记住assa或eh。 我的主要业务是在网上玩我的业余爱好。有什么好的