【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究

原文地址:Unity3D游戏开发之游戏读/存档功能在Unity3D中的实现

感谢风宇冲Unity3D教程宝典之两步实现超实用的XML存档一文提供相关思路!


using Newtonsoft.Json;错误,则是因为缺少Newtonsoft.JSON库,请自行下载。

Newtonsoft.Json文件存放在Unity位置如下所示

【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第1张图片

UNITY对于JSON存储的思路以及介绍,参考资料已经说明很清楚


本文章着重代码说明,说明代码的作用


-----------------------------------------------------TestSave.cs

using UnityEngine;

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

public class TestSave : MonoBehaviour
{
    ///
    /// 定义一个测试类
    ///
    public class TestClass

    {

        public string Name = "张三";
        public float Age = 23.0f;
        public int Sex = 1;
        public List Ints = new List(){1,2,3};//定义List变量

    }

    void Start()
    {

        //定义存档路径
        string dirpath = Application.persistentDataPath + "/Save";//Application.persistentDataPath="C:/Users/Administrator/AppData/LocalLow/lucas_meijer@gmail_com/unity"

        //创建存档文件夹
        IOHelper.CreateDirectory(dirpath);

        //定义存档文件路径
        string filename = dirpath + "/GameData.sav";//dirpath="C:/Users/Administrator/AppData/LocalLow/lucas_meijer@gmail_com/unity/Save"
        TestClass t = new TestClass();

        //保存数据
        IOHelper.SetData(filename, t);

        //读取数据
        TestClass t1 = (TestClass)IOHelper.GetData(filename, typeof(TestClass));
        Debug.Log(t1.Name);
        Debug.Log(t1.Age);
        Debug.Log(t1.Ints);
        Debug.Log(filename);//加上这一句,就可以显示存档路径
    }
}

结束-----------------------------------------------------TestSave.cs


【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第2张图片

【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第3张图片

意思是这个public class TestClass类,里面的数据都是可以存储的,

还可以使用C#类的继承来,子类继承父类,(在原有的类的数据基础上,子类可以添加更多的数据类型和数据)


显示存档路径为

C:/Users/Administrator/AppData/LocalLow/lucas_meijer@gmail_com/unity/Save/GameData.sav

c#如何定义全局变量list


public是公共的,static是静态的,class表示这是类。

public static class 表示这是一个公共的静态类,直接通过类名调用里面的方法,变量等。不用new的。
public class 需要new才可以用。
class 是表示私有的类,外部不能调用。

-----------------------------------------------------IOHelper.cs

using UnityEngine;
using System.Collections;
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using Newtonsoft.Json;

public static class IOHelper

{
    ///
    /// 判断文件是否存在
    ///
    //为真,则路径表示文件
    public static bool IsFileExists(string fileName)
    {
        return File.Exists(fileName);//参考资料1
    }

    ///
    /// 判断文件夹是否存在
    ///
    //为真,则路径表示目录
    public static bool IsDirectoryExists(string fileName)
    {
        return Directory.Exists(fileName);
    }

    ///
    /// 创建一个文本文件
    ///
    /// 文件路径
    /// 文件内容

    public static void CreateFile(string fileName, string content)
    {
        StreamWriter streamWriter = File.CreateText(fileName);//参考资料2 C#中File类的文件操作方法详解
        streamWriter.Write(content);
        streamWriter.Close();
    }

    ///
    /// 创建一个文件夹
    ///

    public static void CreateDirectory(string fileName)
    {
        //文件夹存在则返回//为真,则路径表示目录
        if (IsDirectoryExists(fileName))
            return;
        Directory.CreateDirectory(fileName);
    }

    //写入存档文件
    public static void SetData(string fileName, object pObject)
    {

        //将对象序列化为字符串
        string toSave = SerializeObject(pObject);//调用 序列化函数
        //对字符串进行加密,32位加密密钥//调用 Rijndael加密算法
        toSave = RijndaelEncrypt(toSave, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");//在这里把32个"x"的字符串变量的值 改为一个32位根据MAC地址编辑的变量就是密钥
        StreamWriter streamWriter = File.CreateText(fileName);//· CreateText:为写入文本创建或打开新文件
        streamWriter.Write(toSave);
        streamWriter.Close();
    }

    //读取存档文件
    public static object GetData(string fileName, Type pType)
    {
        StreamReader streamReader = File.OpenText(fileName);//· OpenText:打开现有文本文件以进行读取
        string data = streamReader.ReadToEnd();//参考资料3 ReadToEnd() 这个方法适用于小文件的读取,一次性的返回整个文件

                //对数据进行解密,32位解密密钥//调用 Rijndael解密算法
                data = RijndaelDecrypt(data, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");//在这里把32个"x"的字符串变量的值  改为一个32位根据MAC地址编辑的变量就是密钥
        streamReader.Close();

        return DeserializeObject(data, pType);//调用 反 加密算法函数
        //返回已经解密的值
    }

    ///
    /// Rijndael加密算法
    ///
    /// 待加密的明文
    /// 密钥,长度可以为:64位(byte[8]),128位(byte[16]),192位(byte[24]),256位(byte[32])
    /// iv向量,长度为128(byte[16])
    ///

    private static string RijndaelEncrypt(string pString, string pKey)// Rijndael加密算法
    {
        //密钥
        byte[] keyArray = UTF8Encoding.UTF8.GetBytes(pKey);
        //待加密明文数组
        byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(pString);//上面被序列化的变量
        //Rijndael解密算法
        RijndaelManaged rDel = new RijndaelManaged();
        rDel.Key = keyArray;
        rDel.Mode = CipherMode.ECB;
        rDel.Padding = PaddingMode.PKCS7;

        ICryptoTransform cTransform = rDel.CreateEncryptor();

        //返回加密后的密文
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
        return Convert.ToBase64String(resultArray, 0, resultArray.Length);
    }

    ///
    /// ijndael解密算法
    ///
    /// 待解密的密文
    /// 密钥,长度可以为:64位(byte[8]),128位(byte[16]),192位(byte[24]),256位(byte[32])
    /// iv向量,长度为128(byte[16])
    ///

    private static String RijndaelDecrypt(string pString, string pKey)// ijndael解密算法
    {

        //解密密钥
        byte[] keyArray = UTF8Encoding.UTF8.GetBytes(pKey);
        //待解密密文数组
        byte[] toEncryptArray = Convert.FromBase64String(pString);//上面被序列化的变量

        //Rijndael解密算法
        RijndaelManaged rDel = new RijndaelManaged();
        rDel.Key = keyArray;
        rDel.Mode = CipherMode.ECB;
        rDel.Padding = PaddingMode.PKCS7;

        ICryptoTransform cTransform = rDel.CreateDecryptor();

        //返回解密后的明文
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

        return UTF8Encoding.UTF8.GetString(resultArray);

    }

    ///
    /// 将一个对象序列化为字符串
    ///
    /// The object.
    /// 对象
    /// 对象类型

    private static string SerializeObject(object pObject)
    {
        //序列化后的字符串
        string serializedString = string.Empty;
        //使用Json.Net进行序列化
        serializedString = JsonConvert.SerializeObject(pObject);

        return serializedString;
    }
    ///
    /// 将一个字符串反序列化为对象
    ///
    /// The object.
    /// 字符串
    /// 对象类型
    private static object DeserializeObject(string pString, Type pType)
    {
        //反序列化后的对象
        object deserializedObject = null;
        //使用Json.Net进行反序列化
        deserializedObject = JsonConvert.DeserializeObject(pString, pType);

        return deserializedObject;
    }
}

结束-----------------------------------------------------IOHelper.cs

1.file_exists

c#中怎么获得当前路径

 使用Directory.Exists或File.Exist方法,如果前者为真,则路径表示目录;如果后者为真,则路径表示文件
上面的方法有个缺点就是不能处理那些不存在的文件或目录。
这时可以考虑使用Path.GetFileName方法获得其包含的文件名,如果一个路径不为空,而文件名为空那么它表示目录,否则表示文件;
2.

C#中File类的文件操作方法详解


【整理】C#文件操作大全(SamWang)

3.ReadToEnd()
这个方法适用于小文件的读取,一次性的返回整个文件

StreamReader类以及其方法ReadLine,Read,ReadToEnd的分析


------------------------------------------------------------
那么这个32个“x”是否就是密钥呢,代码改变如下所示

【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第4张图片
UNITY返回的结果如下所示



密钥改变如下所示
【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第5张图片
结果正常

【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第6张图片

那么把 加密和解密的代码注释掉,是否正常运行。

【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第7张图片

源码中的数据都是通过 对自己数据改变,因此注释 加密和解密的代码

是完全没有问题的



---------------------------------------------------------------------------IOHelper.cs代码图片

【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第8张图片

【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第9张图片

【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第10张图片

【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第11张图片

【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第12张图片【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第13张图片

---------------------------------------------------------------------------

那么如何存储多个像NET.JSON一样的数据呢,

添加了一个和张三差不多的数据,李四

【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第14张图片

【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第15张图片

输出的结果如下所示,李四的数据完全覆盖了张三的信息,如果想要分别保存张三和李四的信息,该怎么做呢

【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第16张图片

存储多个“张三”“李四”类型的数据,就得使用继承基础类

,效果理解上与“复制粘贴”一样

每个数据的类型不同,比XML相比较,只用新建一个"李四"类

就可以在不改变数据结构的情况下,保存类似的结构

【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第17张图片

效果如下所示,然后发现是可选的

【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究_第18张图片










你可能感兴趣的:(Unity,Unity资源,Unity工具,#,Unity教程,代码分析,代码问题,Unity经验,#,Unity资料,Unity数据存储,Unity&JSON,Unity,Unity教程,Unity经验,Unity数据存储,UnityJSON)