Unity3D学习(二):使用JSON进行对象数据的存储读取

前言

前段时间完成了自己的小游戏Konster的制作,今天重新又看了下代码。原先对关卡解锁数据的存储时用了Unity自带的PlayerPref(字典式存储数据)。

读取关卡数据的代码:

void Awake ()
    {
        foreach(Transform Child in transform) //Update Level Lists
        {
            //Get Level‘s Name
            string levelname = Child.name.Substring(0,1); 

            //Load level data ,check if it is unlocked
            if(PlayerPrefs.GetInt(levelname) == 0)  //Set Lock
            {
                Child.GetChild(1).gameObject.SetActive(true);
            }
            else
            {
                Child.GetChild(1).gameObject.SetActive(false);
            }
        }
    }

某一关通关时,解锁下一关:

public void LevelCompleted()                   // level completed
    {
        int temp = thisLevel + 1; //next level
        string nextLevel = temp.ToString();
        if (PlayerPrefs.GetInt(nextLevel) == 0) // check if next level is locked
            PlayerPrefs.SetInt(nextLevel, 1);
        PlayerPrefs.Save();
        StartCoroutine(GameSuccess());  //Show the GameSuccess UI
    }

个人觉得虽然使用起来方便,但是如果我想存取一些对象结构数据的话很麻烦,于是自己试着写了个简单的对象数据存储。

使用JSON存储数据

什么是Json

JSON是一种轻量级的数据交换格式。它的本质其实就是一种对象以键值为基础保存的字符串。

比如有一个Person类:

public class Person
{
   public string name;
   public int age;
   public Person(string _name,int _age)
  {
      // constructor
         name = _name;
         age = _age;
  }
}

//
static void Main()
{
     Person kk = new Person("KK",20);
}

然后实例化一个叫KK的人,那么它的JSON字符串格式为:{"name": "KK","age":"19"}。

应用:利用JSON对关卡数据进行存储

这里使用的是JsonFx,一个基于.NET的JSON操作库。下载地址1(CSDN) 下载地址2(GitHub)

首先我们需要确定下数据的存储路径,这里定义了一个FilePath类来存放所有路径(全局变量)。

public class FilePath{
    public static readonly string GAMEDATA_PATH = Application.dataPath + "/GameData"; //游戏数据的文件夹
    public static readonly string LEVEL_PATH = GAMEDATA_PATH + "/leveldata.txt"; //关卡解锁数据存储路径    //之后有新的数据需要存储路径时可以拓展
}

然后将JSON操作和文件IO操作简单封装一下:

using JsonFx.Json;
using System.IO;
public class DataManager{
   //保存对象数据
    public static void SaveClass<T>(T saveClass,string path)
    {
       //如果游戏数据文件夹不存在,创建一个文件夹
        if(!Directory.Exists(FilePath.GAMEDATA_PATH))
            Directory.CreateDirectory(FilePath.GAMEDATA_PATH);
        File.WriteAllText(path, JsonWriter.Serialize(saveClass));

    }

   //读取对象数据
    public static T LoadClass<T>(string path)
    {
        string list = File.ReadAllText(path);
        return JsonReader.Deserialize<T>(list);
    }
}

然后定义一个Level类保存单个关卡数据,需要特别注意的是,JSON序列化的对象必须显式地指明默认构造函数,不然JsonFx会报错。

public class Level{
    //关卡编号
    public int LevelNumber { get; set; }
   //关卡是否解锁
    public bool IsUnlocked { get; set; }
    public Level(){}  //必须提供默认构造函数
    public Level(int _levelnumber,bool _IsUnlocked)
    {
        LevelNumber = _levelnumber;
        IsUnlocked = _IsUnlocked;
    }
}

再定义一个LevelList来存储所有的关卡。

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

public class LevelLists{

    public List<Level> lists;

    //默认构造函数,用于json序列化与反序列化
    public LevelLists() { }

    /// <summary>
    ///  赋值构造函数,用于游戏第一次启动的初始化
    /// </summary>
    public LevelLists(int levels)
    {
        lists = new List<Level>();
        lists.Add(new Level(1, true));  //关卡1肯定必须提前解锁的
        for(int i = 2; i <= levels;i++ )
        {
           lists.Add(new Level(i, false)); //其余关卡锁定
        }
    }
}

然后为了在游戏第一次启动时初始化数据,我们需要一个脚本FirstLaunch来检测游戏是否是第一次启动。在场景里创建一个空物体挂上这个脚本即可。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FirstLaunch : MonoBehaviour {
    public int InitLevelNum; //初始化的关卡数,在编辑器的Inspector里填写好,我填写的是4关
    void Awake()
    {
        Check();
    }

    void Check() //检查游戏是否是第一次启动
    {
        int IsFirstLaunch = PlayerPrefs.GetInt("First");  //获取这个键对应的值,不存在默认为0
        if(IsFirstLaunch == 0)
        {
            //如果不存在,创建并把值设置为1
            PlayerPrefs.SetInt("First", 1);
            PlayerPrefs.Save();
            InitializeLevelLists();
        }
    }

    void InitializeLevelLists() //在本地初始化关卡列表的数据
    {

        LevelLists mylist = new LevelLists(InitLevelNum);
        DataManager.SaveClass<LevelLists>(mylist, FilePath.LEVEL_PATH);
    }
}

然后对于关卡列表,我们写一个脚本来管理它的状态

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

public class LevelsControll : MonoBehaviour{
    public GameObject[] Levels;  //关卡选择
    public GameObject[] Locks;   //关卡锁
    // Use this for initialization

    void Start()
    {
        Initialize();
    }

    void Initialize()   //关卡列表初始化
    {
        //读取关卡数据
        LevelLists data = DataManager.LoadClass<LevelLists>(FilePath.LEVEL_PATH);
        for(int i = 0; i < Levels.Length;i++)
        {
            //初始化点击事件监听
           ClickListener.Get(Levels[i]).onClick += SelectLevels;
            //初始化关卡解锁状态
           Locks[i].SetActive(!data.lists[i].IsUnlocked);
        }
    }

    public void SelectLevels(GameObject go)
    {
        int i = 0;
        for(;i < Levels.Length;i++)
        {
            if (go == Levels[i])
                break;
        }
        //Load Level 这里为了测试直接打印了
        Debug.Log("Load level " + (i + 1));
    }
}

由于关卡选择直接用的UGUI的Image组件,它没有UI点击事件处理,但我们可以自己写一个脚本实现Unity的点击事件接口IPointerClickHandler来监听点击事件。

using UnityEngine;
using UnityEngine.EventSystems;

public class ClickListener : MonoBehaviour, IPointerClickHandler //注意这是Unity提供的点击接口
{
    public delegate void VoidDelegate(GameObject go); //事件委托
    public VoidDelegate onClick;

    public static ClickListener Get(GameObject go) //获取对应GameObject的Listener脚本,没有就新增一个
    {
        ClickListener listener = go.GetComponent<ClickListener>();
        if (listener == null)
            listener = go.AddComponent<ClickListener>();
        return listener;
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        if (onClick != null)
            onClick(gameObject);
    }
}

OK,然后在场景中弄好UI,挂上脚本,点击运行。

可以发现创建了一个叫GameData的文件夹,然后该文件夹下新建了一个leveldata.txt文件,里面存储了关卡的数据。

停止运行,然后这里我再在文本文件里把第四关的IsUnlocked属性修改为true,再运行,发现第四关解锁了。

     

由此,一个简单的关卡数据存储也就完成了。

当然这样没有什么安全性,玩家只需要在对应文件夹里修改这个文本文件就能解锁了,因此有些时候我们需要对数据进行加密。关于数据加密又是另一个话题了( ̄▽ ̄)。

参考资料

《Unity5.X开发指南》   作者:罗盛誊

UGUI研究院之控件以及按钮的监听事件系统(五)  作者:雨凇MOMO

时间: 2024-11-04 22:02:35

Unity3D学习(二):使用JSON进行对象数据的存储读取的相关文章

Java编程思想学习(二)----一切都是对象

2.1用应用操作对象 String s; 这里所创建的只是引用,并不是对象.如果此时向s发送一个消息,就会返回一个运行时错误.这是因为此时s没有和任何事物关联.因此,一种安全的做法是:创建一个引用的同时便进行初始化. 2.2必须由你创建所有对象 一旦创建了一个引用,就希望它能与一个新的对象相关联.通常用new操作符来实现这一目的. String s = new String("asdf"); 2.2.1存储到什么地方 1)寄存器.这是最快的存储区,因为它不同于其他存储区的地方--处理器

读书笔记5:json与xml数据存储

实际项目数据存储往往会用到相对复杂的存储格式,不仅仅是简单的字符串,本章学习的是如何在程序中使用成熟的数据格式,如Json,xml等来实现与程序业务相关的数据存储. 一.json数据序列化存储 json全程JavaScript Object Notation ,是一种轻量级的数据交换语言,易于阅读.json的特点是数据格式比较简单,易于读写,格式是压缩的,占用带宽小并易于解析,所以通常会用json格式传送数据或存储数据 json语法简介: object:一个对象以"{"开始,并以&qu

Android读写JSON格式的数据之JsonWriter和JsonReader

最近的好几个月都没有搞Android编程了,逐渐的都忘却了一些东西.最近打算找一份Android的工作,要继续拾起以前的东西.公司月初搬家之后就一直没有网络,直到今日公司才有网络接入,各部门才开始办公.不说这些了,下面开始今天的正文. JSON格式的数据通常用于网络传输,尤其是在移动设备上与服务端进行数据交互.JSON与XML比较有明显的优势.XML格式的数据非常臃肿,传递少量的数据就要附带很多额外的格式数据.而JSON除了少量的符号外,全部是真正的数据,所以有越来越多的程序用JSON来取代XM

android学习二十三(解析json格式数据)

前面我们已经掌握了xml格式数据的解析方式,那么接下来我们学习下如何解析json格式的数据.比起xml,json的主要优势在于它体积更小,在网络上传输的时候可以更省流量.但缺点在于,它的语义性差,看起来不如xml直观. 开始之前,先在自己的电脑apache-tomcat-6.0.39\webapps\ROOT路径目录下新建一个get_data.json的文件,然后编辑这个文件,并加入如下json格式的内容: [{"id":"5","version"

javascript学习-创建json对象数据,遍历

之前我已经有讲过后台返回json数据到前台,并在前台遍历json数据. 这里讲下直接在JS里创建JSON数据,然后遍历使用~ 创建代码例如以下:(创建的是JSON对象) var YearSelect = {}; var Year = 2014; var DateOption; for (var i = Year; i < Year + 12; i++) { DateOption = {'Year':i, 'Month':i-Year+1}; // alert(DateOption.Year) Y

javaweb学习总结二十五(response对象的用法一)

一:Reponse对象的概念 当客户端发送http请求时,服务器端会对每一次请求,创建request对象和response对象. response对象包括三个部分:响应头.响应状态码以及响应体 二:response对象案例分析 1:向客户端输出中文数据 1 package com.hlcui.servlet; 2 3 import java.io.IOException; 4 import java.io.OutputStream; 5 import java.io.PrintWriter; 6

springmvc学习笔记(18)-json数据交互

springmvc学习笔记(18)-json数据交互 springmvc学习笔记18-json数据交互 springmvc进行json交互 环境准备 添加json转换的依赖 配置json转换器 json交互测试 输入json串输出是json串 输入keyvalue输出是json串 本文主要介绍如何在springmvc中进行json数据的交互,先是环境准备和配置,然后分别展示了"输入json串,输出是json串"和"输入key/value,输出是json串"两种情况下

将json对象数据保存到数据库对应的表中

问题描述  如何将json对象数据保存到数据库对应的表中. 分析问题   json数据内容不固定,json数据格式是固定的(name:value),数据库表结构是固定的,在json数据格式 与 数据库表结构之间建立一套对应规则,写一套逻辑解析这套对应规则. 1.json对象对应的数据库表需要确定. 2.json对象的节点对应数据库表的列需要确定. 3.json对象的value类型需要确定下来,才能对value值做相应的操作. 4.数据库表的主键列比较特殊,一般是自增长列,需要确定. 5.数据库记

Unity3d数据存储 PlayerPrefs,XML,Json数据的存储与解析

今天来复习一下数据存储方面的基础知识,Unity3d中常用的数据存储方式有Unity自带的PlayerPrefs, XML文档, Json文档,还有常用的轻量级数据库SQL, 涉及的琐碎知识非常多,在这里自己归纳总结一下,方便日后温故而知新. PlayerPrefs存储数据 PlayerPrefs的存储方式非常简单,但可用性不强,一般只用于调试过程存储少量数据,很少大范围使用 适用设备:Mac OSX, Linux, Windows,Web Players 存储机制:Key-Value (类似于