我希望用户能够在应用程序中创建网格样式的“地图”,将其保存到磁盘,然后与其他人共享。在基本的地图数据中,我希望用户输入他们的姓名,以便“声明”他们的作品。
为了更加安全,我正在考虑将地图类(带有艺术家名称,地图尺寸,其他有用的选项以及flat / 2D数组/列表[根据需要删除])保存为二进制。因此,XML(人类可读)可能不是我要使用的东西……但是我还没有完全反对XML,只是谨慎地停止“窃取”。
我一直在使用BinaryFormatter.Serialize方法,但是随着我的tiledata大小从200 * 200瓦片增加到300 * 300瓦片,反序列化所需的时间从6.5秒增加到33秒,并且继续增加以指数方式。
理想情况下,我希望能够存储2000 * 2000的地图数据。
因此,除了学习压缩技术(无论如何我都会做以减小文件大小)之外,我还在想是否建议使用其他序列化器。我已经看到有一些第三方软件可用,但是需要弄清楚它们是否与Unity兼容(是的。我是一个自学成才的noob gamedev)。
任何帮助将不胜感激。
为清晰起见,添加了当前测试代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
public class FileReaderTest : MonoBehaviour
{
public int xlimit = 300;
public int ylimit = 300;
// Use this for initialization
void Start()
{
Save();
}
// Update is called once per frame
void Update()
{
if (Input.anyKeyDown)
Load();
}
private void Save()
{
BinaryFormatter formatter = new BinaryFormatter();
FileStream file = File.Open(Application.dataPath + "/saved.data", FileMode.OpenOrCreate);
List<TestDataBaseEntry> mapTileData = new List<TestDataBaseEntry>();
List<TestDataBaseEntry> extraMapTileData = new List<TestDataBaseEntry>();
for (int x = 0; x < xlimit; x++)
{
for (int y = 0; y < ylimit; y++)
{
// Simulating random data
mapTileData.Add(new TestDataBaseEntry(TileState.Filled, x, y));
}
}
for (int x = 0; x < 5; x++)
{
for (int y = 0; y < 3; y++)
{
extraMapTileData.Add(new TestDataBaseEntry(TileState.Ignore, x, y));
}
}
TestMapFile newFile = new TestMapFile("Mike", xlimit, ylimit, mapTileData, extraMapTileData);
formatter.Serialize(file, newFile);
file.Close();
Debug.Log("saved");
}
private void Load()
{
float starttime = Time.realtimeSinceStartup;
if (File.Exists(Application.dataPath + "/saved.data"))
{
using (FileStream file = File.Open(Application.dataPath + "/saved.data", FileMode.Open))
{
BinaryFormatter formatter = new BinaryFormatter();
TestMapFile retrievedTestMapFile = (TestMapFile) formatter.Deserialize(file);
}
}
Debug.Log("Loaded");
Debug.Log("The process took " + (Time.realtimeSinceStartup - starttime));
}
}
[Serializable]
public class TestDataBaseEntry
{
public TileState tileState;
public int x;
public int y;
public TestDataBaseEntry(TileState newTileState, int newX, int newY)
{
tileState = newTileState;
x = newX;
y = newY;
}
}
[Serializable]
public class TestMapFile
{
public int xSize;
public int ySize;
public List<TestDataBaseEntry> mapTileData = new List<TestDataBaseEntry>();
public List<TestDataBaseEntry> mapExtraTileData = new List<TestDataBaseEntry>();
public string createdBy;
public TestMapFile(string artist, int newXSize, int newYSize, List<TestDataBaseEntry> newDB, List<TestDataBaseEntry> newExtraDB)
{
createdBy = artist;
xSize = newXSize;
ySize = newYSize;
mapTileData = newDB;
mapExtraTileData = newExtraDB;
}
}
答案 0 :(得分:0)
看一下protobuf-net。它不是那么易读,相当快并且占用更少的磁盘空间。 https://github.com/mgravell/protobuf-net
答案 1 :(得分:0)
好吧,我从Unity论坛上的上一篇帖子中获得了建议,并考虑了这里所说的一些观点,并创建了一些测试脚本-这是我的发现。
首先,在评论中提到的@Scott Hannen之后(在forum.Unity.com上一篇文章中也提到过),我尝试制作自己的de / serializer,我剥离了要放入的信息进入文件(并从文件中读取),并将时间缩短至0.13秒,以获取足够的信息来重新创建1920 * 1080尺寸的地图的地形。我正在使用的数据只是一个字符串,2个整数和一组布尔值。
因此,我然后回头再次查看BinaryFormatter。为了使比较彼此直接进行,我必须解决的最大区别是将自定义类TestDataBaseEntry的列表更改为bool数组(这是我在binarywriter中使用的数组)。仅此一项,就使读取文件的时间从300 * 300的地图大小的33.3秒减少到1920 * 1080的地图大小的11.1!巨大的改进-我猜想BinaryFormatter的某些过程需要进行大量的背景检查和错误检查?
所以它仍然不如我剥离的自定义序列化器快。但是,这仍然不是一个真正的比较,因为我仍在使用BinaryFormatter反序列化实际的类,而我正在使用BinaryWriter / BinaryReader分别反序列化该类的组件。
所以我还有更多测试要做,但是到目前为止,对我来说,解决方案似乎是使我要写入文件的信息不复杂,并删除尽可能多的自定义类型(?)。很有可能我从中读到了错误的答案...但是我会继续研究,看看能做什么。
非常感谢所有答复并提供其他途径供我研究的人。我仍将进一步研究这些知识,以扩展我的知识...加上其中之一(如protobuf-net)可能仍然是实施的更好解决方案;)
再次,谢谢。以后。
更新-第二天早上...
因此,我进行了另一项测试,这次将定制类完全剥离,并直接在文件中直接对相关部分进行序列化和反序列化。现在,BinaryFormatter不必在可序列化的自定义类中处理它了,我现在获得的读取时间为0.15秒-就像我在使用自己的自定义序列化器一样。
因此,我在您的所有帮助下都学到了非常有价值的东西-序列化基本类型而不是自定义类!
再次,非常感谢;)