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

Unity无法序列化自定义结构体/类到JSON的问题求助

六边形网格瓦片游戏JSON序列化/反序列化问题排查与解决

问题场景

开发六边形网格游戏时,瓦片、坐标结构体、地形类型定义如下:

Tile类

[System.Serializable]
public class Tile
{
    public Hex location;

    public TerrainType terrainType;

    public Color color { get { return terrainType.color; } }

    public int distance;

    public string label;

    public int cost { get { return terrainType.baseMPCost; } }

    public int new_cost;
}

Hex坐标结构体

public struct Hex
{
    public int q;

    public int r;

    public Hex (int Q, int R)
    {
        q = Q;
        r = R;
    }

    public int s
    {
        get { return -q - r; }
    }

    public float x
    {
        get { return (3f / 2f) * HexMetrics.outerRadius * q; }
    }

    public float y
    {
        get { return (Mathf.Sqrt(3f) / 2f * HexMetrics.outerRadius * q + Mathf.Sqrt(3f) * HexMetrics.outerRadius * r); }
    }
}

TerrainType地形结构体

[System.Serializable]
public struct TerrainType
{
    public TerrainType(string Name, int BaseMPCost, Color Color)
    {
        name = Name;
        baseMPCost = BaseMPCost;
        color = Color;
    }
    public string name;
    public int baseMPCost;
    public Color color;
}

使用Stack Overflow的JsonHelper脚本序列化瓦片列表到JSON文件,反序列化时出现以下错误:

ArgumentException: JSON parse error: Invalid value.
UnityEngine.JsonUtility.FromJson (System.String json, System.Type type) (at <1a491ffb1c7c42349a050cc1542277fb>:0)
UnityEngine.JsonUtility.FromJson[T] (System.String json) (at <1a491ffb1c7c42349a050cc1542277fb>:0)
JsonHelper.FromJson[T] (System.String json) (at Assets/Scripts/JsonHelper.cs:9)
InputStateMapEdit.HandleInput () (at Assets/Scripts/StateMachine/InputStates/InputStateMapEdit.cs:57)
InputManager.Update () (at Assets/Scripts/InputManager.cs:40)

将JSON导入json2csharp.com生成的类结构与自定义类型存在差异,希望避免编写中间转换类,排查问题原因并解决。

序列化代码:

var m = map.grid.ToArray();
string grid = JsonHelper.ToJson<Tile>(m);
File.WriteAllText("C:/SG/Strategy Game/Assets/test.json", grid);

反序列化代码:

var m = JsonHelper.FromJson<Tile>("C:/SG/Strategy Game/Assets/test.json");
map.grid = m.ToList();

问题原因

  1. 反序列化传入参数错误:反序列化时直接传入文件路径字符串而非JSON内容,路径本身不是合法JSON格式,导致解析失败。
  2. Hex结构体未标记可序列化:Unity的JsonUtility仅处理标记[System.Serializable]的类型,Hex结构体未添加该标签,导致Tile.location字段无法被序列化/反序列化,JSON中缺失该字段信息。
  3. 只读属性的序列化特性:Tile类中的color、cost是只读属性,JsonUtility会忽略这类属性,导致JSON中无对应字段,这是正常行为,但可能被误判为字段缺失。

解决方案

1. 修复反序列化的文件读取逻辑

先读取JSON文件内容,再传入JsonHelper进行反序列化:

string jsonContent = File.ReadAllText("C:/SG/Strategy Game/Assets/test.json");
var m = JsonHelper.FromJson<Tile>(jsonContent);
map.grid = m.ToList();

2. 为Hex结构体添加可序列化标签

修改Hex结构体,添加[System.Serializable]:

[System.Serializable]
public struct Hex
{
    public int q;

    public int r;

    public Hex (int Q, int R)
    {
        q = Q;
        r = R;
    }

    public int s
    {
        get { return -q - r; }
    }

    public float x
    {
        get { return (3f / 2f) * HexMetrics.outerRadius * q; }
    }

    public float y
    {
        get { return (Mathf.Sqrt(3f) / 2f * HexMetrics.outerRadius * q + Mathf.Sqrt(3f) * HexMetrics.outerRadius * r); }
    }
}

3. 忽略只读属性的序列化差异

Tile.color和Tile.cost是依赖terrainType的计算属性,无需序列化,只要terrainType正确序列化,反序列化后这些属性会自动计算出正确值,无需额外处理。

4. 验证序列化结果

修改后重新执行序列化,检查生成的JSON文件是否包含location(含q、r字段)、terrainType(含name、baseMPCost、color字段)的完整内容,确保结构与自定义类型匹配。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 00:21:39