Unity使用JsonFX插件进行序列化

孙广东  2015.6.25

Unity and JSON – Quick Guide:

相比较XML的沉重和密集,Json更加高效。

Introduction:

什么是 Json ?
如果你从未使用过它,它的内部是字典结构。但你进行序列化和反序列化一些数据之后,你就会想知道他是怎么工作的。

Unity没有为 JSON 提供内置的解决方案。

获得Dark Table的 JsonFX:

Dark Table 已经创建了Unity中的解决方案, JsonFx.  你能得到 DLL 在这, if you want to follow along.

下载它,并且拖拽到Unity项目中,放到Plugins文件中。

Our Data Classes:
来自 JsonFx zip 文件中的readme 自述文件,里面有支持的数据类型的列表。我们会把它当作简单一些基元和数组 — — 只是为了演示功能。
我已经创建了几个用于此示例中的类。我们有一个叫做的 DataPC的类,这是我们要为我们的Player Controller存储的信息。还有提到的类名是 DataName 序列化的类。

我把这些作为数据类,因为他们的目的是要我的 JSON 文件,不是实际的类。换句话说,我也许会有一个类调用 PC 来处理游戏中的功能,但是我简单的 DataPC 类可以帮助存储和检索 json 格式的数据。这不需要通过任何手段。

我创建的第二类是 DataItem 类,存储特定item的数据。

public class DataPC
{
    public string name;
    public int maxLevel;
    public string description;
    public string portrait;

    public DataItem[] inventory;
}

public class DataItem
{
    public string name;
    public int cost;
}

在这里我们变得有点花哨: 我创建了一个 DataItem 数组来存储多个items。

Serializing the Data:
接下来,我已经成立了一个类,处理序列化和反序列化。:

using UnityEngine;
using System.Collections;
using JsonFx.Json;

public class DataHandlerTest : MonoBehaviour
{
    public DataPC myPC;
    void Start()
    {
        myPC = new DataPC();
        myPC.name = "Jimbob";
        myPC.maxLevel = 99;
        myPC.description = "Jimbob likes beer and trucks.";
        myPC.portrait = "jimbob.png";
        myPC.inventory = new DataItem[2];

        myPC.inventory[0] = new DataItem();
        myPC.inventory[1] = new DataItem();

        myPC.inventory[0].name = "Silver Bullet";
        myPC.inventory[0].cost = 5;

        myPC.inventory[1].name = "Shotgun";
        myPC.inventory[1].cost = 200;
    }

    public void OnGUI()
    {
        if (GUILayout.Button("SERIALIZE"))
        {
            string myJson = JsonWriter.Serialize(myPC);
            Debug.Log(myJson);
        }
    }
}

首先要注意的是我们需要包括 JsonFx 库: using JsonFx.Json
接下来,我们创建的 DataPC 的一个新实例并初始化其值。我们给它两个Items存入数组,初始化每个。

在 OnGUI() 方法中。

string myJson = JsonWriter.Serialize(myPC);
Debug.Log(myJson);

我们这里在做什么? 将类序列化为 Json 并成一个字符串保存该 Json。一旦我们有字符串,我们打印出来到debug log。

此方法的一个小问题是它生成 JSON 是一行的,没有排版结构的换行等。无格式。这意味着有大量的数据时它是有点难读的,但你可以把这个Copy到您选择的文本编辑器,你也可以使用一个基于 web 的工具来做这种。这将格式设置为、并验证 Json。

{
   "name":"Jimbob",
   "maxLevel":99,
   "description":"Jimbob likes beer and trucks.",
   "portrait":"jimbob.png",
   "inventory":[
      {
         "name":"Silver Bullet",
         "cost":5
      },
      {
         "name":"Shotgun",
         "cost":200
      }
   ]
}
	

JSON De/Serialization Using Unity and JsonFx:

目的:
        序列化数据的目的是使它可以存储或在不同的系统或甚至应用程序之间共享。它创建一个共同的数据模板,可以来回转换 (序列化和反序列化) 甚至当源数据是不被认为是由接收的系统或应用程序本身。有可以使用的各种常见格式 (即 XML,CSV,二进制文件中,或在我们的例子,JSON)、 序列化到数据。

在我们的示例中,我们要创建一个类,在我们的应用程序中;  当我们创建它的实例时,它将存在于内存中直到我们摧毁它或停止应用程序。一旦我们在 unity 编辑器 (或关闭我们build生成中的窗口)关闭播放play模式,该数据就丢失了。通过序列化,在这种情况下内容到一个文本文件,使用 JSON,我们可以将其存储到文件系统中,不仅我们可以脱机编辑和查看更改反映在我们的应用程序,当我们再次加载它。

Download the JsonFx DLL: here

步骤 1: 创建容器
容器是一个类用来在内存中存储您正在使用的数据。这不是唯一的方式做到这一点,但因为你读了我的向导,我的容器直接使用 C# 类。我们有:

Sandwich.cs

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

[System.Serializable]
public class Sandwich{
    public string name;
    public string bread;
    public float price;
    public List<string> ingredients = new List<string>();
}
	

只是注意字段都是public的,这一点很重要!  此外,[System.Serializable] 能为我们做两件事: 它允许 JsonFx 要序列化的字段,并且它还暴露在UNity的inspector面板上,将这些字段。
很简单,对吧?好吧,让我们继续前进。

第 2 步: 序列化 (Saving/Writing) 数据
将从代码中入手,然后我将解释。
JsonTutorial.cs

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Pathfinding.Serialization.JsonFx;
using System.IO;

public class JsonTutorial : MonoBehaviour {

    public string fileName;
    public Sandwich sandwich;

    private string PATH;

    private void Start() {
        PATH = Application.dataPath + "/../testData/";
    }
    private void OnGUI()   {
        if (GUILayout.Button("SAVE")){
            SerializeAndSave();
        }
    }

    private void SerializeAndSave() {
        string data = JsonWriter.Serialize(sandwich);
        if(!Directory.Exists(PATH)){
            Directory.CreateDirectory(PATH);
        }
        var streamWriter = new StreamWriter(PATH + fileName + ".txt");
        streamWriter.Write(data);
        streamWriter.Close();
    }
}

第一件事情就是包括 JsonFx dll 就像这样:

using Pathfinding.Serialization.JsonFx;

当然了具体的命名空间要根据DLL而定,如果你能够找到另一个版本的 dll,您将通过适当的命名空间 (即 JsonFx.Json)。
第二,我们包括 System.IO。这是因为我们会读取和写入文件。
我会简单地填写字段通过Inspectors。以便您稍后可以看到的输出。

没有必要给它扩展,因为你会注意到在 SerializeAndSave() 方法,我们给它一个自动化 (虽然你可以随时修改代码,以做到)。

接下来的几个字段也只是我们早些时候在容器中定义。
string data = JsonWriter.Serialize(sandwich);

那一行,就在那里处理序列化到一个文件中对sandwich对象。JsonFx 为我们处理繁重的工作。你可以 Debug.Log(data),看看它的样子,但我们要把它写到一个文件中无论如何,所以让我们继续。

下几行简单的核对是否我们指定的目录PATH路径存在,并且如果不存在就创建它。请注意,默认情况下,Application.dataPath 是项目的 /Assets 目录。我已经写到它下了,所以我只是去一个目录 (......),并将保存到一个目录中我 MyProject/ (这样, /Assets,基本上)。

StreamWriter 构造函数实际上采用的全路径,包括文件名。再次,你可以简单地省去手动添加".txt"扩展名,并让用户填写文件名变量,但随便。你将能够在文本编辑器中打开该文件,即使你没有给它的扩展。

测试它!
只是作为一个组件在任何场景中,拖拽 JsonTutorial 脚本,你会看到一个“SAVE”按钮 (记住 OnGUI )。单击按钮,并检查您的project 文件夹。能看到/testData 路径,无论名字是什么在 Inspectors 中 (在我的例子 my_data.txt) 中设置的文件,您应该看到一个 /testData 目录中。

基于我设计的sandwich,该文件将包含以下 JSON 作为文本 :

{ 

   "name": "meatball", 

   "bread": "white", 

   "price": 5.99, 

   "ingredients": [ 

      "metaballs", 

      "sauce", 

      "cheese" 

   ] 

}

我们可以甚至交换的东西有点通过提供它的 sandwiches 而不是只是一个列表。让我们创建一个简单的容器来存放列表sandwiches(这项工作,因为你无法反序列化List<Sandwiches> 直接要求。

In Sandwich.cs

[System.Serializable]
public class Sandwiches{
    public List<Sandwich> sandwiches = new List<Sandwich>();
}
	

相反,你 Sandwich 变量,创建一个新的Sandwich 依次包含List<Sandwich> 根据我们的容器。

只是别忘了更改 JsonWriter.Serialize(sandwich);到 JsonWriter.Serialize(sandwiches);在inspector中,添加一些 sandwiches 运行它,并查看你得到什么。

Step 3: Loading and Deserializing
做最难的部分,我们已经有我们需要的一切,所以剩下的就是创建一个方法来加载数据和一个按钮来调用该方法。
这里是我们的方法:
In JsonTutorial.cs

private void LoadAndDeserialize(){
        var streamReader = new StreamReader(PATH + fileName + ".txt");
        string data = streamReader.ReadToEnd();
        streamReader.Close();

        sandwiches = JsonReader.Deserialize<Sandwiches>(data);
    }

它看起来类似于我们的 SerializeAndSave() 方法,但是我们通过阅读做在这儿的对面 (废话)。
与 StreamWriter相反,我们正在使用 StreamReader

与JsonWriter.Serialize相反,我们使用的 JsonReader.Deserialize。你会注意到的语法是有点不同,在这里,因为我们的读者需要知道什么类型要反序列化 (在本例中,Sandwiches ),和你通过它要反序列化,它是字符串的数据我们从回来我们 StreamReader。

步骤 4: 测试它......再一次!

最终代码
JsonTutorial.cs

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Pathfinding.Serialization.JsonFx;
using System.IO;

public class JsonTutorial : MonoBehaviour {

    public string fileName;
    public Sandwiches sandwiches = new Sandwiches();
    //public List<Sandwich> sandwiches = new List<Sandwich>();

    private string PATH;

    private void Start() {
        PATH = Application.dataPath + "/../testData/";
    }
    private void OnGUI()   {
        if (GUILayout.Button("SAVE")){
            SerializeAndSave();
        }
        if (GUILayout.Button("LOAD")){
            LoadAndDeserialize();
        }
    }

    private void SerializeAndSave() {
        string data = JsonWriter.Serialize(sandwiches);
        if(!Directory.Exists(PATH)){
            Directory.CreateDirectory(PATH);
        }
        var streamWriter = new StreamWriter(PATH + fileName + ".txt");
        streamWriter.Write(data);
        streamWriter.Close();
    }

    private void LoadAndDeserialize(){
        var streamReader = new StreamReader(PATH + fileName + ".txt");
        string data = streamReader.ReadToEnd();
        streamReader.Close();

        sandwiches = JsonReader.Deserialize<Sandwiches>(data);
    }
}

Sandwich.cs

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

[System.Serializable]
public class Sandwich{
    public string name;
    public string bread;
    public float price;
    public List<string> ingredients = new List<string>();

    public Sandwich() { }
}

[System.Serializable]
public class Sandwiches{
    public List<Sandwich> sandwiches = new List<Sandwich>();
}

学习JsonFX 的地方: http://www.raybarrera.com/2014/05/18/json-deserialization-using-unity-and-jsonfx/
http://www.raybarrera.com/2012/11/03/unity-and-json-quick-guide/
https://bitbucket.org/TowerOfBricks/jsonfx-for-unity3d/overview

??

??

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-10 01:28:32

Unity使用JsonFX插件进行序列化的相关文章

[译]为Unity制作WP8插件

前言: 在用Unity发布WP8应用时候,经常会遇到一些API不能用的情况,例如弹出MessageBox,无法使用string.Compare(string,string,bool)等等之类的问题.那么如何解决这些问题呢?解决方案之一就是制作插件.在Unity Manual中有这样一篇文章:http://docs.unity3d.com/Manual/wp8-plugins-guide-csharp.html 讲的就是如何制作Unity的WP8插件.小弟我用中文将这个过程描述一遍.由于能力有限,

unity编辑器和插件的制作(四.1)

好久没有更新,有些急事终于处理完了,接着更新博客! 废话不多说,接着上面的讲,今天我们来接着讲述. 前面说到 怎么去建立一个自己 ,用代码绘制一个色块,今天我们来讲述下,怎么绘制一个图片在场景里面. 首先 我们先做下图片的功课. 在unity中图片的种类分了很多,默认是:Texture, 还有其他的一些属性. 有些人可以会遇到 我放进去的素材为什么编译之后会变模糊那,这是由于,在unity中你没有修改图片的属性,导致的. 在 texture模式下, 我们来分析下这种图片的属性, wrap mod

unity 编辑器和插件制作(五)

接着前面的继续前行,默默的fighting. 前面讲了,怎么使用摄像机发射线到物体,来触发事件.今天我们 来讲述下怎么去实现一个label. 这个就相对比较简单了,其实我们可以直接使用unity自带得textmesh来实现一个字体,但大多数时候,需要改一些设置,字体大小,材质等等 一些得问题所以我们,最好还是自己写一个脚本来实现一些简单的操作,方便简洁嘛.其实很简单 ,下面我们就开始来实现这些方法. 代码 : using UnityEngine; using System.Collections

unity编辑器和插件(三)

接下来 我就开始正规的编辑器和插件的制作. 我这里是按照 IOS android的 控件为例子模板.来制作 一套使用 unity书写的控件. 好首先我们来想下  IOS 和android的 控件都是以四边形基础的. SO, 接下来 我们来转像unity,在unity中 我们怎么去建立一个四边形那, 依照图形绘制的原理.三点一面的理论.我们可以使用6个点来建立一个两三角形组成的四边形. 我们先学会怎么去绘制一个view,也就是简单的一个色面. 我们知道 unity中得面也是采取这种的绘制方法,绘制

【VR】Leap Motion 官网文档 Unity资源与插件

前言: Leap Motion的官网文档已经有不少的热心网友参与了翻译,但没有覆盖官网文档的全部. 为迎合Unity VR的热潮与大家的学习需要,本博客将推出针对Unity方向的官方文档翻译系列. 本篇首先对Leap Motion所提供的Unity资源与插件进行概述. 英文原文网址:https://developer.leapmotion.com/documentation/unity/index.html 译文首发&持续更新:http://blog.csdn.net/duzixi Leap M

Unity时钟定时器插件——Vision Timer源码分析之二

Unity时钟定时器插件--Vision Timer源码分析之二 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 前面的已经介绍了vp_Timer(点击前往查看),vp_TimeUtility相对简单很多,vp_TimeUtility定义了个表示时间的结构Units: C#代码   /// <summary> /// represents a time measured in standard units /// </summar

Unity基础 NGUI插件 创建简单的按钮

Unity版本:4.5.1 NGUI版本:3.6.5 注意NGUI版本,网上的大部分教程都是2.x版本的,在步骤上面略有不同,此文适合初学者. 示例: 通过NGUI创建一个背景和按钮. 1.首先创建一个新场景,并保存,在此场景取名为Test: 在Unity主界面上:File — New Scene,然后保存场景,File — Save Scene As.. 在此,场景命名为Test,可以在Unity中看到如下效果:      2.网上的绝大部分教程都说要删除场景中的自带摄像机,即上文左侧图中的

Unity时钟定时器插件——Vision Timer源码分析之一

Unity时钟定时器插件--Vision Timer源码分析之一 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 因为项目中,UI的所有模块都没有MonBehaviour类(纯粹的C#类),只有像NGUI的基本组件的类是继承MonoBehaviour.因为没有继承MonoBehaviour,这也不能使用Update,InVoke,StartCoroutine等方法,这样就会显得很蹩脚.后来一个同事添加vp_Timer和vp_TimeUti

Unity的NGUI插件篇——入场效果

Unity的NGUI插件篇--入场效果 入场效果 入场效果需要借助于NGUI提供的TweenPosition类来完成,为了说明此类的使用方法,本节将使会讲解两个示例.本文选自  大学霸 <NGUI使用手册>  一书 匀速入场 将游戏主菜单看作一个整体,本小节会令其自上而下匀速入场,具体的实现过程如下: (1)在Project视图里,新建一个C#脚本,命名为AppearFromAbove,为其添加下面的代码: 01     using UnityEngine; 02     using Syst