Unity中保存数据的方法

一、概述

Unity中可用于持久化的方式有:

1)通过ScriptableObject在可编辑模式下保存数据

2)通过excel、json等文件实现数据的可持久化

二、ScriptableObject的使用

1、使用背景

假如需要制作子弹预设体,每个子弹上有speed速度和damage伤害力的参数。

按照现有的方法,这两个参数设置为public或者[SerializedField] private的属性,那么就可以在Inspector界面中配置两个参数的具体值。

当游戏运行的时候,每生成一个实例都会复制一份这个数据,实际上复制的都是同一份数据,这样就造成了内存的浪费。

通过ScriptableObject方法可以实现编辑模式下的数据存储,针对这种复制同一份数据的情况,比excel、json等更加方便。

2、ScritableObject介绍

2.1 定义

1)ScriptableObject是Unity的一个数据配置存储基类 ,类似于MonoBehaviour的基类,继承自UnityEngine.Object。它是一个可以用来保存大量数据的数据容器 ,实例化后可以将它保存为自定义的数据资源文件

2)ScriptableObject本身是一个类,ScriptableObject实例化后被保存为.asset资源文件,和预设体、材质球、音频文件等类似,存放在Assets文件夹下。

2.2 作用

1)编辑模式下的数据持久化

编辑模式下会保存数据,但是游戏运行时修改ScriptableObject的数据是不会保存到本地的,重新打开运行时数据还是配置的的初始数据。

2)配置文件(配置游戏中的数据)

配置文件的数据在游戏发布前定义好规则,运行时只会读出使用而不会修改数据的内容。传统配置文件是放在xml、json、excel等里面,ScriptableObject直接在Inspector中进行配置更加方便。

3)数据复用(多个对象共用一套数据)

三、使用示例

1、效果

unity配置:

2、创建ScriptableObject类的BulletData.cs:

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName ="BulletData", menuName ="ScritableObject/子弹数据")]
public class BulletData : ScriptableObject
{
    public int speed;
    public int damage;
}

fileName表示数据资源文件创建出来的文件名

menuName表示在Assets/Create下的名字

创建后命名为BulletData,并放在Assets/ScriptableObject目录下,并配置speed和damage的值。

3、创建PanelOperator.cs文件,并挂载到Panel对象上

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class PanelOperator : MonoBehaviour
{
    public BulletData bulletData;
    // Start is called before the first frame update
    void Start()
    {
        this.transform.Find("SpeedInfo").GetComponent<Text>().text = bulletData.speed.ToString();
        this.transform.Find("DamageInfo").GetComponent<Text>().text = bulletData.damage.ToString(); 
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

配置Panel的BulletData对象的值

4、编写Button的操作类ButtonOperator.cs并挂载到ButtonOperator上

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;

public class ButtonOperator : MonoBehaviour
{
    public Text speedText;
    public Text damageText;
    public BulletData bulletData;

    public void addSpeed()
    {
        int currentValue = int.Parse(speedText.text);
        currentValue += 1;
        speedText.text = currentValue.ToString(); 
    }

    public void addDamage()
    {
        int currentValue = int.Parse(damageText.text);
        currentValue += 1;
        damageText.text = currentValue.ToString();
    }

    public void storeData()
    {
        bulletData = ScriptableObject.CreateInstance<BulletData>();
        bulletData.speed = int.Parse(speedText.text);
        bulletData.damage = int.Parse(damageText.text);

        string dataStr = JsonUtility.ToJson(bulletData);
        Debug.Log(Application.streamingAssetsPath);
        // 一定要在Assets下创建StreamingAssets目录
        File.WriteAllText(Application.streamingAssetsPath + "/testJson.json", dataStr); 
    }

    public void recoverData()
    {
        string dataStr = File.ReadAllText(Application.streamingAssetsPath + "/testJson.json");
        Debug.Log(dataStr);
        // 否则报错:ArgumentNullException: Value cannot be null Parameter name: objectToOverwrit
        bulletData = ScriptableObject.CreateInstance<BulletData>();  
        JsonUtility.FromJsonOverwrite(dataStr, bulletData); 
        speedText.text = bulletData.speed.ToString();
        damageText.text = bulletData.damage.ToString(); 
    }
}

然后配置SpeedButton、DamageButton、Store、Recover的事件。

配置ButtonOperator的参数如下:

5、JSON持久化解读

5.1 保存数据

bulletData = ScriptableObject.CreateInstance<BulletData>();
bulletData.speed = int.Parse(speedText.text);
bulletData.damage = int.Parse(damageText.text);

string dataStr = JsonUtility.ToJson(bulletData);
Debug.Log(Application.streamingAssetsPath);
File.WriteAllText(Application.streamingAssetsPath + "/testJson.json", dataStr);

如果保存在Application.streamingAssetsPath路径下,一定要在Assets下创建StreamingAssets目录。

5.2 读取数据

string dataStr = File.ReadAllText(Application.streamingAssetsPath + "/testJson.json");

Debug.Log(dataStr);

bulletData = ScriptableObject.CreateInstance<BulletData>();

JsonUtility.FromJsonOverwrite(dataStr, bulletData);

speedText.text = bulletData.speed.ToString();

damageText.text = bulletData.damage.ToString();

如果使用FromJsonOverwrite把数据保存到类的实例中,一定要确保类已经实例化了。否则会报错:"ArgumentNullException: Value cannot be null Parameter name: objectToOverwrite"。

6、生成ScriptableObject非持久化数据

利用ScriptableObject类的静态方法CreateInstance<>()可以生成非持久化的数据,此时相当于BulletData继承于MonoBehaviour时的效果。使得ScriptableObject的类做到了两种用法。

该方法可以在运行时创建出指定继承自ScriptableObject的对象,该对象只存在于内存中,可以被GC垃圾回收,调用依次就创建一次。

方法见:bulletData = ScriptableObject.CreateInstance<BulletData>();

四、总结

对于只用不变的数据,就是和用ScriptableObject做数据配置文件,再加上编辑模式下实现数据持久化的特点,我们可以在Inspector面板中进行数据的配置与调试,有的时候是更加方便的,并且可以达到数据复用的目的,减少内存消耗。但是它无法在游戏打包发布后将数据的变动存储到磁盘中。

相关推荐
张老师带你学2 小时前
unity TerrainSampleAssets
科技·游戏·unity·游戏引擎·模型
亿元程序员2 小时前
亿元Cocos小游戏实战合集2.0
游戏·游戏引擎
RReality5 小时前
【Unity Shader URP】色带渐变着色(Ramp Shading)实战教程
ui·unity·游戏引擎·图形渲染
mxwin13 小时前
Unity URP 体积光与雾效 基于深度重建世界空间位置,实现体积雾与体积光
unity·游戏引擎
张老师带你学14 小时前
unity 树资源 有樱花树 buildin
科技·游戏·unity·游戏引擎·模型
魔士于安14 小时前
unity 植物 不常见 花 触手植物
游戏·unity·游戏引擎·贴图·模型
魔士于安15 小时前
unity=>传送门特效 带自由视角旋转放大 鼠标操作
前端·游戏·unity·游戏引擎·贴图·模型
南無忘码至尊16 小时前
Unity学习90天 - 第4天 - 认识物理系统基础并实现物体碰撞反弹
学习·unity·游戏引擎
南無忘码至尊16 小时前
Unity学习90天 - 第4天 - 学习预制体 Prefab + 实例化并实现按鼠标生成子弹
学习·unity·游戏引擎
魔士于安1 天前
Unity资源Toon City Pack 发电厂 工地 公园 地铁站口 银行 车 直升飞机 可动 URP
游戏·unity·游戏引擎·贴图·模型