Я хочу сохранить объекты на сцене, как Minecraft - PullRequest
0 голосов
/ 17 февраля 2019

В Minecraft сохранено местоположение множества блоков.

Я попробую это по-своему, используя PlayerPrefs.

int i, ObjectType;
Vector3 Pos;

// ObjectType is a block ID such as grass block or iron block in Minecraft.
// Pos is a position of each blocks

PlayerPrefs.SetString("object" + i, ObjectType + ", " + Pos); 

Однако при обработке сотен данныхБыло сказано, что PlayerPrefs не может быть рекомендован. Я знаю только сохранение данных в PlayerPrefs.

Что мне делать в таких случаях?

Ответы [ 2 ]

0 голосов
/ 18 февраля 2019

Я бы рекомендовал использовать, например, файл XML для хранения всей структуры ваших данных

Блок : для хранения данных одного блока.Вы можете расширить это по желанию, например, с помощью перечисления BlockType или цвета материала и т. Д. (Все, что можно сериализовать)

using System;
using System.Xml.Serialization;
using UnityEngine;

[Serializable]
public class Block
{
    [XmlAttribute] public string Name;
    [XmlElement] public Vector3 Position;

    // for the serializer a parameter-free default constructor is mandatory
    public Block() { }

    public Block(string name, Vector3 position)
    {
        Name = name;
        Position = position;
    }
}

BlocksData : для хранения данных всех блоков и обработкиXML-файл IO

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using UnityEngine;

[XmlRoot("BlocksData")]
[Serializable]
public class BlocksData
{
    [XmlArray]
    [XmlArrayItem]
    public List<Block> Blocks = new List<Block>();

    public void Save(string filePath)
    {
        var serializer = new XmlSerializer(typeof(BlocksData));
        using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
        {
            serializer.Serialize(stream, this);
        }
    }

    public static BlocksData Load(string filePath)
    {
        if (!File.Exists(filePath))
        {
            Debug.LogWarning("File not found: " + filePath);
        }

        var serializer = new XmlSerializer(typeof(BlocksData));
        using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            return serializer.Deserialize(stream) as BlocksData;
        }
    }
}

И, наконец, класс контроллера, который использует этот BlocksData и что-то с ним делает.Например,

using System.Collections.Generic;
using System.IO;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;

public class BlocksController : MonoBehaviour
{
    private const string FILE_EXTENSION = ".xml";

    // fileName of the XML file (without extension)
    public string FileName;

    // prefab to be spawned for each block
    public GameObject BlockPrefab;

    // blocks in the scene
    public List<Transform> SceneBlocks;

    // blocks in the data
    public BlocksData BlocksData;

    private static string Folder
    {
        get
        {
#if UNITY_EDITOR
            return Application.streamingAssetsPath;
#else
            return Application.persistentDataPath;
#endif
        }
    }

    private string FilePath
    {
        get
        {
            return Path.Combine(Folder, FileName + FILE_EXTENSION);

        }
    }

    [ContextMenu("Load Blocks")]
    public void LoadBlocks()
    {
        // Load from file
        BlocksData = BlocksData.Load(FilePath);

        // remove current scene blocks
        foreach (var sceneBlock in SceneBlocks)
        {
            // Have to se destroyImmediate in editmode
            if (Application.isEditor && !Application.isPlaying)
            {
                DestroyImmediate(sceneBlock.gameObject);
            }
            else
            {
                Destroy(sceneBlock.gameObject);
            }
        }

        // instantiate and setup prefab foreach block in data
        foreach (var block in BlocksData.Blocks)
        {
            var newBlock = Instantiate(BlockPrefab, block.Position, Quaternion.identity, transform);
            newBlock.name = block.Name;

            // don't forget to add it to the list of sceneBlocks
            SceneBlocks.Add(newBlock.transform);
        }
    }

    [ContextMenu("Save Blocks")]
    public void SaveBlocks()
    {
        // clear current data list
        BlocksData.Blocks.Clear();

        // add a block data foreach block in scene
        foreach (var sceneBlock in SceneBlocks)
        {
            BlocksData.Blocks.Add(new Block(sceneBlock.name, sceneBlock.position));
        }

        // finally write to file
        BlocksData.Save(FilePath);

#if UNITY_EDITOR
        AssetDatabase.Refresh();
#endif
    }
}

см. Сохранение и загрузка данных: XmlSerializer для получения более подробной информации.

0 голосов
/ 17 февраля 2019

PlayerPrefs предназначен для хранения и доступа к настройкам игрока между игровыми сессиями, такими как настройки.Вы можете использовать его только для сохранения типов данных string, int или float.Да, он не должен использоваться для хранения большого количества данных, как вы хотите.Что если вы решите добавить больше уровней?В итоге вы получите все уровни, настройки и другую игровую информацию в одном объекте словаря PlayerPrefs, который сложно поддерживать, неэффективно и легко изменить для ваших пользователей.

Вы должны создать класс / структуру с информацией об уровне, списком блочных объектов и т. Д., А затем сериализовать объект в двоичный файл, который можно сохранить на локальном устройстве в виде файла или передать на онлайн-сервер.Я предлагаю посмотреть этот учебник по Unity Live Session: Постоянство - сохранение и загрузка данных для начинающих.

Вы также можете хранить свои игровые данные в базе данных локально или онлайн.

...