详细报错如下:NotSupportedException: rigidbody property has been deprecated
(wrapper dynamic-method) System.Object.lambda_method(System.Runtime.CompilerServices.Closure,object)
Newtonsoft.Json.Serialization.ExpressionValueProvider.GetValue (System.Object target) (at /root/repo/Src/Newtonsoft.Json/Serialization/
不同的开发者报错可能会有细微不同,例如上文中的rigidbody可能换成了camera,rigidbody2D,camera等等,其实这些报错的根本原因是一样的,因为它们的共同点都是Unity的内置组件,通常是"MonoBehaviour"的子类,由于这些组件往往含有Unity引用或者其他非序列化字段,所以直接序列化这些组件会导致问题。解决方案有两个,各位根据自己实际情况任选其一即可。
解决方案一:
自定义一个"ContractResolver"来排除无法正常序列化的属性,首先创建一个类,它会检查每个属性,如果属性名是"rigidbody",则不会将其包含在序列化的JSON中,然后在我们自己的save代码所在的序列化类当中使用这个自定义的"ContractResolver"。话不多说,贴代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Reflection;
public class CustomContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
//排除名为"rigidbody"的属性
if(property.PropertyName == "rigidbody" )
{
property.ShouldSerialize = instance => false;
}
return property;
}
}
然后假设你有这样一个Save()方法,在方法内添加如下代码即可:
public void Save1()
{
int a = 1;//举例用的数据,各位开发者根据实际需求换成自己的数据即可
JsonSerializerSettings settings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
ContractResolver = new CustomContractResolver()//使用自定义的ContractResolver
};
var jsonData = JsonConvert.SerializeObject(a, settings);
}
如果运行代码后,报错中的rigidbody换成了别的属性,那么只需要在第一段代码中的排除属性部分添加||符号来增加其他的报错属性即可。
解决方案二:
还是只需要改变第一段代码中的排除部分,其他代码与方案一相同。代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Reflection;
public class CustomContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
//排除所有在UnityEngine命名空间下的属性
if(member.DeclaringType.Namespace == "UnityEngine")
{
property.ShouldSerialize = instance => false;
}
return property;
}
}
注意:方案二是一刀切的方法,可以保证不报错,但是有些需要序列化的数据可能会无法成功序列化,导致项目保存出现问题!