假设我有一个这样的课程:
[System.Serializable]
public class Item {
private Transform _transform;
private float _value;
}
我想使用BinaryFormatter序列化这个类。我无法序列化转换组件,因此我需要在序列化时忽略它,但我仍然需要在检查器中看到此 _transform 字段。在此示例中,只应序列化字段 _value 。
如果我在 _transform 字段中使用 [System.NonSerialized] ,它将无法在Unity检查器中看到,如果我使用 [SerializeField] 我无法使用BinaryFormatter序列化Transform。
看起来有点像悖论......是否可以这样做?
答案 0 :(得分:1)
我无法序列化Transform组件,所以我需要忽略它 序列化,但我仍然需要这个_transform字段可见 检查员。
你不能这样做,但有一个解决方法。与scott提到的一样,请使用JsonUtilty
。这不会完全解决您的问题,但会阻止您在尝试反序列化由于_transform
变量引起的json数据时出错。
您只需要Transform
类的位置,轮播和比例,所有这些都可以序列化,因为它们可能是Vector3
或Quaternion
,但Transform
无法序列化。因此,您必须声明位置,旋转和缩放,并从_transform
变量中获取它们的值。然后,您可以序列化这3个值。
[System.Serializable]
public class Item
{
//Will be ignored by JsonUtility but will be visible in the Editor
[SerializeField]
private Transform _transform;
[SerializeField]
private float _value;
[SerializeField]
private Vector3 position;
[SerializeField]
private Quaternion rotation;
[SerializeField]
private Vector3 scale;
//Call before serializing
public void updateValues()
{
position = _transform.position;
rotation = _transform.rotation;
scale = _transform.localScale;
}
}
在将对象序列化为json之前调用updateValues()
函数。
void Start()
{
Item item = new Item();
...
...
item.updateValues();
string json = JsonUtility.ToJson(item);
Debug.Log(json);
}
通过使用json,您在序列化数据时不会遇到任何问题。如果您打算保存这个,那么请查看我处理所有这些的简单wrapper。
答案 1 :(得分:1)
我不建议您使用场景对象或域对象进行序列化。您将始终在两种不同的序列化要求之间展开斗争。
我建议在场景模型和持久性/序列化模型之间分离模型。
public class SerializableItemModel
{
public Vector3 position;
public Quaternion rotation;
public float _value;
}
然后有一个映射器,而不是可以在对象之间映射。
public class ItemToModelMapper
{
public SerializableItemModel MapToModel(Item item)
{
var model = new SerializableItemModel
{
position = item.transform.position;
rotation = item.transform.rotation;
_value = item._value;
};
return model
}
public Item MapFromModel(SerializableItemModel model)
{
return new Item(model.position, model.rotation, model._value);
}
}
如果你像这样分开你的对象,你将永远不必担心横切问题,例如序列化对象的持久性,以及以某种方式在检查器中显示它等。如果你只想序列化你的场景对象的10%那么你将它映射到一个小模型并将其序列化。
当然,这比您希望编写的代码要多得多。如果您愿意,可以将Item提供给SerializableItemModel构造函数并跳过映射层。
public class SerializableItemModel
{
public Vector3 position;
public Quaternion rotation;
public float _value;
public SerializableItemModel(Item item)
{
this.position = item.transform.position;
this.rotation = item.transform.rotation;
this._value = item.transform._value;
}
}
现在,您的代码在序列化时将如下所示:
private ItemToModelMapper mapper;
void Start()
{
Item item = new Item();
...
...
// Serialize
var serializationModel = this.mapper.MapToModel(item);
string json = JsonUtility.ToJson(serializationModel );
// Deserialize
SerializableItemModel deserializedModel = JsonUtility.FromJson<SerializableItemModel>(json);
Item loadedItem = this.mapper.MapFromModel(deserializedModel);
}
编辑:正如程序员所指出的那样,我从未处理过Item的检查器视图。因为Item类现在只有一个责任,所以欢迎将[SerializeField]放在任何字段上,因为该对象不会用于任何其他序列化。你现在也可以使用你想要的任何序列化器(JsonUtility,BinaryFormatter,JsonConvert,XmlSerializer等)。