You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity 3D中从JSON加载多个GameObject遇问题求助

Unity JSON存读系统问题解决方案

错误原因分析

你遇到的CS1579错误,是因为JsonUtility.FromJson<objectData>(json)返回的是单个objectData实例,而非可枚举的集合(比如List、数组),foreach语句只能遍历实现了IEnumerable接口的类型,所以无法直接遍历单个对象。

同时,原代码用File.WriteAllText写入文件时,会完全覆盖原有内容;如果直接用File.AppendAllText追加字符串,会破坏JSON格式导致无法解析,必须通过读取已有数据合并新内容的方式实现“追加”效果。

修正后的完整代码

1. 定义序列化数据类与容器类

Unity的JsonUtility无法直接序列化顶级数组/List,需要用容器类包裹;同时确保数据类可被序列化:

using System.Collections.Generic;
using UnityEngine;
using System.IO;

[Serializable]
public class ObjectDataContainer
{
    public List<objectData> objectList = new List<objectData>();
}

[Serializable]
public class objectData
{
    public string name;
    public float trfx;
    public float trfy;
    public float trfz;
    public float rotx;
    public float roty;
    public float rotz;
}

2. 修正保存方法(支持追加数据)

读取已有文件数据,合并新对象后再写入,避免覆盖原有内容:

public void SaveToJson(string ObjectName, float trfx, float trfy, float trfz, float rotx, float roty, float rotz)
{
    string filePath = Application.dataPath + "/ObjectDataFile.json";
    ObjectDataContainer container = new ObjectDataContainer();

    // 读取已有数据(如果文件存在)
    if (File.Exists(filePath))
    {
        string existingJson = File.ReadAllText(filePath);
        container = JsonUtility.FromJson<ObjectDataContainer>(existingJson);
    }

    // 创建新数据并添加到列表
    objectData newData = new objectData();
    newData.name = ObjectName;
    newData.trfx = trfx;
    newData.trfy = trfy;
    newData.trfz = trfz;
    newData.rotx = rotx;
    newData.roty = roty;
    newData.rotz = rotz;

    container.objectList.Add(newData);

    // 序列化并写入文件(合并后覆盖,实现追加效果)
    string json = JsonUtility.ToJson(container, true);
    File.WriteAllText(filePath, json);
}

3. 修正加载方法(遍历多个对象)

读取容器类中的对象列表,逐个实例化:

public void LoadFromJson()
{
    string filePath = Application.dataPath + "/ObjectDataFile.json";
    if (!File.Exists(filePath))
    {
        Debug.LogError("对象数据文件不存在");
        return;
    }

    string json = File.ReadAllText(filePath);
    ObjectDataContainer container = JsonUtility.FromJson<ObjectDataContainer>(json);

    // 遍历所有保存的对象数据
    foreach (objectData data in container.objectList)
    {
        // 注意:GameObject.Find仅能找到场景中已激活的对象,若加载预制体建议用Resources.Load
        GameObject targetPrefab = GameObject.Find(data.name);
        if (targetPrefab == null)
        {
            Debug.LogError($"找不到名为 {data.name} 的对象/预制体");
            continue;
        }

        Vector3 pos = new Vector3(data.trfx, data.trfy, data.trfz);
        Quaternion rot = Quaternion.Euler(data.rotx, data.roty, data.rotz);
        Instantiate(targetPrefab, pos, rot);
    }
}

额外注意事项

  • 预制体加载优化:如果要实例化预制体,建议将预制体放入Resources文件夹,改用Resources.Load<GameObject>(data.name)加载,避免GameObject.Find受对象激活状态的限制。
  • 字段序列化权限:确保objectData的字段为public,或添加[SerializeField]标签,否则JsonUtility无法序列化这些字段。
  • 路径适配:发布后建议改用Application.persistentDataPath作为文件存储路径,该路径在所有平台都具备读写权限,避免Application.dataPath在部分平台的权限问题。

内容的提问来源于stack exchange,提问作者ShulkTNT2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 00:45:01