Unity背包系统 - JSON读取完整实现
一、Excel转JSON方法
1.1 Excel表格格式示例
创建Items.xlsx,结构如下:
| ItemName | ItemImageName | ItemCount | ItemNumber | ItemType |
|---|---|---|---|---|
| 生命药水 | HealthPotion | 5 | 1001 | 1 |
| 魔力药水 | ManaPotion | 3 | 1002 | 1 |
| 长剑 | Sword | 1 | 2001 | 2 |
1.2 将Excel转为JSON的方法
方法一:使用在线转换工具
将Excel另存为CSV格式
使用CSV转JSON在线工具
保存为
Items.json,放到Unity的Resources文件夹中
方法二:使用C#脚本转换
创建ExcelToJsonConverter.cs:
using UnityEngine; using System.IO; #if UNITY_EDITOR using Excel = Microsoft.Office.Interop.Excel; #endif public class ExcelToJsonConverter : MonoBehaviour { #if UNITY_EDITOR [ContextMenu("Convert Excel to JSON")] public void ConvertExcelToJson() { string excelPath = Application.dataPath + "/Items.xlsx"; string jsonPath = Application.dataPath + "/Resources/Items.json"; Excel.Application excelApp = new Excel.Application(); Excel.Workbook workbook = excelApp.Workbooks.Open(excelPath); Excel.Worksheet worksheet = workbook.Sheets[1]; // 读取数据转换为JSON // ... 转换代码 ... workbook.Close(); excelApp.Quit(); } #endif }二、完整的JSON读取实现
2.1 JSON数据结构类
// ItemData.cs - JSON数据类 using System; using System.Collections.Generic; [Serializable] public class ItemList { public List<ItemJsonData> items; } [Serializable] public class ItemJsonData { public string itemName; public string imageName; // 图片文件名 public int itemCount; public int itemNumber; public int itemType; }2.2 道具信息类(优化版)
// itemonfro.cs - 道具信息类 using UnityEngine; [System.Serializable] public class itemonfro { public string Itemname; public Sprite ItemImage; public int ItemCount; public int ItemNumBu; public int ItemType; // 空构造函数供JSON解析使用 public itemonfro() { } // 构造函数 public itemonfro(string name, Sprite image, int count = 1, int id = 0, int type = 0) { Itemname = name; ItemImage = image; ItemCount = count; ItemNumBu = id; ItemType = type; } }2.3 完整的ItemClone类
using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.UI; public class ItemClone : MonoBehaviour { [Header("UI组件")] public GameObject ItemGridPre; // 道具格子预制体 public RectTransform ItemGridParent; // Content父物体 [Header("资源管理")] public List<Sprite> ItemImageInfro; // 所有道具图片列表 public string jsonFilePath = "Items"; // JSON文件路径(不带后缀) [Header("道具数据")] public itemonfro[] ItemAllInfo; // 道具信息数组 // 图片名称映射字典 private Dictionary<string, Sprite> spriteDictionary = new Dictionary<string, Sprite>(); private void Awake() { // 1. 初始化图片字典 InitializeSpriteDictionary(); // 2. 从JSON加载数据 LoadDataFromJSON(); // 3. 克隆道具格子 CloneItem(); } // 初始化图片字典 void InitializeSpriteDictionary() { spriteDictionary.Clear(); foreach (Sprite sprite in ItemImageInfro) { if (sprite != null && !spriteDictionary.ContainsKey(sprite.name)) { spriteDictionary.Add(sprite.name, sprite); } } } // 从JSON文件加载数据 void LoadDataFromJSON() { // 1. 加载JSON文件 TextAsset jsonFile = Resources.Load<TextAsset>(jsonFilePath); if (jsonFile == null) { Debug.LogError($"找不到JSON文件: {jsonFilePath}"); CreateDefaultItems(); return; } try { // 2. 解析JSON数据 ItemList itemList = JsonUtility.FromJson<ItemList>(jsonFile.text); if (itemList == null || itemList.items == null) { Debug.LogError("JSON解析失败,使用默认数据"); CreateDefaultItems(); return; } // 3. 创建itemonfro数组 ItemAllInfo = new itemonfro[itemList.items.Count]; for (int i = 0; i < itemList.items.Count; i++) { ItemJsonData jsonData = itemList.items[i]; // 创建新的itemonfro对象 ItemAllInfo[i] = new itemonfro(); // 赋值数据 ItemAllInfo[i].Itemname = jsonData.itemName; ItemAllInfo[i].ItemCount = jsonData.itemCount; ItemAllInfo[i].ItemNumBu = jsonData.itemNumber; ItemAllInfo[i].ItemType = jsonData.itemType; // 通过图片名称查找Sprite if (!string.IsNullOrEmpty(jsonData.imageName)) { if (spriteDictionary.ContainsKey(jsonData.imageName)) { ItemAllInfo[i].ItemImage = spriteDictionary[jsonData.imageName]; } else { Debug.LogWarning($"找不到图片: {jsonData.imageName},使用默认图片"); ItemAllInfo[i].ItemImage = GetDefaultSprite(); } } else { ItemAllInfo[i].ItemImage = GetDefaultSprite(); } } Debug.Log($"成功加载 {ItemAllInfo.Length} 个道具"); } catch (System.Exception e) { Debug.LogError($"JSON解析错误: {e.Message}"); CreateDefaultItems(); } } // 获取默认Sprite Sprite GetDefaultSprite() { if (ItemImageInfro != null && ItemImageInfro.Count > 0) return ItemImageInfro[0]; return null; } // 创建默认道具数据(JSON加载失败时使用) void CreateDefaultItems() { ItemAllInfo = new itemonfro[5]; ItemAllInfo[0] = new itemonfro("生命药水", GetDefaultSprite(), 5, 1001, 1); ItemAllInfo[1] = new itemonfro("魔力药水", GetDefaultSprite(), 3, 1002, 1); ItemAllInfo[2] = new itemonfro("长剑", GetDefaultSprite(), 1, 2001, 2); ItemAllInfo[3] = new itemonfro("盾牌", GetDefaultSprite(), 1, 2002, 2); ItemAllInfo[4] = new itemonfro("金币", GetDefaultSprite(), 999, 3001, 3); } // 克隆道具到UI void CloneItem() { if (ItemAllInfo == null || ItemAllInfo.Length == 0) { Debug.LogError("没有道具数据可显示"); return; } // 清空现有道具格子 foreach (Transform child in ItemGridParent) { Destroy(child.gameObject); } // 克隆新道具格子 for (int i = 0; i < ItemAllInfo.Length && i < 100; i++) // 限制最多100个 { // 实例化预制体 GameObject TempItemGrid = Instantiate(ItemGridPre, ItemGridParent); TempItemGrid.name = $"Item_{ItemAllInfo[i].Itemname}_{i}"; try { // 获取UI组件并赋值 TextMeshProUGUI nameText = TempItemGrid.transform .GetChild(2) // 假设第3个子物体是名称容器 .GetChild(0) .GetChild(0) .GetComponent<TextMeshProUGUI>(); Image itemImage = TempItemGrid.transform .GetChild(3) // 假设第4个子物体是图片 .GetComponent<Image>(); // 赋值数据 if (nameText != null) nameText.text = ItemAllInfo[i].Itemname; if (itemImage != null && ItemAllInfo[i].ItemImage != null) itemImage.sprite = ItemAllInfo[i].ItemImage; // 设置计数显示(可选) Transform countTransform = TempItemGrid.transform.Find("ItemCount"); if (countTransform != null) { TextMeshProUGUI countText = countTransform.GetComponent<TextMeshProUGUI>(); if (countText != null) { countText.text = ItemAllInfo[i].ItemCount > 1 ? ItemAllInfo[i].ItemCount.ToString() : ""; } } } catch (System.Exception e) { Debug.LogError($"设置道具 {i} 时出错: {e.Message}"); } } } // 重新加载数据(可在编辑器测试用) [ContextMenu("重新加载JSON数据")] void ReloadData() { LoadDataFromJSON(); CloneItem(); } }三、JSON文件示例
{ "items": [ { "itemName": "生命药水", "imageName": "HealthPotion", "itemCount": 5, "itemNumber": 1001, "itemType": 1 }, { "itemName": "魔力药水", "imageName": "ManaPotion", "itemCount": 3, "itemNumber": 1002, "itemType": 1 }, { "itemName": "长剑", "imageName": "Sword", "itemCount": 1, "itemNumber": 2001, "itemType": 2 }, { "itemName": "盾牌", "imageName": "Shield", "itemCount": 1, "itemNumber": 2002, "itemType": 2 }, { "itemName": "钥匙", "imageName": "Key", "itemCount": 3, "itemNumber": 3001, "itemType": 3 } ] }、使用步骤
准备图片资源
将道具图片导入Unity
图片命名与JSON中的
imageName一致将所有图片拖到
ItemImageInfro列表中
创建JSON文件
在
Assets/Resources文件夹中创建Items.json按格式编写道具数据
设置UI组件
将预制体和Content拖到对应位置
确保预制体结构与代码中的GetChild索引匹配
运行测试
运行游戏即可看到从JSON加载的道具
修改JSON文件后,可在编辑器中使用"重新加载JSON数据"菜单更新
五、注意事项
图片查找:确保JSON中的
imageName与导入的Sprite名称完全一致JSON格式:必须严格按照JSON格式,可使用JSON验证工具
路径问题:JSON文件必须放在
Resources文件夹内预制体结构:确保预制体结构与代码中的
GetChild索引匹配
这样就完成了从Excel到JSON再到Unity背包的完整流程!