Json

Json
John Doe1.Json概述
1.什么是数据持久化
就是玩游戏时将数据存储到硬盘上,等下次再玩游戏时从硬盘读取数据
2.什么是Json
一种人为定义的文件与规则,不是一种语言,是一种纯文本的数据格式
2.Json配置规则
Json文件的键一定要用双引号包裹
3.Json配置规则练习
4.Excel转Json
原因:
栗子:
将上述数据填到excel表中
搜索一个excel转json的网站,就可以得到json文件
如果觉得每次这样复制粘贴到网站再出json有点麻烦,在编辑器相关知识里会讲到自己写转换的代码
5.JsonUtility序列化
1.JsonUtility是什么
2.必备知识点:File存读字符串
存字符串的时候会帮你创建一个文件,但此文件的路径(父文件夹)必须是已经存在的
1 | File.WriteAllText(Application.persistentDataPath + "/Test.json","唐老狮存储的json文件"); |
读文件会返回字符串类型
1 | string content = File.ReadAllText(Application.persistentDataPath + "/Test.json"); |
3.使用JsonUtility进行序列化
下列注意点很重要,请仔细阅读
在此之前已经定义了MrTang和Student的类,创建一个MrTang新对象,对成员变量分别赋值后,使用如下来序列化
1 | string jsonStr = JsonUtility.ToJson(t); |
自定义类需要加上序列化特性,只作用于内部成员Student这样的类,在定义上方加,对于MrTang外部类不用
4.流程
- 创建并填充对象
- 使用JsonUtility.ToJson序列化
- 通过File.WriteAllText存储到文件
- 后续可通过File.ReadAllText读取
6.JsonUtility反序列化
FromJson提供了两种重载,一般我们用泛化的:
1 | string jsonStr=File.ReadAllText(Application.persistentDataPath+"/MrTang.json"); |
注意事项:
无法读取数据集合([包含多个对象数据]),即无法让包含多个对象的json反序列化至一个List<>上,然而我们可以做一层包裹,创建一个新类并把List<>当做成员变量(别忘了给List<某类>里的某类加上序列化特性),然后在json文件里加上List<>的成员变量名作为键,读到外层的新对象即可
7.LitJson序列化
是一个第三方插件,只需要将src文件夹下的cs文件导入工程就可使用(年久失修,现在可能不是首选了,但仍有很多优点)
以下注意都很重要:
1 | string jsonStr=JsonMapper.ToJson(t); |
8.LitJson反序列化
仍然建议使用通过泛型转换这种重载
1 | MrTang2 t2 =JsonMapper.ToObject<MrTang2>(jsonStr); |
两个大坑:
特殊之处:
可以反序列化数据集合,无需包裹类
9.JsonUtility和LitJson对比
10.总结
11.实践(重要)
1.存储和读取数据
1 | using System.IO; |
where T: new() 有什么用?
这是一个泛型约束(Generic Constraint)。
请看你代码里的第 10 行:
1 | return new T(); |
这行代码的业务逻辑非常好:如果在所有路径下都没找到这个 JSON 文件(说明是玩家第一次玩这个游戏,或者存档丢了),为了防止游戏报错空指针,我们直接在内存里 new 一个全新的、空的数据对象返回给他。
但是!编译器在这个时候会“抬杠”:
编译器:“你凭什么保证这个未知的 T 可以被 new 出来?万一别人传进来一个不能被 new 的类(比如抽象类),或者它的构造函数必须传参数(比如 public PlayerData(int id)),那 new T() 不就崩溃了吗?”
为了让编译器闭嘴并放行,你必须给泛型
它在告诉编译器:“我保证,凡是想用我这个 LoadData
加上这句约束后:
- 你在代码里写 new T() 就绝对安全合法了。
- 如果你在外部试图读取一个没有无参构造函数的类,代码在编译阶段就会直接标红报错,把隐患扼杀在摇篮里。
2.代码打包
选择需要的代码,导出包即可,以后在别的工程可以直接导入
12.关于PersistentDataPath与StreamingAssetsDataPath
一、 Application.persistentDataPath 到底是哪里?
这个路径的名字直译过来叫**“持久化数据路径”。你可以把它通俗地理解为:“专门用来放玩家存档和配置的文件夹”**。
1. 它在电脑/手机上的具体位置:
它不在你 Unity 工程的 Assets 目录下,而是由操作系统(Windows/Mac/Android/iOS)分配给你的一个隐藏沙盒目录。
- Windows 电脑:
C:\Users\你的用户名\AppData\LocalLow\你的公司名\你的游戏名 - Mac 电脑:
~/Library/Application Support/你的公司名/你的游戏名 - Android 手机:
手机内部存储/Android/data/你的包名/files - iOS 手机:
沙盒目录/Documents
(你可以自己在 Unity 里写一句Debug.Log(Application.persistentDataPath);运行一下,控制台会把你电脑上的具体路径打印出来,你可以顺着路径找过去看看。)
2. 为什么新 JSON(比如玩家存档)必须写在这个文件夹下?
因为只有这个文件夹是【绝对可读、可写】且【更新不丢失】的!
- 原因 A(权限问题):当你的游戏打包成
.exe或.apk后,游戏安装目录里的文件会被系统锁定为只读状态。如果你试图把玩家的存档写进安装目录(比如你新建的那个 StreamingAssets 里),操作系统会直接给你报UnauthorizedAccessException(无权限访问)错误,游戏直接崩溃。 - 原因 B(更新不覆盖):假如你的游戏出了 2.0 版本,玩家更新游戏时,游戏的安装目录会被整个清空替换。但操作系统会保留
persistentDataPath里的文件!所以你把存档写在这里,玩家更新游戏后存档才不会丢。
二、 新建的 StreamingAssets 文件夹
没错!只要你拼写完全正确(注意大小写,必须是 StreamingAssets),它就是代码里 Application.streamingAssetsPath 指向的那个文件夹!
这个文件夹有极其特殊的魔法:
在 Unity 中,所有的资源(图片、模型、普通 JSON)在打包时,都会被 Unity 疯狂压缩、加密、打乱,变成机器才认识的二进制乱码(比如 .assets 文件)。
但是,放在 StreamingAssets 文件夹里的任何文件,Unity 在打包时都会“原封不动”地拷贝到包里! 不压缩、不加密、保留原文件名和后缀!
三、这俩文件夹该怎么打配合?
现在你再回头看我上一条回答里帮你改的那个 LoadData 逻辑,就能完全看懂它的精妙之处了:
StreamingAssets(初始配置区):- 特点:天生自带,打包后只读不可写。
- 放什么:放游戏初始的默认 JSON 文件。比如系统默认的怪物数值表、初始装备表、一个完全没玩过的
DefaultPlayer.json。
persistentDataPath(玩家存档区):- 特点:一开始是空的,游戏运行后动态生成,完全可读可写。
- 放什么:放玩家玩过之后发生变化的数据。比如
PlayerSave.json。
你代码里的完美闭环流程是这样的:
- 玩家刚下载游戏,第一次打开。
- 代码去
persistentDataPath(存档区)找Player.json。发现找不到(因为是新玩家)。 - 代码退而求其次,去
StreamingAssets(初始区)找Player.json,把里面 1 级、0 金币的数据读出来,作为初始数据。 - 玩家玩了一会儿,升到了 10 级。
- 当你调用
SaveData方法时,必须把新的 JSON 写入到persistentDataPath里!(因为StreamingAssets在手机上是只读的,写不进去)。 - 第二天玩家再打开游戏,代码再去
persistentDataPath找,这次找到了!直接读出 10 级的存档,完美!
四、⚠️ 一个价值千金的避坑警告(针对 Android 打包)
如果你打算把游戏打包到 Android 手机上,请一定注意这件极其变态的事:
在 Android 手机上,StreamingAssets 文件夹会被整个打包进 .apk 压缩包的肚子里!
所以,你在 LoadData 里的这句代码:File.ReadAllText(Application.streamingAssetsPath + "/" + fileName);
在 Windows 和 Mac 编辑器下跑得完美无缺,但在安卓手机上会直接报错找不到路径!(因为 C# 底层的 File 类没法直接读压缩包内部的文件)。
如果你要发安卓版,读 StreamingAssets 里的文件必须用 Unity 特有的 UnityWebRequest 方式读取。(如果你目前只在电脑上做 PC 游戏,就当没看见这条,放心地用 File.ReadAllText 吧!)
这是一个非常有前瞻性的问题!你能想到**“玩家硬盘空间”和“系统盘(C盘)占用”**,说明你已经开始具备成熟的商业游戏开发者思维了!
直接给你吃颗定心丸:只要你存的是纯数据(比如 JSON 存档),它不仅不会过度占用空间,甚至小到可以忽略不计!
但是,如果你在这个文件夹里放了**“其他东西”**,那确实有可能把玩家的 C 盘塞爆。我们来把这笔“空间账”算清楚:
五、 纯 JSON 存档到底有多大?(小到离谱)
你的 JsonMgr 是用来把 C# 对象转换成文本序列化的。你要知道,纯文本文件占用的空间是极其微小的。
- 算一笔账:1 个英文字母占 1 个字节(Byte),1 个汉字占 2~3 个字节。1 MB(兆)= 1024 KB = 1,048,576 字节。
- 打个比方:假设你的玩家存档非常复杂,包含了 100 个满级英雄的属性、几千个背包道具、上万条任务进度。转换成 JSON 文本后,哪怕有十万个字符,这个 JSON 文件的大小也就仅仅只有 100 KB 左右。
- 结论:就算玩家在你的游戏里建了 10 个存档槽,总共也就占 1 MB。对于现在动辄 1TB、2TB 的电脑硬盘来说,连一根汗毛都算不上。
所以,单靠“游戏存档”是绝对不可能把 C 盘塞满的。
六、 为什么非要放在 C 盘?(微软的硬性规矩)
你可能会觉得:“玩家把游戏安装在 D 盘,为什么存档非要跑到 C 盘去?”
其实,这是 Windows 操作系统(微软)定下的死规矩:
那个隐藏的 AppData(Application Data)文件夹,本来就是 Windows 专门设计给全天下所有软件**存放“用户个人配置”**的地方。
- 权限最安全:C 盘的
AppData是跟着“当前登录的 Windows 账号”走的。你在网吧或者公共电脑玩,张三登录他的 Windows 账号,看到的是张三的存档;李四登录,看到的是李四的存档。互相隔离,极其安全。 - 不怕被误删:玩家如果在 D 盘直接把游戏安装目录
Shift + Delete暴力删除了,只要他没清空系统盘,他下次重新下载游戏,存档依然还在! - Steam 云存档最爱:Steam、Epic 等平台的云存档功能,绝大多数默认抓取的就是 C 盘
AppData或Documents(我的文档)下的文件。
(其实你现在打开你电脑的 C盘 -> 用户 -> AppData -> LocalLow 看一眼,你会发现市面上绝大部分用 Unity 做的单机游戏,存档全都在这里!)
七、 什么时候会把 C 盘塞爆?(热更新的“锅”)
虽然 JSON 存档很小,但有一个情况会让 persistentDataPath 变得极其庞大——热更新(Hot Update)。
在**手机游戏(安卓/iOS)开发中:
因为手机 App 上架后,安装包(APK/IPA)是不能随便改的,所以当游戏出新活动、新角色时,开发者会把几十上百 MB 的新模型、新图片、新音频(AssetBundles / Addressables)**下载到手机里。
下载到哪呢?没错,只能下载到手机的 persistentDataPath 里!像《原神》这种游戏,手机上的这个文件夹可能会高达十几甚至几十个 GB。
但是在 PC 电脑端:
通常大型游戏更新是通过 Steam / Wegame 客户端直接覆盖 D 盘的安装目录的,PC 游戏一般不使用 persistentDataPath 来存美术资源。
13.问题
现在流程需要策划人员在excel写数据,然后在网页转换成json,程序员要根据这些数据创建对应类,相当繁琐
所以我们可以创建一个自动化工具来帮助处理这些事项,需要unity编辑器相关知识




































