(Unity3D)保存/加载播放器库存

时间:2018-01-07 00:52:21

标签: c# unity3d save load

每当通过播放器脚本保存或加载时,两侧的库存总是空白,我无法确定问题所在。库存使用Unity中间库存教程中使用的相同系统,该工作正常,但加载时库存始终为空白。

播放器

public void Save(){
    Debug.Log ("Saving data (player / inventory)");

    SaveLoadManager.SavePlayer (this); //works fine
    SaveLoadInventory.SaveInventory (inv); //where the issue is
}
public void Load(){
    Debug.Log ("Loading data (player / inventory)");

    float[] loadedStats = SaveLoadManager.LoadPlayer (); //works fine
    Item[] loadedItems = SaveLoadInventory.LoadInventory (); //comes up empty

    inv.items = loadedItems; //try to set the referenced Inventory script array of items equal to the loaded items

    //loadedStats[...] are set to player values and all works good
}

广告

public class Inventory : MonoBehaviour {

public Image[] itemImages = new Image[numItemSlots];
public Text[] itemAmountsText = new Text[numItemSlots];
public int[] itemAmounts = new int[numItemSlots];
public Item[] items = new Item[numItemSlots];

public const int numItemSlots = 40;

public void AddItem(Item itemToAdd){
    for (int i = 0; i < items.Length; i++) {
        if(items [i] == itemToAdd){
            if (itemAmounts [i] <= 99) {
                itemAmounts [i]++;
            } else {
                items [i] = itemToAdd;
                itemImages [i].sprite = itemToAdd.itemImage;
                itemImages [i].enabled = true;
            }
            itemAmountsText [i].text = itemAmounts [i] + "";
            return;
        } else if (items [i] == null) {
            itemAmounts [i]++;
            itemAmountsText [i].text = itemAmounts [i] + "";
            items [i] = itemToAdd;
            itemImages [i].sprite = itemToAdd.itemImage;
            itemImages [i].enabled = true;
            return;
        }
    }
}

public void RemoveItem(Item itemToRemove){
    for (int i = 0; i < items.Length; i++) {
        if (items [i] == itemToRemove) {
            items [i] = null;
            itemImages [i].sprite = null;
            itemImages [i].enabled = false;
            return;
        }
    }
}

public void ClearAllItems(){
    for (int i = 0; i < items.Length; i++) {
        items [i] = null;
        itemImages [i].sprite = null;
        itemImages [i].enabled = false;
        return;
    }
}

[Serializable]
public class InventoryData {
    public Image[] itemImages = new Image[numItemSlots];
    public Text[] itemAmountsText = new Text[numItemSlots];
    public int[] itemAmounts = new int[numItemSlots];
    public Item[] items;

    public InventoryData(Inventory inv){
        items = new Item[numItemSlots];

        for (int i = 0; i < items.Length; i++) {
            inv.items[i] = items[i];
            inv.itemAmounts[i] = itemAmounts[i];
            inv.itemAmountsText[i] = itemAmountsText[i];
            inv.itemImages[i] = itemImages[i];
            }
        }
    }
}

SaveLoadInventory

public static class SaveLoadInventory {

    public static void SaveInventory(Inventory inv){

    BinaryFormatter bf = new BinaryFormatter();
    var createdir = Directory.CreateDirectory(Application.persistentDataPath + "/saves");
    String dir = Application.persistentDataPath + "/saves";
    Inventory.InventoryData data = new Inventory.InventoryData (inv);

    DirectoryInfo dir_i = new DirectoryInfo(dir);
    FileInfo[] info = dir_i.GetFiles("*.inv");
    foreach (FileInfo f in info) {
        Debug.Log (f);
    }

    FileStream stream = new FileStream (dir + "/player" + (info.Length + 1) + ".inv", FileMode.Create);

    bf.Serialize (stream, data);
    stream.Close ();

}

    public static Item[] LoadInventory(){
    String dir = Application.persistentDataPath + "/saves";

    DirectoryInfo dir_i = new DirectoryInfo(dir);
    FileInfo[] info = dir_i.GetFiles("*.inv");
    foreach (FileInfo f in info) {
        Debug.Log (f);
    }

    if (info.Length >= 1) {

        BinaryFormatter bf = new BinaryFormatter ();
        var createdir = Directory.CreateDirectory(Application.persistentDataPath + "/saves");
        FileStream stream = new FileStream (dir + "/player" + (info.Length) + ".inv", FileMode.Open);
        Inventory.InventoryData data = bf.Deserialize (stream) as Inventory.InventoryData;

        stream.Close ();
        return data.items;
    } else {
        return null;
    }
}

老实说,我会尝试一些调试组合并自己解决这个问题,但这一切看起来都太复杂了,无法解决这个问题,并且担心它不会起作用。如果您有任何帮助或建议,将不胜感激。

1 个答案:

答案 0 :(得分:2)

  

但加载时库存始终为空白。

第一个问题是要在InventoryData类中序列化的变量类型。您无法直接对ImageText组件进行序列化,因为它们是UnityEngine.Object类型。对于Image组件,请保存Image组件正在使用的Sprite的路径。对于Text组件,保存包含文本本身的.text属性的值。

如果要序列化ImageText组件的多个属性,最好创建一个新的可序列化的类/包装器,它将保存您要序列化的重要数据Image组件和Text组件的另一个组件。

例如,假设您要序列化有关Text组件的信息,例如字体大小,实际文本和颜色,这是一个示例简单的包装器:

[Serializable]
public class TextWrapper
{
    public int fontSize;
    public string text;
    public Color color;

    public TextWrapper(Text text)
    {

        //Get Text Info
        fontSize = text.fontSize;
        this.text = text.text;
        color = text.color;
    }
}

要序列化的Text组件:

public Text myText;

您可以从TextWrapper组件创建Text的新实例以进行序列化:

TextWrapper textWrapper = new TextWrapper(myText);

现在,您可以使用问题中的BinaryFormatter对其进行序列化。您可以将TextWrapper类放在InventoryData类中,也应该序列化。

请注意,TextWrapper必须放在自己的 .cs 文件中,否则BinaryFormatter可以提交序列化/反序列化文件。如果你仍然有问题..使用Json。有关详细信息,请参阅this帖子。