[英]C#: How can I rewrite my code for managing Game Data Serialization using an Array instead of a List in Unity?
I am fairly new to coding and I am currently working on creating scripts to serialize data to a hard drive. 我是编码的新手,目前正在创建脚本以将数据序列化到硬盘。 I have managed to get it working with a list with the type "Game".
我设法使其与类型为“游戏”的列表一起使用。 The Game class holds data that can be serialized.
Game类保存可以序列化的数据。 I have been trying to write this code to work with an array instead that has a size of 3. Unfortunately, I have been having trouble when I run my program and try to use my GUI.
我一直在尝试编写此代码以使用大小为3的数组来代替。不幸的是,在运行程序并尝试使用GUI时遇到了麻烦。 I just need a push in the right direction for how to approach rewriting my code.
我只需要在正确的方向上推动如何重写我的代码。 I know to start with:
我知道从开始:
public static Game[] savedGames = new Game[3];
But how do I get my definitions to work with using an array instead of a list. 但是,如何使用数组而不是列表来使用定义。
//<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();
}
}
This is my script for the GUI. 这是我的GUI脚本。 I currently have it working for a list but I am having trouble using it with an array as well.
我目前在列表中使用它,但是在将其与数组一起使用时也遇到了麻烦。 I need help finding a way to pass an index value from the menu to modify an array.
我需要帮助,找到一种从菜单传递索引值来修改数组的方法。
//<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();
}
}
You pretty much only need to replace your cast of a List<Game>
to a Game[]
. 您几乎只需要将
List<Game>
演员List<Game>
替换为Game[]
。 Here's some (error unhandled) sample code infrastructure to get you started. 这是一些(未处理错误)示例代码基础结构,可帮助您入门。 As a hint, wrapping your file/serialization code in
try
, catch
with IOException
and SerializationException
should take care of the brunt of normal user case scenarios. 提示一下,将文件/序列化代码包装在
try
,使用IOException
和SerializationException
catch
应该可以避免普通用户案例场景的冲击。 It may be worth trying to mess with your .bin
files just to see what happens and test various corner case functionality of your code. 可能只想弄清楚
.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;
}
}
In addition, it's worth mentioning that the .net Binary serializer is pretty slow in comparison to other common serialization methods in general usage cases, so I advise against using it in your final builds. 另外,值得一提的是, .net Binary序列化程序在一般情况下与其他常见序列化方法相比非常慢 ,因此,建议不要在最终版本中使用它。 Other well-known serialization methods like XML and JSON generate very human readable output, and works well when you don't care about final file size, or serialization speed.
其他众所周知的序列化方法(如XML和JSON)会生成易于阅读的输出,并且在您不关心最终文件大小或序列化速度时也能很好地工作。 If you really want speed and size, the Google Protocol Buffers (Protobuf) are a good starting point.
如果您确实想要速度和大小,则Google协议缓冲区(Protobuf)是一个很好的起点。
All of the links I've given you contain boiler-plate copy and paste code, although they all end up serializing dynamic array lists. 我给您的所有链接都包含样板代码复制和粘贴代码,尽管它们最终都会序列化动态数组列表。 As I said above, simply changing the explicit casts to arrays should not cause you any headache.
就像我在上面说的,简单地将显式强制转换为数组不会引起任何麻烦。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.