简体   繁体   English

不序列化字段,但在检查器中显示

[英]Do not serialize field but show in the inspector

Let's say I have a class like this: 假设我有一个这样的课程:

[System.Serializable]
public class Item {
private Transform _transform;
private float _value;
}

I want to serialize this class using BinaryFormatter. 我想使用BinaryFormatter序列化此类。 I can't serialize Transform component so I need to ignore it while serializing but I still need this _transform field to be visible in the inspector. 我无法序列化Transform组件,因此在序列化时需要忽略它,但是我仍然需要此_transform字段在检查器中可见。 In this example only field _value should be serialized. 在此示例中,仅应将字段_value序列化。

If I use [System.NonSerialized] on _transform field it won't be visible in the Unity inspector and if I use [SerializeField] I can't serialize Transform with BinaryFormatter. 如果在_transform字段上使用[System.NonSerialized] ,则在Unity检查器中将不可见;如果使用[SerializeField] ,则无法使用BinaryFormatter序列化Transform。

Seems a bit like a paradox... Is it possible to do so? 似乎有点自相矛盾...有可能这样做吗?

I can't serialize Transform component so I need to ignore it while serializing but I still need this _transform field to be visible in the inspector. 我无法序列化Transform组件,因此在序列化时需要忽略它,但是我仍然需要此_transform字段在检查器中可见。

You can't do this but there is a workaround. 您无法执行此操作,但是有一种解决方法。 Like scott mentioned, use JsonUtilty . 就像提到的scott一样,使用JsonUtilty That will not completely solve your problem but will prevent giving you error when you try to de-serialize the json data due to the _transform variable. 那不会完全解决您的问题,但是当您尝试因_transform变量而尝试反序列化json数据时,将防止出现错误。

You only need position, rotation and scale from the Transform class and all these can be serialized since they are either Vector3 or Quaternion but Transform cannot be serialized. 您只需要Transform类中的位置,旋转和比例,并且所有这些都可以序列化,因为它们是Vector3Quaternion但是Transform无法序列化。 So you have to declare position, rotation and scale and get their values from the _transform variable. 因此,您必须声明位置,旋转和比例,并从_transform变量获取它们的值。 You can then serialize those 3 values. 然后,您可以序列化这三个值。

[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;
    }
}

Call the updateValues() function before serializing the object to json. 在将对象序列化为json之前,请调用updateValues()函数。

void Start()
{
    Item item = new Item();
    ...
    ...
    item.updateValues();
    string json = JsonUtility.ToJson(item);
    Debug.Log(json);
}

By using json you will not have any problems while serializing the data. 通过使用json,在序列化数据时不会有任何问题。 If you plan on saving this then look into a simple wrapper I made to handle all these. 如果您打算保存此内容,请查看我为处理所有这些内容而设计的简单包装

I would not recommend using your scene objects or domain objects for serialization as well. 我不建议同时使用场景对象或域对象进行序列化。 You will always be battling between the two different serialization requirements. 您将始终在两种不同的序列化需求之间进行斗争。

I would recommend separating your models between scene model and persistence/serialization model. 我建议将场景模型和持久性/序列化模型分开。

public class SerializableItemModel
{
    public Vector3 position;
    public Quaternion rotation;
    public float _value;
}

Then have a mapper than can map between your objects. 然后使用一个可以在对象之间进行映射的映射器。

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);
    }
}

If you separate your objects like this you will never have to worry about cross cutting concerns like serializing your object for persistence and also somehow display it in the inspector etc. If you want to serialize only 10% of your scene object then you map it into a small model and serialize that instead. 如果像这样分离对象,则无需担心诸如交叉序列化对象以保持持久性以及在检查器中以某种方式显示等交叉问题。如果只想序列化场景对象的10%,则可以将其映射到一个小模型,然后序列化它。

Of course this is a lot more code than you probably were hoping to write. 当然,这比您可能希望编写的代码多得多。 If you wanted to you could just provide the Item to the SerializableItemModel constructor and skip the mapping layer. 如果需要,可以将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;
    }
}

Now your code will look like this when serializing: 现在,您的代码在序列化时将如下所示:

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);
}

EDIT: As pointed out by Programmer I never addressed the inspector view for Item. 编辑:正如程序员指出的那样,我从未谈到Item的检查人员视图。 Because the Item class now only has one responsibility you are welcome to put [SerializeField] on any field because this object will not be used for any other serialization. 由于Item类现在只承担一项责任,因此欢迎您将[SerializeField]放在任何字段上,因为此对象将不会用于任何其他序列化。 You can now also use any serializer you want (JsonUtility, BinaryFormatter, JsonConvert, XmlSerializer, etc). 现在,您还可以使用所需的任何序列化程序(JsonUtility,BinaryFormatter,JsonConvert,XmlSerializer等)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM