赞
踩
在Unity中使用NewtonJson时,如果要序列化的类继承了别的类,可能报如下错误:
JsonSerializationException: Self referencing loop detected for property......
解决的方法是新建一个JsonSerializerSettings对象,并设置对象的ReferenceLoopHandling参数为:ReferenceLoopHandling.Ignore,然后在序列化时将这个对象作为参数添加进去。参考如下:
- var settings = new JsonSerializerSettings();
- settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
- string json = JsonConvert.SerializeObject(infos, settings);
如果我们要序列化一个基类的数组,由于子类可能会出现参数相同,但是类型不同的问题,最好在JsonSerializerSettings对象里面设置TypeNameHandling的值为TypeNameHandling.Auto,这样NewtonJson序列化时会在必要的情况下添加对象的类型信息。参考如下:
- var settings = new JsonSerializerSettings();
- settings.TypeNameHandling = TypeNameHandling.Auto;
- settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
- string json = JsonConvert.SerializeObject(infos, settings);
序列化的结果参考如下:
- [
- {
- "$type": "BoxColliderInfo, Assembly-CSharp",
- "size": {
- "x": 1.0,
- "y": 1.0,
- "z": 1.0,
- "normalized": {
- "x": 0.577350259,
- "y": 0.577350259,
- "z": 0.577350259,
- "magnitude": 1.0,
- "sqrMagnitude": 0.99999994
- },
- "magnitude": 1.73205078,
- "sqrMagnitude": 3.0
- },
- "center": {
- "x": 0.0,
- "y": 1.0,
- "z": 0.0,
- "magnitude": 1.0,
- "sqrMagnitude": 1.0
- },
- "cip": "0"
- },
- {
- "$type": "SphereColliderInfo, Assembly-CSharp",
- "radius": 2.5,
- "center": {
- "x": 1.0,
- "y": 0.0,
- "z": 0.0,
- "magnitude": 1.0,
- "sqrMagnitude": 1.0
- },
- "cip": "1"
- }
- ]
需要注意的是,这里面添加了"$type"字段,这是为了在反序列化是能得到正确类型的对象。
最后需要说的是,在序列化和反序列化时应该使用相同的JsonSerializerSettings对象设置。于是我写了一个类来简化使用NewtonJson的代码,参考如下:
- using Newtonsoft.Json;
-
- public class JsonTool
- {
- static JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, ReferenceLoopHandling = ReferenceLoopHandling.Ignore};
-
- public static string ToJson(object obj) { return JsonConvert.SerializeObject(obj, settings);}
- public static T FromJson<T>(string json) { return JsonConvert.DeserializeObject<T>(json, settings); }
- }
现在,我们使用JsonTool.ToJson和JsonTool.FromJson就可以了。
如果你之前使用的是Unity内置的JsonUtility,现在直接用JsonTool搜索并替换JsonUtility就可以了。
//----------------------------------------------------------------------------------------------------------------------------
好吧,其实还是有问题。
本来以为万事大吉了,结果发现NewtonJson有个很神奇的错误,如果我给一个Color变量赋值,如果里面的rgba值为0或者为1就没有问题,如果是0到1之间的浮点数,Unity就直接退出,出这个问题的时候一直以为是别的方面的错误,最后一行代码一行代码的测试,才发现居然是NewtonJson的问题,最后想了个别的办法,所有用于序列化的类里面的Color都改成自定义的Vector4D,这样就不会出错,只不过要重载一大堆运算符,尤其是Vector4D,既要重载Vector4D和Vector4之间的操作,又要重载Vector4D和Color之间的操作,本来还想重载Vector4D和Quaternion之间的操作,感觉不大可能序列化Quaternion方面的东西,算了。
当时序列化的时候还发现一个问题,就是序列化Vector3的时候会把Vector3对象的magnitude和sqrMagnitude的值也序列化了,这个是没有必要的,所以干脆在用于序列化的类里面把Vector3用Vector3D替代,把Vector2用Vector2D替代,这样序列化出来的内容就简洁而且不报错了。就是上面代码中的那行
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
可以不用写了。
所定义的Vector2D、Vector3D、Vector4D参考如下:
- using System;
- using UnityEngine;
-
- [Serializable]
- public class TranP
- {
- public Vector3D position = Vector3.zero;
- public TranP(Vector3 position)
- {
- this.position = position;
- }
- public TranP() { position = Vector3.zero; }
- }
-
- [Serializable]
- public class TranPR : TranP
- {
- public Vector3D euler = Vector3.zero;
- public TranPR(Vector3 position, Vector3 euler) : base(position)
- {
- this.euler = euler;
- }
-
- public TranPR() : base() { euler = Vector3.zero; }
-
- public Quaternion GetRotation() { return Quaternion.Euler(euler); }
- }
-
- [Serializable]
- public class TranPRS : TranPR
- {
- public Vector3D scale = Vector3.one;
- public TranPRS(Vector3 position, Vector3 euler, Vector3 scale) : base(position, euler)
- {
- this.scale = scale;
- }
- public TranPRS() : base() { scale = Vector3.one; }
- }
-
- [Serializable]
- public class TranNP : TranP
- {
- public string name;
- public TranNP(string name, Vector3 position) : base(position)
- {
- this.name = name;
- }
- }
-
- [Serializable]
- public class TranNPR : TranPR
- {
- public string name;
- public TranNPR(string name, Vector3 position, Vector3 euler) : base(position, euler)
- {
- this.name = name;
- }
- }
-
- [Serializable]
- public class TranNPRS : TranPRS
- {
- public string name;
- public TranNPRS(string name, Vector3 position, Vector3 euler, Vector3 scale) : base(position, euler, scale)
- {
- this.name = name;
- }
- }
-
- [Serializable]
- public class CamRot
- {
- public float rotH;
- public float rotV;
- public CamRot(float rotH, float rotV) { this.rotH = rotH; this.rotV = rotV; }
- }
-
- [Serializable]
- public class TranCam
- {
- public Vector3D position;
- public CamRot camRot;
- public TranCam(Vector3 position, CamRot camRot)
- {
- this.position = position;
- this.camRot = camRot;
- }
- }
-
- [Serializable]
- public class Vector2D
- {
- public float x;
- public float y;
-
- public Vector2D()
- {
- x = 0;
- y = 0;
- }
-
- public Vector2D(float x, float y)
- {
- this.x = x;
- this.y = y;
- }
-
- public float GetSqrtMagnitude()
- {
- return x * x + y * y;
- }
-
- public float GetMagnitude()
- {
- return Mathf.Sqrt(GetSqrtMagnitude());
- }
-
- public static implicit operator Vector2D(Vector2 v)
- {
- return new Vector2D(v.x, v.y);
- }
-
- public static implicit operator Vector2(Vector2D v)
- {
- return new Vector2(v.x, v.y);
- }
-
- public static Vector2D operator +(Vector2D v1, Vector2D v2)
- {
- return new Vector2D(v1.x + v2.x, v1.y + v2.y);
- }
-
- public static Vector2D operator -(Vector2D v1, Vector2D v2)
- {
- return new Vector2D(v1.x - v2.x, v1.y - v2.y);
- }
-
- public static Vector2D operator *(Vector2D v, float f)
- {
- return new Vector2D(v.x * f, v.y * f);
- }
-
- public static Vector2D operator /(Vector2D v, float f)
- {
- return new Vector2D(v.x / f, v.y / f);
- }
-
- public static Vector2D operator +(Vector2D v1, Vector2 v2)
- {
- return new Vector2D(v1.x + v2.x, v1.y + v2.y);
- }
-
- public static Vector2D operator -(Vector2D v1, Vector2 v2)
- {
- return new Vector2D(v1.x - v2.x, v1.y - v2.y);
- }
-
- public static Vector2D operator +(Vector2 v1, Vector2D v2)
- {
- return new Vector2D(v1.x + v2.x, v1.y + v2.y);
- }
-
- public static Vector2D operator -(Vector2 v1, Vector2D v2)
- {
- return new Vector2D(v1.x - v2.x, v1.y - v2.y);
- }
- }
-
- [Serializable]
- public class Vector3D
- {
- public float x;
- public float y;
- public float z;
-
- public Vector3D()
- {
- x = 0;
- y = 0;
- z = 0;
- }
-
- public Vector3D(float x, float y, float z)
- {
- this.x = x;
- this.y = y;
- this.z = z;
- }
-
- public float GetSqrtMagnitude()
- {
- return x * x + y * y + z * z;
- }
-
- public float GetMagnitude()
- {
- return Mathf.Sqrt(GetSqrtMagnitude());
- }
-
- public static implicit operator Vector3D(Vector3 v)
- {
- return new Vector3D(v.x, v.y, v.z);
- }
-
- public static implicit operator Vector3(Vector3D v)
- {
- return new Vector3(v.x, v.y, v.z);
- }
-
- public static Vector3D operator +(Vector3D v1, Vector3D v2)
- {
- return new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
- }
-
- public static Vector3D operator -(Vector3D v1, Vector3D v2)
- {
- return new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
- }
-
- public static Vector3D operator *(Vector3D v, float f)
- {
- return new Vector3D(v.x * f, v.y * f, v.z * f);
- }
-
- public static Vector3D operator /(Vector3D v, float f)
- {
- return new Vector3D(v.x / f, v.y / f, v.z / f);
- }
-
- public static Vector3D operator +(Vector3D v1, Vector3 v2)
- {
- return new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
- }
-
- public static Vector3D operator -(Vector3D v1, Vector3 v2)
- {
- return new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
- }
-
- public static Vector3D operator +(Vector3 v1, Vector3D v2)
- {
- return new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
- }
-
- public static Vector3D operator -(Vector3 v1, Vector3D v2)
- {
- return new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
- }
- }
-
- [Serializable]
- public class Vector4D
- {
- public float r;
- public float g;
- public float b;
- public float a;
-
- public Vector4D() { r = 1; g = 1; b = 1; a = 1; }
-
- public Vector4D(float r, float g, float b, float a)
- {
- this.r = r;
- this.g = g;
- this.b = b;
- this.a = a;
- }
-
- public static implicit operator Vector4D(Color c)
- {
- return new Vector4D(c.r, c.g, c.b, c.a);
- }
-
- public static implicit operator Color(Vector4D c)
- {
- return new Color(c.r, c.g, c.b, c.a);
- }
-
- public static Vector4D operator +(Vector4D v1, Vector4D v2)
- {
- return new Vector4D(v1.r + v2.r, v1.g + v2.g, v1.b + v2.b, v1.a + v2.a);
- }
-
- public static Vector4D operator -(Vector4D v1, Vector4D v2)
- {
- return new Vector4D(v1.r - v2.r, v1.g - v2.g, v1.b - v2.b, v1.a - v2.a);
- }
-
- public static Vector4D operator *(Vector4D v, float f)
- {
- return new Vector4D(v.r * f, v.g * f, v.b * f, v.a * f);
- }
-
- public static Vector4D operator /(Vector4D v, float f)
- {
- return new Vector4D(v.r / f, v.g / f, v.b / f, v.a / f);
- }
-
- public static Vector4D operator +(Vector4D v1, Vector4 v2)
- {
- return new Vector4D(v1.r + v2.x, v1.g + v2.y, v1.b + v2.z, v1.a + v2.w);
- }
-
- public static Vector4D operator -(Vector4D v1, Vector4 v2)
- {
- return new Vector4D(v1.r - v2.x, v1.g - v2.y, v1.b - v2.z, v1.a - v2.w);
- }
-
- public static Vector4D operator +(Vector4 v1, Vector4D v2)
- {
- return new Vector4D(v1.x + v2.r, v1.y + v2.g, v1.z + v2.b, v1.w + v2.a);
- }
-
- public static Vector4D operator -(Vector4 v1, Vector4D v2)
- {
- return new Vector4D(v1.x - v2.r, v1.y - v2.g, v1.z - v2.b, v1.w - v2.a);
- }
- }
希望这次没有问题了吧。
//----------------------------------------------------------------------------------------------------------------------------
不是的,还有一些小问题,代码里面有些地方用的是Vector3的magnitude,但是Vector3D里面没有,关键是我不能加这个属性啊,一加这个属性,序列化又多出magnitude和sqrtMagnitude这个内容了,所以如果需要的化,就添加一个GetMagnitude()方法和GetSqrtMagnitude()方法替代,或者用Vector3.Distance方法解决吧,有些地方需要Quaternion对象作为返回属性的就写个GetQuaternion()方法替代吧。
希望没问题了,呵呵。
//----------------------------------------------------------------------------------------------------------------------------
好吧,我又幼稚了,原来的Vector3是struct,但是现在定义的Vector3D之类的都是class,由于class允许设置位null,但是struct不行,所以如果当Vector3D的对象为null的时候,如果赋值给一个Vector3对象,会出现莫名奇妙的运行错误,并且不提示!比如说for循环或者foreach循环执行到这个赋值的位置直接跳出去!疯了!!疯了!!!
后来查看了一下相关代码,应该是这样的,当class的对象为null赋值给一个struct时,就会导致执行错误,比如说莫名其妙的跳出循环,因为struct不可能是null啊,关键是不报错,后面的还能正常执行,也是醉了。
所以最终的代码应该是把class都换成struct,就像下面这样的:
- [Serializable]
- public struct Vector2D
- {
- public float x;
- public float y;
-
- public Vector2D(float x, float y)
- {
- this.x = x;
- this.y = y;
- }
-
- public readonly float GetSqrtMagnitude()
- {
- return x * x + y * y;
- }
-
- public readonly float GetMagnitude()
- {
- return Mathf.Sqrt(GetSqrtMagnitude());
- }
-
- public static implicit operator Vector2D(Vector2 v)
- {
- return new Vector2D(v.x, v.y);
- }
-
- public static implicit operator Vector2(Vector2D v)
- {
- return new Vector2(v.x, v.y);
- }
-
- public static Vector2D operator +(Vector2D v1, Vector2D v2)
- {
- return new Vector2D(v1.x + v2.x, v1.y + v2.y);
- }
-
- public static Vector2D operator -(Vector2D v1, Vector2D v2)
- {
- return new Vector2D(v1.x - v2.x, v1.y - v2.y);
- }
-
- public static Vector2D operator *(Vector2D v, float f)
- {
- return new Vector2D(v.x * f, v.y * f);
- }
-
- public static Vector2D operator /(Vector2D v, float f)
- {
- return new Vector2D(v.x / f, v.y / f);
- }
-
- public static Vector2D operator +(Vector2D v1, Vector2 v2)
- {
- return new Vector2D(v1.x + v2.x, v1.y + v2.y);
- }
-
- public static Vector2D operator -(Vector2D v1, Vector2 v2)
- {
- return new Vector2D(v1.x - v2.x, v1.y - v2.y);
- }
-
- public static Vector2D operator +(Vector2 v1, Vector2D v2)
- {
- return new Vector2D(v1.x + v2.x, v1.y + v2.y);
- }
-
- public static Vector2D operator -(Vector2 v1, Vector2D v2)
- {
- return new Vector2D(v1.x - v2.x, v1.y - v2.y);
- }
- }
-
- [Serializable]
- public struct Vector3D
- {
- public float x;
- public float y;
- public float z;
-
- public Vector3D(float x, float y, float z)
- {
- this.x = x;
- this.y = y;
- this.z = z;
- }
-
- public readonly float GetSqrtMagnitude()
- {
- return x * x + y * y + z * z;
- }
-
- public readonly float GetMagnitude()
- {
- return Mathf.Sqrt(GetSqrtMagnitude());
- }
-
- public static implicit operator Vector3D(Vector3 v)
- {
- return new Vector3D(v.x, v.y, v.z);
- }
-
- public static implicit operator Vector3(Vector3D v)
- {
- return new Vector3(v.x, v.y, v.z);
- }
-
- public static Vector3D operator +(Vector3D v1, Vector3D v2)
- {
- return new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
- }
-
- public static Vector3D operator -(Vector3D v1, Vector3D v2)
- {
- return new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
- }
-
- public static Vector3D operator *(Vector3D v, float f)
- {
- return new Vector3D(v.x * f, v.y * f, v.z * f);
- }
-
- public static Vector3D operator /(Vector3D v, float f)
- {
- return new Vector3D(v.x / f, v.y / f, v.z / f);
- }
-
- public static Vector3D operator +(Vector3D v1, Vector3 v2)
- {
- return new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
- }
-
- public static Vector3D operator -(Vector3D v1, Vector3 v2)
- {
- return new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
- }
-
- public static Vector3D operator +(Vector3 v1, Vector3D v2)
- {
- return new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
- }
-
- public static Vector3D operator -(Vector3 v1, Vector3D v2)
- {
- return new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
- }
- }
-
- [Serializable]
- public struct Vector4D
- {
- public float r;
- public float g;
- public float b;
- public float a;
-
- public Vector4D(float r, float g, float b, float a)
- {
- this.r = r;
- this.g = g;
- this.b = b;
- this.a = a;
- }
-
- public static implicit operator Vector4D(Color c)
- {
- return new Vector4D(c.r, c.g, c.b, c.a);
- }
-
- public static implicit operator Color(Vector4D c)
- {
- return new Color(c.r, c.g, c.b, c.a);
- }
-
- public static Vector4D operator +(Vector4D v1, Vector4D v2)
- {
- return new Vector4D(v1.r + v2.r, v1.g + v2.g, v1.b + v2.b, v1.a + v2.a);
- }
-
- public static Vector4D operator -(Vector4D v1, Vector4D v2)
- {
- return new Vector4D(v1.r - v2.r, v1.g - v2.g, v1.b - v2.b, v1.a - v2.a);
- }
-
- public static Vector4D operator *(Vector4D v, float f)
- {
- return new Vector4D(v.r * f, v.g * f, v.b * f, v.a * f);
- }
-
- public static Vector4D operator /(Vector4D v, float f)
- {
- return new Vector4D(v.r / f, v.g / f, v.b / f, v.a / f);
- }
-
- public static Vector4D operator +(Vector4D v1, Vector4 v2)
- {
- return new Vector4D(v1.r + v2.x, v1.g + v2.y, v1.b + v2.z, v1.a + v2.w);
- }
-
- public static Vector4D operator -(Vector4D v1, Vector4 v2)
- {
- return new Vector4D(v1.r - v2.x, v1.g - v2.y, v1.b - v2.z, v1.a - v2.w);
- }
-
- public static Vector4D operator +(Vector4 v1, Vector4D v2)
- {
- return new Vector4D(v1.x + v2.r, v1.y + v2.g, v1.z + v2.b, v1.w + v2.a);
- }
-
- public static Vector4D operator -(Vector4 v1, Vector4D v2)
- {
- return new Vector4D(v1.x - v2.r, v1.y - v2.g, v1.z - v2.b, v1.w - v2.a);
- }
- }
哈哈,这绝对是最后一次修改!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。