簡體   English   中英

C#:如何在Unity中使用數組而不是列表重寫用於管理游戲數據序列化的代碼?

[英]C#: How can I rewrite my code for managing Game Data Serialization using an Array instead of a List in Unity?

我是編碼的新手,目前正在創建腳本以將數據序列化到硬盤。 我設法使其與類型為“游戲”的列表一起使用。 Game類保存可以序列化的數據。 我一直在嘗試編寫此代碼以使用大小為3的數組來代替。不幸的是,在運行程序並嘗試使用GUI時遇到了麻煩。 我只需要在正確的方向上推動如何重寫我的代碼。 我知道從開始:

public static Game[] savedGames = new Game[3];

但是,如何使用數組而不是列表來使用定義。

//<SaveLoad.cs>

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

public static class SaveLoad {
    // Note: [ 07 / 20 / 2018]
    // 1. Make  an array of game saves index of 3. (To replace list) 
    // 2. Create definition for overwritesave()??
    // 3. Rewrite definitions Save/Load/Delete to work with an array
    // 4. Start working on custom GUI

public static List<Game> savedGames = new List<Game>(3);

public static void Save()
{
    savedGames.Add(Game.current);
    BinaryFormatter bf = new BinaryFormatter();
    FileStream file = File.Create(Application.persistentDataPath + 
    "/savedGames.gd");
    Debug.Log("The file is saved at " + Application.persistentDataPath);
    bf.Serialize(file, savedGames);
    file.Close();
}

public static void Load()
{
    if (File.Exists(Application.persistentDataPath + "/savedGames.gd"))
    {
        BinaryFormatter bf = new BinaryFormatter();
        FileStream file = File.Open(Application.persistentDataPath + 
        "/savedGames.gd", FileMode.Open);
        Debug.Log("The File is loaded from " + 
        Application.persistentDataPath);
        savedGames = (List<Game>)bf.Deserialize(file);
        file.Close();
    }
}

public static void DeleteSave(int index) {

    if (File.Exists(Application.persistentDataPath + "/savedGames.gd"))
    {
        BinaryFormatter bf = new BinaryFormatter();
        FileStream file = File.Open(Application.persistentDataPath + 
        "/savedGames.gd", FileMode.Open);
        savedGames = (List<Game>)bf.Deserialize(file);
        file.Close();
    }

    savedGames.RemoveAt(index); 
    // Removes element in List from the passed Index

    BinaryFormatter bf2 = new BinaryFormatter();
    FileStream file2 = File.Create(Application.persistentDataPath + 
    "/savedGames.gd"); //you can call it anything you want
    Debug.Log("Save file has been Updated at " + 
    Application.persistentDataPath);
    bf2.Serialize(file2, savedGames); // Saves Changes to Data
    file2.Close();
    }
 }

這是我的GUI腳本。 我目前在列表中使用它,但是在將其與數組一起使用時也遇到了麻煩。 我需要幫助,找到一種從菜單傳遞索引值來修改數組的方法。

//<MainMenu.cs>

 using UnityEngine;
 using System;
 using UnityEngine.SceneManagement;

 public class MainMenu : MonoBehaviour {

 int index = 0;

 public enum Menu {
    MainMenu,
    NewGame,
    Continue,
    delete,
    caution
}

 public Menu currentMenu;

     void OnGUI () {

         GUILayout.BeginArea(new Rect(0,0,Screen.width, Screen.height));
         GUILayout.BeginHorizontal();
         GUILayout.FlexibleSpace();
         GUILayout.BeginVertical();
         GUILayout.FlexibleSpace();

        if(currentMenu == Menu.MainMenu) {

            GUILayout.Box("THE EIGHT");
            GUILayout.Space(10);

        if(GUILayout.Button("New Game")) {
            Game.current = new Game();
            currentMenu = Menu.NewGame;
        }

        if(GUILayout.Button("Continue")) {
            SaveLoad.Load();
            currentMenu = Menu.Continue;
        }

        if(GUILayout.Button("Delete Save")) {
            SaveLoad.Load();
            currentMenu = Menu.delete;
        }

        if(GUILayout.Button("Quit")) {
            Application.Quit();
        }
    }

    else if (currentMenu == Menu.NewGame) {

        GUILayout.Box("Name Your Characters");
        GUILayout.Space(10);

        GUILayout.Label("Some Strange Boy");
        Game.current.Nestor.name = 
        GUILayout.TextField(Game.current.Nestor.name, 20);
        GUILayout.Label("Some Strange Girl");
        Game.current.SomeGirl.name = 
        GUILayout.TextField(Game.current.SomeGirl.name, 20);
        GUILayout.Label("Some Strange Friend");
        Game.current.SomeBro.name = 
        GUILayout.TextField(Game.current.SomeBro.name, 20);

        if(GUILayout.Button("Save")) {
            //Save the current Game as a new saved Game
            SaveLoad.Save();
            //Move on to game...
            SceneManager.LoadScene(2);
        }

        GUILayout.Space(10);
        if(GUILayout.Button("Cancel")) {
            currentMenu = Menu.MainMenu;
        }

    }

    else if (currentMenu == Menu.Continue) {

        GUILayout.Box("Select Save");
        GUILayout.Space(10);

        foreach(Game g in SaveLoad.savedGames) {
            if(GUILayout.Button(g.Nestor.name + " - " + g.SomeGirl.name + " - " + g.SomeBro.name)) {
                Game.current = g;
                //Move on to game...
                SceneManager.LoadScene(2);
            }

        }

        GUILayout.Space(10);
        if(GUILayout.Button("Cancel")) {
            currentMenu = Menu.MainMenu;
        }

    }

    else if (currentMenu == Menu.delete)
    {

        GUILayout.Box("Select Save to Delete");
        GUILayout.Space(10);

        foreach (Game g in SaveLoad.savedGames)
        {
            if (GUILayout.Button(g.Nestor.name + " - " + g.SomeGirl.name + " 
            - " + g.SomeBro.name))
            {
                index = SaveLoad.savedGames.IndexOf(g);
                Debug.Log(index);
                currentMenu = Menu.caution;
            }

        }

        GUILayout.Space(10);
        if (GUILayout.Button("Cancel"))
        {
            currentMenu = Menu.MainMenu;
        }

    }
else if(currentMenu == Menu.caution) {

        GUILayout.Box("Are you sure?");
        GUILayout.Space(10);
        if (GUILayout.Button("Yes")) {
            Debug.Log(index);
            SaveLoad.DeleteSave(index);
            currentMenu = Menu.MainMenu;
        }

           GUILayout.Space(10);
            if (GUILayout.Button("No")) {
                currentMenu = Menu.delete;
            }

        }

        GUILayout.FlexibleSpace();
        GUILayout.EndVertical();
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();
        GUILayout.EndArea();

    }
}

您幾乎只需要將List<Game>演員List<Game>替換為Game[] 這是一些(未處理錯誤)示例代碼基礎結構,可幫助您入門。 提示一下,將文件/序列化代碼包裝在try使用IOExceptionSerializationException catch應該可以避免普通用戶案例場景的沖擊。 可能只想弄清楚.bin文件,看看會發生什么並測試代碼的各種特殊情況,這是值得的。

void Awake() {
    //this is an object initializer, pass your Game[] in place of this
    Save(new[] {
        new Game { propertyStub = 0 },
        new Game { propertyStub = 1 },
        new Game { propertyStub = 2 }
    });

    var gA = Load();
    if(gA == null || gA.Length > 3) throw new SerializationException("Serialize error");

    foreach (var g in gA) Debug.Log(g);
}

public static void Save(Game[] gA) {
    using (var f = File.Create(Directory.GetCurrentDirectory() + "\\sample.bin")) new BinaryFormatter().Serialize(f, gA);
}

public static Game[] Load() {
    using (var f = File.Open(Directory.GetCurrentDirectory() + "\\sample.bin", FileMode.Open)) return (new BinaryFormatter().Deserialize(f)) as Game[];
}

//Stub class used for testing purposes
[Serializable]
class Game {
    public int propertyStub { get; set; }

    public override string ToString() {
        return "propertyStub value: " + propertyStub;
    }
}

另外,值得一提的是, .net Binary序列化程序在一般情況下與其他常見序列化方法相比非常慢 ,因此,建議不要在最終版本中使用它。 其他眾所周知的序列化方法(如XMLJSON)會生成易於閱讀的輸出,並且在您不關心最終文件大小或序列化速度時也能很好地工作。 如果您確實想要速度和大小,則Google協議緩沖區(Protobuf)是一個很好的起點。

我給您的所有鏈接都包含樣板代碼復制和粘貼代碼,盡管它們最終都會序列化動態數組列表。 就像我在上面說的,簡單地將顯式強制轉換為數組不會引起任何麻煩。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM