如何将 3 维数组保存到文件中并稍后加载

How can I save 3-dimension array into file and load later

我正在尝试保存 3D 数组 具有使用 Unity 的块的位置数据,但我找不到如何保存它。

public class Block
{
    public Vector3 position;
    public short blockType;
    public byte facing;

    public Block(Vector3 pos, short t, byte f)
    {
        position = pos;
        blockType = t;
        facing = f;
    }
}

这是我存储区块信息的区块class。

public Block[,,] WorldBlock = new Block[100, 10, 100];

这是我要保存的数组,里面有 100000 个块。

有很多方法可以解决这个问题。

一种方法是,例如是 Newtonsoft JSON(在最新的 Unity 版本中作为 package via the PackageManager 甚至 pre-installed)

using Newtonsoft.Json;

....

public Block[,,] WorldBlock = new Block[100, 10, 100];

private string filePath => Path.Combine(Application.persistentDataPath, "example.json");

private void Save()
{
    var json = JsonConvert.SerializeObject(WorldBlock);
    
    File.WriteAllText(filePath, json);
}

private void Load()
{
    if (File.Exists(filePath))
    {
        var json = File.ReadAllText(filePath);
        WorldBlock = JsonConvert.DeserializeObject<Block[,,]>(json);
    }

    var block = WorldBlock[1, 2, 3];
    Debug.Log($"{block.position} - {block.blockType} - {block.facing}");
}

或者 - 因为 JSON 为你的用例浪费了很多字符 space - 你也可以实现你自己的二进制序列化,例如使用BinaryReader and BinaryWriter

例如

[Serializable]
public class Block
{
    public Vector3 position;
    public short blockType;
    public byte facing;

    public Block(Vector3 pos, short t, byte f)
    {
        position = pos;
        blockType = t;
        facing = f;
    }

    public void Serialize(BinaryWriter writer)
    {
        writer.Write(position.x);
        writer.Write(position.y);
        writer.Write(position.z);
        
        writer.Write(blockType);
        
        writer.Write(facing);
    }

    public void Deserialize(BinaryReader reader)
    {
        position. x = reader.ReadSingle();
        position. y = reader.ReadSingle();
        position. z = reader.ReadSingle();

        blockType = reader.ReadInt16();
        
        facing = reader.ReadByte();
    }
}

然后

private void Save()
{
    using (var stream = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.Write))
    {
        using (var writer = new BinaryWriter(stream))
        {
            // first store the size of each dimension
            for (var i = 0; i < WorldBlock.Rank; i++)
            {
                writer.Write(WorldBlock.GetLength(i));
            }
            
            // then serialize all blocks
            for (var i = 0; i < WorldBlock.GetLength(0); i++)
            {
                for (var j = 0; j < WorldBlock.GetLength(1); j++)
                {
                    for (var k = 0; k < WorldBlock.GetLength(2); k++)
                    {
                        var block = WorldBlock[i, j, k];
                        block.Serialize(writer);
                    }
                }
            }
        }
    }
}

private void Load()
{
    if (File.Exists(filePath))
    {
        using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read))
        {
            using (var reader = new BinaryReader(stream))
            {
                // first get th size of each dimension
                var x = reader.ReadInt32();
                var y = reader.ReadInt32();
                var z = reader.ReadInt32();

                WorldBlock = new Block[x, y, z];

                // then deserialize all blocks
                for (var i = 0; i < WorldBlock.GetLength(0); i++)
                {
                    for (var j = 0; j < WorldBlock.GetLength(1); j++)
                    {
                        for (var k = 0; k < WorldBlock.GetLength(2); k++)
                        {
                            var block = new Block();
                            block.Deserialize(reader);

                            WorldBlock[i, j, k] = block;
                        }
                    }
                }
            }
        }
    }

    var exampleBlock = WorldBlock[1, 2, 3];
    Debug.Log($"{exampleBlock.position} - {exampleBlock.blockType} - {exampleBlock.facing}");
}