[英]Is there any way to serialize referenced MonoBehaviours to JSON?
Let's say I have an object called ObjectA
which contains two objects: ObjectsB
and ObjectC
. 比方说,我有一个名为对象
ObjectA
包含两个对象: ObjectsB
和ObjectC
。
[System.Serializable]
public ClassA
{
public ClassB classB;
public ClassC classC;
public ClassA()
{
classB = new ClassB();
classC = new ClassC();
}
}
[System.Serializable]
public ClassB
{
//Some fields.
}
[System.Serializable]
public ClassC
{
//Some fields.
}
If I serialize ObjectA
to JSON, ObjectB
and ObjectC
don't get serialized. 如果我将
ObjectA
序列化为JSON,则ObjectB
和ObjectC
不会序列化。 This is what I've got after serializing ObjectA
to JSON: 这是将
ObjectA
序列化为JSON之后的结果:
{"_instanceB":{"instanceID":10480},"_instanceC":{"instanceID":10230}}
I need to serialize all these objects to a file and save it locally on hard drive to be able to restore their states later. 我需要将所有这些对象序列化为文件,并将其本地保存在硬盘驱动器上,以便以后恢复它们的状态。 How can I do it?
我该怎么做?
Am I supposed to retrieve ClassB
and ClassC
from ClassA
then serialize and save them individually? 我是否应该从
ClassA
检索ClassB
和ClassC
,然后分别进行序列化和保存? Something like this: 像这样:
public void Save()
{
//Get instances of ClassB and ClassC.
ClassB classB = classA.GetClassB;
ClassC classC = classA.GetClassC;
//Generate different JSON for each class.
string classA_JSON = JsonUtility.ToJson(classA);
string classB_JSON = JsonUtility.ToJson(classB);
string classC_JSON = JsonUtility.ToJson(classC);
//Paths for saving locally.
string pathForClassA = Path.Combine("C:\\", "classA.json");
string pathForClassB = Path.Combine("C:\\", "classB.json");
string pathForClassC = Path.Combine("C:\\", "classC.json");
File.WriteAllText(pathForClassA, classA_JSON);
File.WriteAllText(pathForClassB, classB_JSON);
File.WriteAllText(pathForClassC, classC_JSON);
}
Looks ugly and it will generate a new JSON file for each nested class. 看起来很丑,它将为每个嵌套类生成一个新的JSON文件。 Can I somehow serialize
ClassA
including its nested classes into one JSON file? 我可以以某种方式将包括嵌套类的
ClassA
序列化为一个JSON文件吗?
PS This is a Unity project and ClassA
, ClassB
, and ClassC
derive from MonoBehaviour
. PS这是一个Unity项目,
ClassA
, ClassB
和ClassC
源自MonoBehaviour
。 Since BinaryFormatter
doesn't support MonoBehaviour
I can't use it. 由于
BinaryFormatter
不支持MonoBehaviour
,因此无法使用它。 The only thing that left for me is to serialize it to JSON. 剩下的唯一一件事就是将其序列化为JSON。
Can I somehow serialize ClassA including its nested classes into one JSON file?
我可以以某种方式将包括嵌套类的ClassA序列化为一个JSON文件吗?
Yes you could but it would require some work: 是的,您可以,但是需要一些工作:
You could have [Serializable]
representation classes for ClassB
and ClassC
and use the ISerializationCallbackReceiver
interface for filling and using them in ClassA
您可以为
ClassB
和ClassC
使用[Serializable]
表示形式类,并使用ISerializationCallbackReceiver
接口在ClassA
进行填充和使用
Something like eg 像例如
public class ClassB : MonoBehaviour
{
[SerializeField] private float example1;
[SerializeField] private string example2;
// etc.
public void SetUp(SerializableClassB values)
{
// set all values
this.example1 = values.example1;
this.example2 = values.example2;
// etc.
}
public SerializableClassB GetSerializable()
{
var output = new SerializableClassB();
output.example1 = this.example1;
output.example2 = this.example2;
// etc.
return output;
}
}
[Serializable]
public class SerializableClassB
{
public float example1;
public string example2;
// etc
}
And the same for ClassC
与
ClassC
相同
public class ClassC : MonoBehaviour
{
[SerializeField] private float example3;
[SerializeField] private string example4;
// etc.
public void SetUp(SerializableClassC values)
{
// set all values
example3 = values.example3;
example4 = values.example4;
// etc.
}
public SerializableClassC GetSerializable()
{
var output = new SerializableClassC();
output.example3 = example3;
output.example4 = example4;
// etc.
return output;
}
}
[Serializable]
public class SerializableClassC
{
public float example3;
public string example4;
// etc
}
Then in ClassA
you can do 然后在
ClassA
您可以
public class ClassA : MonoBehaviour, ISerializationCallbackReceiver
{
public ClassB _classB;
public ClassC _classC;
[SerializeField] private SerializableClassB _serializableClassB;
[SerializeField] private SerializableClassC _serializeableClassC;
public void OnBeforeSerialize()
{
// before writing to a Json get the information from the MonoBehaviours into the normal classes
if(_classB) _serializableClassB = _classB.GetSerializable();
if(_classC) _serializeableClassC = _classC.GetSerializable();
}
public void OnAfterDeserialize()
{
// after deserializing write the infromation from the normal classes into the MonoBehaviours
if(_classB) _classB.SetUp(_serializableClassB);
if(_classC) _classC.SetUp(_serializeableClassC);
}
}
The second huge advantage (side-effect) is that now you additionally can also controll the values of _classB
and _classC
directly on the ClassA
instance. 第二个巨大的优势(副作用)是,现在您还可以直接在
ClassA
实例上控制_classB
和_classC
的值。 This way you can modify MonoBehaviour values in a centralized manager class. 这样,您可以在集中管理器类中修改MonoBehaviour值。
After serializing to json using 使用序列化为json后
private void Start()
{
File.WriteAllText(Path.Combine(Application.streamingAssetsPath, "Test.txt"), JsonUtility.ToJson(this));
AssetDatabase.Refresh();
}
you now get 你现在得到
{
"_classB":{"instanceID":-6766},"_classC":{"instanceID":-6826},
"_serializableClassB": {
"example1":23.0,
"example2":"54ththfghg"
},
"_serializeableClassC": {
"example3":67.0,
"example4":"567gffhgfhgf"
}
}
Than for the example I changed it to 比起示例,我将其更改为
{
"_classB":{"instanceID":-6766},"_classC":{"instanceID":-6826},
"_serializableClassB": {
"example1":47,
"example2":"Hello"
},
"_serializeableClassC": {
"example3":32.123,
"example4":"World!"
}
}
and deserialized on start from json using 并从json开始使用
private void Start()
{
JsonUtility.FromJsonOverwrite(File.ReadAllText(Path.Combine(Application.streamingAssetsPath, "Test.txt")), this);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.