UGUI 读取JSON动态克隆背包道具信息

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的方法

方法一:使用在线转换工具

  1. 将Excel另存为CSV格式

  2. 使用CSV转JSON在线工具

  3. 保存为Items.json,放到Unity的Resources文件夹中

方法二:使用C#脚本转换

创建ExcelToJsonConverter.cs

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数据结构类

cs 复制代码
// 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 道具信息类(优化版)

cs 复制代码
// 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类

cs 复制代码
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文件示例

cs 复制代码
{
    "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
        }
    ]
}

、使用步骤

  1. 准备图片资源

    • 将道具图片导入Unity

    • 图片命名与JSON中的imageName一致

    • 将所有图片拖到ItemImageInfro列表中

  2. 创建JSON文件

    • Assets/Resources文件夹中创建Items.json

    • 按格式编写道具数据

  3. 设置UI组件

    • 将预制体和Content拖到对应位置

    • 确保预制体结构与代码中的GetChild索引匹配

  4. 运行测试

    • 运行游戏即可看到从JSON加载的道具

    • 修改JSON文件后,可在编辑器中使用"重新加载JSON数据"菜单更新

五、注意事项

  1. 图片查找 :确保JSON中的imageName与导入的Sprite名称完全一致

  2. JSON格式 :必须严格按照JSON格式,可使用JSON验证工具

  3. 路径问题 :JSON文件必须放在Resources文件夹内

  4. 预制体结构 :确保预制体结构与代码中的GetChild索引匹配

这样就完成了从Excel到JSON再到Unity背包的完整流程!

相关推荐
望外追晚4 小时前
mask_color_map.json丢失,导致分割标签.png无法导入X-Anylabeling的解决办法
人工智能·计算机视觉·json·paddlepaddle
咘噜biu5 小时前
Java 安全的打印对象数据到日志
java·json·日志·脱敏
未来魔导14 小时前
go语言中json操作总结
数据分析·go·json
青鱼入云1 天前
@JsonValue和@JsonCreator介绍
json·jackson
这儿有一堆花1 天前
JSON 与 MongoDB:直存对象的便利与隐性代价
数据库·mongodb·json
╰⋛⋋⊱⋋翅膀⋌⊰⋌⋚╯2 天前
cJSON使用
json
正在走向自律2 天前
从Oracle到金仓KES:PL/SQL兼容性与高级JSON处理实战解析
数据库·sql·oracle·json·金仓数据库·电科金仓·兼容性挑战
皮卡龙3 天前
Java常用的JSON
java·开发语言·spring boot·json
@#---3 天前
如何准确判断json文件并且拿到我想要的信息
android·python·json