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();
问题原因
- 反序列化传入参数错误:反序列化时直接传入文件路径字符串而非JSON内容,路径本身不是合法JSON格式,导致解析失败。
- Hex结构体未标记可序列化:Unity的
JsonUtility仅处理标记[System.Serializable]的类型,Hex结构体未添加该标签,导致Tile.location字段无法被序列化/反序列化,JSON中缺失该字段信息。 - 只读属性的序列化特性:
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
相关产品推荐
相关产品推荐

