【Unity】数据持久化及方法

2023-10-28 05:59

本文主要是介绍【Unity】数据持久化及方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 一、Unity常见路径以及文件夹
      • 1.1 常见路径
        • Android平台
        • IOS平台
      • 1.2 文件夹
        • Resources
        • StreamingAssets
        • AssetBundle
        • PersistentDataPath
    • 二、PlayerPrefs
    • 三、二进制序列化
    • 三、JSON
      • 3.1 JSON介绍
    • 四、XML


一、Unity常见路径以及文件夹

1.1 常见路径

Unity中包含很多特殊文件夹以及路径。

属性名作用
Application.dataPath此属性用于返回程序的数据文件所在文件夹的路径,例如Editor中的Assets。
Application.streamingAssetsPath此属性用于返回流数据的缓存目录,返回路径为相对路径,适合设置一些外部数据文件的路径。该路径下的文件是只读的。
Application.persistentDataPath此属性用于返回一个持久化数据存储目录的路径,可以在此路径下存储一些持久化的数据文件。
Application.temporaryCachePath此属性用于返回一个临时数据的缓存目录。
Android平台
属性名路径
Application.dataPath/data/app/xxx.xxx.xxx.apk
Application.streamingAssetsPathjar:file:///data/app/xxx.xxx.xxx.apk/!/assets
Application.persistentDataPath/data/data/xxx.xxx.xxx/files
Application.temporaryCachePath/data/data/xxx.xxx.xxx/cache
IOS平台
属性名路径
Application.dataPathApplication/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data
Application.streamingAssetsPathApplication/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data/Raw
Application.persistentDataPathApplication/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Documents
Application.temporaryCachePath/data/data/xxx.xxx.xxx/Library/Cache

注:Application.dataPath该路径在移动端没有访问权限!

1.2 文件夹

Resources

是一个Unity3D的保留文件夹,里面的内容在打包时会被无条件的打到发布包中

它的特点简单总结就是:

  1. 只读,即不能动态修改,所以动态更新的资源不要放在其中
  2. 会将文件夹内的资源打包集成到.asset文件里面,因此可以放入一些Prefab,因为Prefab打包时会自动过滤不需要的资源
  3. 主线程加载,资源读取使用Resources.Load()
StreamingAssets

和Resources类似,同样是一个只读的Unity3D的保留文件夹

不同的是Resources文件夹中的内容在打包时会被压缩和加密

而StreamingAssets文件夹中的内容则会原封不动的打入包中,因此主要用来存放一些二进制文件

  1. 同样只读不可写。
  2. 主要用来存放二进制文件。
  3. 只能用WWW类来下载,在Unity2018以后使用UnityWebRequest类。

实际代码:

  • WWW方法(高版本已弃用)
IEnumerator LoadStreamingAssetsByWWW()
{string filePath = Application.streamingAssetsPath + "/test.txt";WWW www = new WWW(filePath);yield return www;_result = www.text;
}
  • UnityWebRequest方法
IEnumerator LoadStreamingAssetsByUnityWebRequest()
{string filePath = Application.streamingAssetsPath + "/test.txt";UnityWebRequest webRequest = UnityWebRequest.Get(filePath);yield return webRequest.SendWebRequest();//异常处理if (webRequest.isHttpError || webRequest.isNetworkError){Debugger.Log(webRequest.error);}// webRequest 就是最后获取到的文件数据// webRequest.downloadHandler.data 获取二进制数据
}

注:这段代码编写完成之后,在Mac或者编辑器里测试,无法输出内容。Editor和IOS在读取本地文件的时候,地址需要加一个file://。

string filePath = "file://" + Application.streamingAssetsPath + "/test.txt";
if (Application.isMobilePlatform)
{if (Application.platform == RuntimePlatform.Android){filePath = Application.streamingAssetsPath + "/test.txt";}
}
AssetBundle

就是俗称的AB包

  1. 是Unity3D定义的一种二进制类型
  2. 最好将prefab封装成AssetBundle
  3. 使用WWW类来下载
PersistentDataPath

这个路径是可读写的

在IOS上就是程序的沙盒,但是在Android上可以是程序的沙盒,也可以是sdcard

并且在Android打包的时候,ProjectSetting页面有一个选项Write Access,可以设置它的路径是沙盒还是sdcard

  1. 内容可读写,不过只能运行时才能写入或者读取。不能提前将数据存入
  2. 无内容限制,可以从StreamingAsset中读取二进制文件或者从AssetBundle读取文件来写入PersistentDataPath中
  3. 写入的文件,可以在电脑上进行读写

从StreamingAsset中读取二进制文件写入的例子

string savePath = Application.persistentDataPath + "/test.txt";
using (FileStream fs = File.Create(savePath))
{fs.Write(webRequest.downloadHandler.data, 0, webRequest.downloadHandler.data.Length);
}

二、PlayerPrefs

PlayerPrefs是Unity自带的数据结构,位于UnityEngine命名空间下

它可以对整数,浮点数,字符串3种类型的数据进行存取

它是持久存储于设备上的,只要用户没有删除应用或者手动去清除数据,PlayerPrefs的数据会一直保留

适合存储一些设置相关的信息

PlayerPrefs采用键值对的方式进行数据的查询与存储,存储数据的方式如下:

PlayerPrefs.SetInt ("ID",1);
PlayerPrefs.SetFloat ("WEIGHT",20.5f);
PlayerPrefs.SetString ("NAME","SNAGE");

读取数据的方式如下:

int id = PlayerPrefs.GetInt ("ID");
float weight = PlayerPrefs.GetFloat ("WEIGHT");
string name = PlayerPrefs.GetString ("NAME");

删除数据的方式如下:

PlayerPrefs.DeleteKey ("NAME");
PlayerPrefs.DeleteAll ();

三、二进制序列化

这里举例使用 BinaryFormatter 进行二进制序列化,但比较建议使用ProtoBuf

假设有一个Player类

[System. Serializable]
public class Player
{public int health;public int  power;public Vector3 position;
}

由于BinaryFormatter序列化不支持Unity的Vector3类型,所以需要包装一下,创建好PlayerData类准备序列化

public class PlayerData{public int level;public int health;public float[] position;public PlayerData(Player player){this.level = player.level;this.health = player.health;this.position = new float[3];this.position[0] = player.transform.position.x;this.position[1] = player.transform.position.y;this.position[2] = player.transform.position.z;}
}

对PlayerData进行保存和读取,读取出来的PlayerData可以赋值给Player类

public static class SaveSystem{//保存数据public static void SavePlayer(Player player){BinaryFormatter formatter = new BinaryFormatter();string path = Application.persistentDataPath + "/player.fun";FileStream stream = new FileStream(path,FileMode.Create);PlayerData data = new PlayerData(player);formatter.Serialize(stream,data);stream.Close();}//读取数据public static PlayerData LoadPlayer(){string path = Application.persistentDataPath+"/player.fun";if(File.Exists(path)){BinaryFormatter formatter = new BinaryFormatter();FileStream stream = new FileStream(path,FileMode.Open);PlayerData data = formatter.Deserialize(stream) as PlayerData;stream.Close();return data;}else{Debug.LogError("Save file not found in  "+path);return null;}}
}

三、JSON

3.1 JSON介绍

JSON是一种轻量级的数据交换和存储格式

可以用于对数据的设备(如手机的本地存储)和向Web服务器上传,并且符合面向对象编程的思想

JSON采用完全独立于语言的文本格式,但也使用了类似于C语言家族的习惯(包括C,C++,C#,JAVA等)

这些特性使JSON成为理想的数据交换语言,易于人阅读和编写,同时也易于机器解析和生成

可以使用NewtonJson来进行序列化。

假设有一个玩家存档类

public class PlayerSaveData
{public string versionId { get; set; }                   // 版本号public int gold { get; set; }                           // 金币数量public int energy { get; set; }                         // 体力public int mainWeapon { get; set; }                     // 主武器public int towerUp { get; set; }                        // 上炮台public int towerDown { get; set; }                      // 下炮台public Dictionary<int, int> chapterProgress;            // 字典测试
}

通过使用NewtonJson序列化并输出,并且NewtonJson还可以将字典进行序列化

// NewtonJson测试
// 创建字典Dictionary<int, int> dic = new Dictionary<int, int>
{{ 1000, 1 },{ 1001, 2 },
};
PlayerSaveData data = new PlayerSaveData()
{versionId = "0.01",gold = 1000,energy = 50,mainWeapon = 20000,towerUp = 40000,towerDown = 40000,chapterProgress = dic,						// 将字典赋值
};
string json = JsonConvert.SerializeObject(data);

最后输出结果,其中{"chapterProgress":{"1000":1,"1001":2}是从字典转化而来:
在这里插入图片描述
反序列化

PlayerSaveData data = new PlayerSaveData();
data = JsonConvert.DeserializeObject<PlayerSaveData>(json);

四、XML

这篇关于【Unity】数据持久化及方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/291174

相关文章

Java function函数式接口的使用方法与实例

《Javafunction函数式接口的使用方法与实例》:本文主要介绍Javafunction函数式接口的使用方法与实例,函数式接口如一支未完成的诗篇,用Lambda表达式作韵脚,将代码的机械美感... 目录引言-当代码遇见诗性一、函数式接口的生物学解构1.1 函数式接口的基因密码1.2 六大核心接口的形态学

Python实现文件下载、Cookie以及重定向的方法代码

《Python实现文件下载、Cookie以及重定向的方法代码》本文主要介绍了如何使用Python的requests模块进行网络请求操作,涵盖了从文件下载、Cookie处理到重定向与历史请求等多个方面,... 目录前言一、下载网络文件(一)基本步骤(二)分段下载大文件(三)常见问题二、requests模块处理

Linux内存泄露的原因排查和解决方案(内存管理方法)

《Linux内存泄露的原因排查和解决方案(内存管理方法)》文章主要介绍了运维团队在Linux处理LB服务内存暴涨、内存报警问题的过程,从发现问题、排查原因到制定解决方案,并从中学习了Linux内存管理... 目录一、问题二、排查过程三、解决方案四、内存管理方法1)linux内存寻址2)Linux分页机制3)

vue基于ElementUI动态设置表格高度的3种方法

《vue基于ElementUI动态设置表格高度的3种方法》ElementUI+vue动态设置表格高度的几种方法,抛砖引玉,还有其它方法动态设置表格高度,大家可以开动脑筋... 方法一、css + js的形式这个方法需要在表格外层设置一个div,原理是将表格的高度设置成外层div的高度,所以外层的div需要

Java中注解与元数据示例详解

《Java中注解与元数据示例详解》Java注解和元数据是编程中重要的概念,用于描述程序元素的属性和用途,:本文主要介绍Java中注解与元数据的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参... 目录一、引言二、元数据的概念2.1 定义2.2 作用三、Java 注解的基础3.1 注解的定义3.2 内

将sqlserver数据迁移到mysql的详细步骤记录

《将sqlserver数据迁移到mysql的详细步骤记录》:本文主要介绍将SQLServer数据迁移到MySQL的步骤,包括导出数据、转换数据格式和导入数据,通过示例和工具说明,帮助大家顺利完成... 目录前言一、导出SQL Server 数据二、转换数据格式为mysql兼容格式三、导入数据到MySQL数据

C++中使用vector存储并遍历数据的基本步骤

《C++中使用vector存储并遍历数据的基本步骤》C++标准模板库(STL)提供了多种容器类型,包括顺序容器、关联容器、无序关联容器和容器适配器,每种容器都有其特定的用途和特性,:本文主要介绍C... 目录(1)容器及简要描述‌php顺序容器‌‌关联容器‌‌无序关联容器‌(基于哈希表):‌容器适配器‌:(

Python判断for循环最后一次的6种方法

《Python判断for循环最后一次的6种方法》在Python中,通常我们不会直接判断for循环是否正在执行最后一次迭代,因为Python的for循环是基于可迭代对象的,它不知道也不关心迭代的内部状态... 目录1.使用enuhttp://www.chinasem.cnmerate()和len()来判断for

C#提取PDF表单数据的实现流程

《C#提取PDF表单数据的实现流程》PDF表单是一种常见的数据收集工具,广泛应用于调查问卷、业务合同等场景,凭借出色的跨平台兼容性和标准化特点,PDF表单在各行各业中得到了广泛应用,本文将探讨如何使用... 目录引言使用工具C# 提取多个PDF表单域的数据C# 提取特定PDF表单域的数据引言PDF表单是一

Java循环创建对象内存溢出的解决方法

《Java循环创建对象内存溢出的解决方法》在Java中,如果在循环中不当地创建大量对象而不及时释放内存,很容易导致内存溢出(OutOfMemoryError),所以本文给大家介绍了Java循环创建对象... 目录问题1. 解决方案2. 示例代码2.1 原始版本(可能导致内存溢出)2.2 修改后的版本问题在