简体   繁体   English

序列化从不可序列化的类派生的类

[英]Serialize a class that is derived from a non serializable class

I have a problem with serialization, in Unity (using C#). 我在Unity中使用C#进行序列化有问题。

I have the following classes (the arrows indicate inheritance): 我有以下课程(箭头表示继承):

Vehicle (abstract) <- Car (abstract) <- Sedan Vehicle (摘要)<- Car (摘要)<- Sedan

and

Vehicle (abstract) <- MotorBike Vehicle (摘要)<- MotorBike

The vehicle class inherits from MonoBehavior . 车辆类继承自MonoBehavior

I have some gameobjects (prefabs), that I attached the classed to. 我有一些游戏对象(预制件),我将其分类。 I only use the non abstract classes (ie MotorBike and Sedan ). 我只使用非抽象类(即MotorBikeSedan )。

My problem is this: 我的问题是这样的:

I want to serialize the data stored within these classes, to be able to save/load. 我想序列化存储在这些类中的数据,以便能够保存/加载。 (I use BinaryFormatter for this.) The problem is, MonoBehavior isn't serializable. (我为此使用BinaryFormatter 。)问题是, MonoBehavior无法序列化。

All I want is to serialize the data within the vehicle classes, and (upon loading the data) pass that to my Vehicle Factory class, to re-instantiate the prefabs, with the deserialized data. 我想要的只是序列化车辆类中的数据,(在加载数据时)将其传递给我的“车辆工厂”类,以使用反序列化的数据重新实例化预制件。 So, I'm not really interested in whatever is stored in the MonoBehavior part. 因此,我对MonoBehavior部分中存储的内容并不真正感兴趣。

What I've tried so far: 到目前为止,我已经尝试过:

Using a separate Data class, but this causes all kinds of problems and I would need to create a child data class for each of my Vehicle classes. 使用单独的Data类,但这会引起各种问题 ,我需要为每个Vehicle类创建一个子数据类。 And I would need to make the Vehicle class Generic, to indicate which Data class it needs to use, which would require me to use the Generic Type in every place I use the Vehicle type. 而且我需要将Vehicle类设为通用,以指示需要使用哪个数据类,这将要求我在使用Vehicle类型的每个位置都使用Generic Type。

Also, I tried to make a SerializationSurrogate for MonoBehaviour, but this didn't work out, because there are numerous other Types that would need a surrogate. 另外,我尝试为MonoBehaviour创建一个SerializationSurrogate,但这没有奏效,因为还有许多其他类型需要替代。 And since I'm not interested in the MonoBehaviour, but only in the Vehicle Class and it's child classes, this seemed to be too complex to try. 而且由于我对MonoBehaviour并不感兴趣,而仅对Vehicle类及其子类感兴趣,因此似乎很难尝试。

So, my question is: Does anybody know a way to handle this? 所以,我的问题是:有人知道解决这个问题的方法吗?

I always find saving data from inherited classes hard. 我总是很难从继承的类中保存数据。 Your data classes should not inherit or derive from anything. 您的数据类不应继承任何东西。 A class inside another class is totally fine. 另一个类中的一个类完全可以。 The goal here is to have two classes for every vehicle. 这里的目标是每辆车都有两个类别。 One that derives from MonoBehaviour (Object) and one that doesn't(data). 一种是从MonoBehaviour (对象)派生而另一种不是(数据)派生。

You use the Object class to perform action on the vehicles such as moving, collision decision and more. 您可以使用Object类对车辆执行动作,例如移动,碰撞决策等。 You use the data class to store information about each car/vehicle. 您可以使用数据类来存储有关每辆汽车/车辆的信息。

The example below uses Sedan to demonstrate what I am saying: 下面的示例使用Sedan演示我的意思:

Attach the SedanObject.cs to the Sedan Prefab. SedanObject.cs附加到Sedan Prefab。

class SedanObject : MonoBehaviour
{
    float fuel;
    public void setFuel(float fuel)
    {
        this.fuel = fuel;
    }

    public float getFuel(float fuel)
    {
        return this.fuel;
    }

    void Start()
    {

    }

    void Update()
    {

    }
}

The Data class for Sedan: 轿车的数据类:

[Serializable]
public class MotorBike
{

}

[Serializable]
public class Sedan
{
    public float fuel;
}

[Serializable]
public class Cars
{
    public List<Sedan> sedan;

    public Cars()
    {
        sedan = new List<Sedan>();
    }
}

[Serializable]
public class Vehicles
{
    public Cars cars;
    public MotorBike motorBike;

    public Vehicles()
    {
        cars = new Cars();
        motorBike = new MotorBike();
    }
}

At the end of the game, save the Vehicles settings. 游戏结束时,保存车辆设置。 Every class/script inside Vehicles will be saved. 车辆中的每个班级/脚本都将被保存。

//Save on Exit
Vehicles vehicles = new Vehicles();
string vehicleJson = JsonUtility.ToJson(vehicles);
PlayerPrefs.SetString("vehicles", vehicleJson);
PlayerPrefs.Save();

When Game starts, load the Vehicles info from disk then instantiate Sedan Prefab based on how many sedans in the list. 游戏开始时,从磁盘加载Vehicles信息,然后根据列表中的轿车数量实例化Sedan Prefab。

//Load on Startup
string loadVehicleJson = PlayerPrefs.GetString("vehicles");
Vehicles loadVehicles;
loadVehicles = JsonUtility.FromJson<Vehicles>(loadVehicleJson);

//Process and instantiate sedan based on the loaded data amount/count
for (int i = 0; i < vehicles.cars.sedan.Count; i++)
{
    GameObject tempObjt = Instantiate(sedanPrefab);
    SedanObject sd = tempObjt.GetComponent<SedanObject>();

    //Send loaded settings to each vehicle script 
    sd.setFuel(vehicles.cars.sedan[i].fuel);
}

And if you want to add more Sedans later on: 如果以后要添加更多轿车,请执行以下操作:

//Create 3 Sedans
vehicles.cars.sedan.Add(new Sedan());
vehicles.cars.sedan.Add(new Sedan());
vehicles.cars.sedan.Add(new Sedan());

This is just a basic solution and can be extended. 这只是一个基本解决方案,可以扩展。 You can pass instance of each sedan data script to SedanObject during the for loop, just like I passed in loaded fuel to each instance. 您可以在for循环期间将每个轿车数据脚本的实例传递给SedanObject ,就像我将加载的燃料传递给每个实例一样。 By passing each instance, information from the data script can be modified from each instance of SedanObject script during run-time. 通过传递每个实例,可以在运行时从SedanObject脚本的每个实例修改数据脚本中的信息。 This can be done with xml too. 这也可以用xml完成。

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

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