如何使用加载功能?

时间:2019-12-13 15:41:09

标签: c# unity3d

为了保存,我在状态类中创建了结构:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

[Serializable]
public class SaveState
{
    public struct Position
    {
        public float x;
        public float y;
        public float z;

        public void Fill(Vector3 v3)
        {
            x = v3.x;
            y = v3.y;
            z = v3.z;
        }

        public Vector3 V3 { get { return new Vector3(x, y, z); } set { Fill(value); } }
    }

    public struct Rotation
    {
        public float x;
        public float y;
        public float z;
        public float w;

        public void Fill(Quaternion Quat)
        {
            x = Quat.x;
            y = Quat.y;
            z = Quat.z;
            w = Quat.w;
        }

        public Quaternion Qua { get { return new Quaternion(x, y, z, w); } set { Fill(value); } }
    }

    public struct Scale
    {
        public float x;
        public float y;
        public float z;
        public float w;

        public void Fill(Vector3 v3)
        {
            x = v3.x;
            y = v3.y;
            z = v3.z;
        }

        public Vector3 V3 { get { return new Vector3(x, y, z); } set { Fill(value); } }
    }

    public SaveState(Vector3 pos, Quaternion rot, Vector3 sca)
    {
        Position position = new Position();
        position.V3 = pos;

        Rotation qua = new Rotation();
        qua.Qua = rot;

        Scale scale = new Scale();
        scale.V3 = sca;
    }
}

然后在管理器脚本中:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.Serialization.Formatters.Binary;
using System;
using System.IO;

public class SaveManager : MonoBehaviour
{
    public static void Save(SaveState player)
    {
        BinaryFormatter formatter = new BinaryFormatter();
        string path = Application.persistentDataPath + "/player.bin";
        FileStream stream = new FileStream(path, FileMode.Create);

        formatter.Serialize(stream, player);
        stream.Close();
    }

    public static SaveState Load()
    {
        string path = Application.persistentDataPath + "/player.bin";
        if (File.Exists(path))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            FileStream stream = new FileStream(path, FileMode.Open);

            SaveState data = formatter.Deserialize(stream) as SaveState;
            stream.Close();

            return data;
        }
        else
        {
            Debug.LogError("Save file not found in " + path);
            return null;
        }
    }
}

和测试脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SaveTest : MonoBehaviour
{
    private void Update()
    {
        if(Input.GetKeyDown(KeyCode.T))
        {
            var player = GameObject.Find("Player");
            SaveState saveState = new SaveState(player.transform.position, player.transform.rotation,player.transform.localScale);

            SaveManager.Save(saveState);
        }

        if(Input.GetKeyDown(KeyCode.L))
        {
            var player = GameObject.Find("Player");


        }
    }
}

保存部分似乎还可以,但是我不确定加载部分。 我不确定Load函数的编写是否正确,也不确定如何在L键输入中使用它。

编辑:

更新后我的类和脚本:

保存状态:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

[Serializable]
public class SaveState
{
    public struct SerializableVector3
    {
        public float X;
        public float Y;
        public float Z;

        public SerializableVector3(Vector3 v)
        {
            X = v.x;
            Y = v.y;
            Z = v.z;
        }

        // And now some magic
        public static implicit operator SerializableVector3(Vector3 v)
        {
            return new SerializableVector3(v);
        }

        public static implicit operator Vector3(SerializableVector3 sv)
        {
            return new Vector3(sv.X, sv.Y, sv.Z);
        }
    }

    public struct SerializableQuaternion
    {
        public float X;
        public float Y;
        public float Z;
        public float W;

        public SerializableQuaternion(Quaternion q)
        {
            X = q.x;
            Y = q.y;
            Z = q.z;
            W = q.w;
        }

        public static implicit operator SerializableQuaternion(Quaternion q)
        {
            return new SerializableQuaternion(q);
        }

        public static implicit operator Quaternion(SerializableQuaternion sq)
        {
            return new Quaternion(sq.X, sq.Y, sq.Z, sq.W);
        }
    }

    public SerializableVector3 position;
    public SerializableQuaternion rotation;
    public SerializableVector3 scale;

    public SaveState(Vector3 pos, Quaternion rot, Vector3 sca)
    {
        position = pos;
        rotation = rot;
        scale = sca;
    }

    public void ApplyToPlayer(Transform player)
    {
        player.position = position;
        player.rotation = rotation;
        player.localScale = scale;
    }
}

经理:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.Serialization.Formatters.Binary;
using System;
using System.IO;

public class SaveManager : MonoBehaviour
{
    public static void Save(SaveState player)
    {
        BinaryFormatter formatter = new BinaryFormatter();
        string path = Application.persistentDataPath + "/player.bin";
        FileStream stream = new FileStream(path, FileMode.Create);

        formatter.Serialize(stream, player);
        stream.Close();
    }

    public static SaveState Load()
    {
        string path = Application.persistentDataPath + "/player.bin";
        if (File.Exists(path))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            FileStream stream = new FileStream(path, FileMode.Open);

            SaveState data = formatter.Deserialize(stream) as SaveState;
            stream.Close();

            return data;
        }
        else
        {
            Debug.LogError("Save file not found in " + path);
            return null;
        }
    }
}

测试脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SaveTest : MonoBehaviour
{
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.T))
        {
            var player = GameObject.Find("Player");
            SaveState saveState = new SaveState(player.transform.position, player.transform.rotation, player.transform.localScale);
            SaveManager.Save(saveState);
        }

        if (Input.GetKeyDown(KeyCode.L))
        {
            var player = GameObject.Find("Player");

            var playerInfo = SaveManager.Load();
            playerInfo.ApplyToPlayer(player.transform);
        }
    }
}

2 个答案:

答案 0 :(得分:1)

Load()似乎还可以。

通过这种方式,您还可以使用FileStream stream = File.Open(path, FileMode.Open);

使用它没什么特别的,只是:SaveState save = SaveManager.Load();

答案 1 :(得分:1)

您当前在班级中没有任何字段!

仅类型定义。您将需要一些类似的东西

public Position position;
public Rotation rotation;
public Scale scale;

您使用的只是局部方法变量,不会存储在任何地方!

然后在构造函数中分配这些

public SaveState(Vector3 pos, Quaternion rot, Vector3 sca)
{
    // Since structs are never null
    // you don't need to create new ones
    position.V3 = pos;
    rotation.Qua = rot;
    scale.V3 = sca;
}

然后我通常会在您的类中寻找一种方法,例如

public void ApplyToPlayer(Transform player)
{
    player.position = position.V3;
    player.rotation = rotation.Qua;
    player.localScale = scale.V3;
}

,然后在您的L块中

var player = GameObject.Find("Player").transform;
var playerInfo = SaveManager.Load();

playerInfo.ApplyToPlayer(player);

最后一步:

对于您的结构,我什至建议编写implicit operator转换作为一个示例:

[Serializable]
public struct SerializableVector3
{
    public float X;
    public float Y;
    public float Z;

    public SerializableVector3(Vector3 v)
    {
        X = v.x;
        Y = v.y;
        Z = v.z;
    }

    // And now some magic
    public static implicit operator SerializableVector3 (Vector3 v)
    {
        return new SerializableVector3 (v);
    }

    public static implicit operator Vector3 (SerializableVector3 sv)
    {
        return new Vector3 (sv.X, sv.Y, sv.Z);
    }
}

这使您现在可以像希望使用的那样简单地互换使用这两种类型

public SerializableVector3 position;
// This type is your homework
public SerializableQuaternion rotation;
public SerializableVector3 scale;

然后您可以直接将其分配为

player.position = someSaveStat.position;

还有

someSaveStat.position = player.position;

因此您可以将构造函数更改为例如

public SaveState(Vector3 pos, Quaternion rot, Vector3 sca)
{
    position = pos;
    rotation = rot;
    scale = sca;
}

,应用方法将变为

public void ApplyToPlayer (Transform player)
{
    player.position = position;
    player.rotation = rotation;
    player.localScale = scale;
}

注意:我在智能手机上键入内容,但我希望这个主意能弄清楚。