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

自定义Json.net转换器失效:反序列化GameObject类型不兼容报错排查

问题:Unity GameObject序列化/反序列化类型不兼容错误解决

由于GameObject无法被直接序列化,我编写了GameObjectReferencer类存储GameObject名称,试图反序列化时通过名称查找对象,但出现以下错误:

JsonSerializationException: Type specified in JSON 'GameObjectReferencer, SaveSystem, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not compatible with 'UnityEngine.GameObject, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. Path 'wrappedSaveDatas.$values[4].savedObject.other.$type', line 338, position 55.

自定义转换器代码

public class GameObjectFromReferenceConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {       
        return objectType == typeof(GameObjectReferencer);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {        
        throw new Exception("GameObjectFromReferenceConverter should only be used when loading");
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        GameObjectReferencer goRef = (GameObjectReferencer)reader.Value;

        return ((GameObjectReferencer)goRef).GetGameObject();
    }
}

GameObjectReferencer类代码

public class GameObjectReferencer
{
    public string targetGameObjectName;

    public GameObjectReferencer(string gameObjectName)
    {
        this.targetGameObjectName = gameObjectName;  
    }

    public GameObject GetGameObject()
    {
        GameObject go = GameObject.Find(targetGameObjectName);
        if (go == null)
            throw new System.Exception("Can't find object with the name " + targetGameObjectName);
        return go;
    }

    public override string ToString()
    {
        return "GameObjectReference of \"" + targetGameObjectName+ "\"";
    }

    public static GameObjectReferencer GenerateReference(GameObject gameObject)
    {
        return new GameObjectReferencer(gameObject.name);
    }
}

问题分析与修复方案

核心问题

错误根源在于:

  1. 转换器的CanConvert仅针对GameObjectReferencer类型,但反序列化的目标字段是GameObject,导致转换器未被触发
  2. ReadJson中直接将reader.Value强转为GameObjectReferencer是错误的,reader.Value是JSON原始数据,并非已实例化的GameObjectReferencer对象
  3. GameObjectReferencer缺少无参构造函数,Json.NET无法自动反序列化该类

修复步骤

1. 调整转换器的目标类型

让转换器处理GameObject类型,因为我们需要把JSON中的GameObjectReferencer数据转换为GameObject:

public override bool CanConvert(Type objectType)
{
    return objectType == typeof(GameObject);
}

2. 正确反序列化GameObjectReferencer并获取GameObject

修改ReadJson方法,先将JSON数据反序列化为GameObjectReferencer实例,再调用方法获取对应GameObject:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    var goRef = serializer.Deserialize<GameObjectReferencer>(reader);
    return goRef?.GetGameObject();
}

3. 给GameObjectReferencer添加无参构造函数

Json.NET需要无参构造函数才能完成反序列化:

public class GameObjectReferencer
{
    public string targetGameObjectName;

    // 添加无参构造函数
    public GameObjectReferencer() { }

    public GameObjectReferencer(string gameObjectName)
    {
        this.targetGameObjectName = gameObjectName;  
    }

    // 其他原有代码不变
}

4. 完善序列化逻辑(可选)

如果需要将GameObject序列化为GameObjectReferencer数据,补充WriteJson方法:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    var go = (GameObject)value;
    var goRef = GameObjectReferencer.GenerateReference(go);
    serializer.Serialize(writer, goRef);
}

5. 注册转换器到序列化配置

确保序列化/反序列化时使用该转换器:

var settings = new JsonSerializerSettings();
settings.Converters.Add(new GameObjectFromReferenceConverter());

// 序列化
string saveJson = JsonConvert.SerializeObject(yourSaveDataObject, settings);
// 反序列化
var loadedData = JsonConvert.DeserializeObject<YourSaveDataType>(saveJson, settings);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 04:10:08