序列化一个派生自非可序列化类

时间:2016-06-02 15:26:42

标签: c# oop serialization unity3d

我在Unity中使用序列化有问题(使用C#)。

我有以下类(箭头表示继承):

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

Vehicle(摘要)< - MotorBike

车辆类继承自MonoBehavior

我有一些游戏对象(预制件),我将其归类于。我只使用非抽象类(即MotorBikeSedan)。

我的问题是:

我想序列化这些类中存储的数据,以便能够保存/加载。 (我为此使用BinaryFormatter。)问题是,MonoBehavior不可序列化。

我想要的是序列化车辆类中的数据,并且(在加载数据时)将其传递给我的Vehicle Factory类,以使用反序列化的数据重新实例化预制件。所以,我对MonoBehavior部分中存储的内容并不感兴趣。

到目前为止我尝试过的事情:

使用单独的Data类,但这会导致各种problems,我需要为每个Vehicle类创建一个子数据类。我需要使Vehicle类Generic,以指示它需要使用哪个Data类,这将要求我在每个使用Vehicle类型的地方使用Generic Type。

此外,我尝试为MonoBehaviour制作一个SerializationSurrogate,但这并没有成功,因为还有许多其他类型需要代理。由于我对MonoBehaviour并不感兴趣,只是在车辆类和它的儿童课程中,这似乎太复杂了,无法尝试。

所以,我的问题是:有人知道处理这个问题的方法吗?

1 个答案:

答案 0 :(得分:3)

我总是很难找到继承类中的保存数据。您的数据类不应继承或派生自任何东西。另一个班级里面的班级完全没问题。这里的目标是为每辆车提供两个班级。一个派生自MonoBehaviour(对象),另一个派生不(数据)。

您可以使用对象类对车辆执行操作,例如移动,碰撞决策等。您可以使用数据类来存储有关每辆车/车辆的信息。

以下示例使用Sedan来演示我的意思:

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()
    {

    }
}

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

在游戏结束时,保存车辆设置。车辆内的每个课程/脚本都将被保存。

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

当游戏开始时,从磁盘加载车辆信息,然后根据列表中的轿车数量实例化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);
}

如果你想稍后添加更多的Sedans:

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

这只是一个基本的解决方案,可以扩展。您可以在for循环期间将每个轿车数据脚本的实例传递给SedanObject,就像我将加载的燃料传递给每个实例一样。通过传递每个实例,可以在运行时从SedanObject脚本的每个实例修改数据脚本中的信息。这也可以通过xml来完成。