Unity-原生 JsonUtility 实现 JSON 与TMP UI 交互实战

📅 2026/8/4 16:23:49
Unity-原生 JsonUtility 实现 JSON 与TMP UI 交互实战
适用场景工业仿真、PLC 参数配置、单机工具存档无需第三方插件原生 API目录前言基础原理基础版JSON 读写最简代码进阶实战TMP UI 输入 保存 / 读取按钮交互List 列表 JSON 存储方案高频踩坑大全优缺点总结1. 前言在 Unity 项目开发中经常需要保存设备参数、配置信息。很多开发者直接引入Newtonsoft.Json但中小型项目、工业仿真项目完全不需要第三方插件。 Unity 内置JsonUtility原生支持、跨平台、打包无冲突、轻量零依赖。本文分为两大模块 ✅ 基础通用 JSON 读写工具类 ✅ 进阶结合 TMP 输入框、按钮实现可视化配置保存加载开发环境Unity 2021TextMeshPro整体结构2. 基础核心原理核心 APIJsonUtility.ToJson(obj,prettyPrint:true)对象 → JSON 字符串JsonUtility.FromJsonT(jsonString)JSON 字符串 → 对象三条硬性规则99% 报错根源数据模型类必须添加[System.Serializable]需要序列化的字段必须标记为publicJsonUtility不支持直接序列化顶层 List / 数组需要包装类路径选择推荐路径Application.persistentDataPath✅ 编辑器、打包后均可读写 ❌ 禁止使用Application.dataPath打包后只读无法写入文件3. 基础版代码实现3.1 数据模型PLC 配置示例using System; [Serializable] public class PlcConfigData { public string Ip; public int Rack; public int Slot; public float Speed; public bool IsConnected; }3.2 通用静态 JSON 工具类全局调用using UnityEngine; using System.IO; public static class JsonTool { /// summary /// 保存对象到JSON文件 /// /summary /// typeparam nameT数据模型/typeparam /// param namedata数据源/param /// param namefilePath完整保存路径/param public static void SaveJsonT(T data, string filePath) { // prettyPrinttrue 格式化输出json方便手动查看 string jsonStr JsonUtility.ToJson(data, true); File.WriteAllText(filePath, jsonStr); Debug.Log($JSON保存成功{filePath}); } /// summary /// 读取JSON文件转为对象 /// /summary public static T LoadJsonT(string filePath) { if (!File.Exists(filePath)) { Debug.LogWarning(JSON配置文件不存在); return default; } string jsonStr File.ReadAllText(filePath); return JsonUtility.FromJsonT(jsonStr); } }3.3 基础调用示例using UnityEngine; using System.IO; public class JsonTest : MonoBehaviour { private string SavePath Path.Combine(Application.persistentDataPath, plcConfig.json); void Start() { // 构造测试数据 PlcConfigData data new PlcConfigData() { Ip 192.168.0.1, Rack 0, Slot 1, Speed 35.5f, IsConnected false }; // 保存 JsonTool.SaveJson(data, SavePath); // 读取 PlcConfigData loadData JsonTool.LoadJsonPlcConfigData(SavePath); if (loadData ! null) { Debug.Log(读取IP: loadData.Ip); } } }文件查找路径Windows 编辑器C:\Users\用户名\AppData\LocalLow\公司名称\项目名称\plcConfig.jsonAppData 为隐藏文件夹直接粘贴路径到资源管理器地址栏打开。4. 进阶实战TMP UI 可视化配置需求TMP 输入框填写 IP、机架、槽号、速度 2.【保存按钮】读取输入框内容写入 JSON 3.【读取按钮】加载 JSON 数据自动回填输入框4.1 场景准备在 Canvas 下创建 UI 组件TMP_InputField ×4IP 地址、机架号、槽号、速度Button ×2【保存配置】、【读取配置】 将脚本挂载到场景物体Inspector 面板拖拽绑定组件。4.2 UI 交互完整脚本using UnityEngine; using TMPro; using UnityEngine.UI; using System.IO; public class PlcConfigUI : MonoBehaviour { [Header(TMP输入框绑定)] public TMP_InputField tmpIp; public TMP_InputField tmpRack; public TMP_InputField tmpSlot; public TMP_InputField tmpSpeed; [Header(按钮绑定)] public Button btnSave; public Button btnLoad; // 配置文件路径 private string SavePath Path.Combine(Application.persistentDataPath, plcConfig.json); void Start() { // 绑定按钮点击事件 btnSave.onClick.AddListener(OnSaveClick); btnLoad.onClick.AddListener(OnLoadClick); // 可选启动游戏自动加载上次保存的参数 // OnLoadClick(); } /// summary /// 保存按钮回调读取UI数据 → 写入JSON /// /summary void OnSaveClick() { PlcConfigData config new PlcConfigData(); config.Ip tmpIp.text; // TryParse安全转换非法输入不会导致程序崩溃 int.TryParse(tmpRack.text, out config.Rack); int.TryParse(tmpSlot.text, out config.Slot); float.TryParse(tmpSpeed.text, out config.Speed); JsonTool.SaveJson(config, SavePath); Debug.Log(参数保存完成); } /// summary /// 读取按钮回调加载JSON → 回填UI输入框 /// /summary void OnLoadClick() { PlcConfigData config JsonTool.LoadJsonPlcConfigData(SavePath); if (config null) { Debug.LogError(配置文件不存在无法读取); return; } tmpIp.text config.Ip; tmpRack.text config.Rack.ToString(); tmpSlot.text config.Slot.ToString(); tmpSpeed.text config.Speed.ToString(); Debug.Log(参数读取成功已回填界面); } private void OnDestroy() { // 移除监听防止内存泄漏 btnSave.onClick.RemoveListener(OnSaveClick); btnLoad.onClick.RemoveListener(OnLoadClick); } }可选优化建议限制输入框只能输入数字选中 TMP InputField 组件 →ContentType设置为Number启动自动加载取消 Start 函数中OnLoadClick()的注释新增 TMP 文本组件展示「保存成功 / 失败」提示保存数据保存效果修改数据读取数据5. List 列表数据存储方案问题JsonUtility 不支持直接序列化顶层数组 / List会报错。解决方案外层包装类using System; using System.Collections.Generic; [Serializable] public class DataListWrapper { public ListPlcConfigData DataList; }使用示例//保存列表 DataListWrapper wrapper new DataListWrapper(); wrapper.DataList new ListPlcConfigData(); wrapper.DataList.Add(new PlcConfigData() { Ip 192.168.0.2, Rack 0, Slot 2 }); JsonTool.SaveJson(wrapper, SavePath); //读取列表 DataListWrapper loadWrap JsonTool.LoadJsonDataListWrapper(SavePath); if (loadWrap ! null) { foreach (var item in loadWrap.DataList) { Debug.Log(item.Ip); } }6. 高频踩坑大全❌ 数据类缺少[Serializable]现象生成空 json{}读取所有字段为空无报错 ✅ 解决方案必须添加序列化标签❌ 字段使用 private 修饰 现象字段无法序列化json 看不到数据 ✅ 解决方案序列化字段使用 public❌ 保存后立刻读取偶尔读取失败 原因操作系统磁盘写入延迟 ✅ 解决方案使用协程延迟读取❌ 尝试序列化 Dictionary 原生 JsonUtility 不支持字典方案改用 List 键值对模型 / Newtonsoft.Json❌ 使用Application.dataPath做存档路径 打包后目录只读无法创建文件必须使用persistentDataPath7. 优缺点总结✅ 优点零第三方插件原生自带无版本冲突跨平台兼容 Windows / Android / IOS轻量高效工业仿真、工具项目完全够用❌ 缺点不支持顶层数组、List原生不支持 Dictionary 类型