如何在运行时保存和更新“.xml”文件?

How to save and update ".xml" file at runtime?

我正在开发一个游戏项目,我们将玩家收集的物品保存到 .xml 文件中,我们这样做是为了跟踪玩家的开发过程。例如,您要进入地牢杀死敌人。在你杀死敌人后,游戏会掉落随机物品,如果你想将该物品添加到你的库存中,你只需点击它即可。这就是问题发生的地方。将新项目保存到 xml 文档的功能工作正常,但如果我手动刷新 xml 页面或重新启动游戏,它只会添加收集的项目。 (在这种情况下我们不想要)有什么方法或解决方法可以让我更新 xml 文档并在游戏 运行 时保存它?

我试图通过使用 "XmlTextWriter" class 来解决这个问题,但它最终从数据库中删除了所有项目并开始重新插入所有项目。 这让我想到了性能。

这是将新项目保存到数据库的函数。 "ContentDataCarrier" 是 class,其中包含有关项目的信息。 (ID, Name, Effects, SellPrice 等)

 public void AddItemToDatabase(ContentDataCarrier contentDataCarrier)
 {
            var databaseDocument = new XmlDocument();

            // Load the database XML document with the file path.
            // Note: We need to make sure if "AssetDatabase.GetAssetPath()" function also works at runtime. 
            databaseDocument.Load(AssetDatabase.GetAssetPath(_itemProgressDatabase));

            // Now create new nodes for each property that "contentDataCarrier" has.
            XmlNode itemWrapperNode = databaseDocument.CreateElement("item");

            XmlNode idNode = databaseDocument.CreateElement("ID");
            idNode.InnerText = LastAddedItemID++.ToString();

            XmlNode levelNode = databaseDocument.CreateElement("level");
            levelNode.InnerText = contentDataCarrier.Level.ToString();

            XmlNode nameNode = databaseDocument.CreateElement("name");
            nameNode.InnerText = contentDataCarrier.Name; 

            XmlNode descriptionNode = databaseDocument.CreateElement("description");
            descriptionNode.InnerText = contentDataCarrier.Description;

            XmlNode spriteNode = databaseDocument.CreateElement("sprite");
            spriteNode.InnerText = "null"; // Somehow find a way to save sprite id and load it into game.

            XmlNode qualityNode = databaseDocument.CreateElement("quality");
            qualityNode.InnerText = contentDataCarrier.Quality.ToString();

            XmlNode slotTypeNode = databaseDocument.CreateElement("slotType");
            slotTypeNode.InnerText = contentDataCarrier.SlotType.ToString();

            XmlNode sellPriceNode = databaseDocument.CreateElement("sellPrice");
            sellPriceNode.InnerText = contentDataCarrier.SellPrice.ToString();

            XmlNode buyPriceNode = databaseDocument.CreateElement("buyPrice");
            buyPriceNode.InnerText = contentDataCarrier.BuyPrice.ToString();

            XmlNode sellableNode = databaseDocument.CreateElement("sellable");
            sellableNode.InnerText = contentDataCarrier.Sellable.ToString();

            XmlNode droppedFromEnemyNode = databaseDocument.CreateElement("droppedFromEnemy");
            droppedFromEnemyNode.InnerText = contentDataCarrier.DroppedFromEnemy.ToString();

            XmlNode itemEffectsListNode = databaseDocument.CreateElement("effects");
            AddItemEffectsToDatabase(databaseDocument, itemEffectsListNode, contentDataCarrier.ItemEffects);

            // Save the new item.
            itemWrapperNode.AppendChild(idNode);
            itemWrapperNode.AppendChild(levelNode);
            itemWrapperNode.AppendChild(nameNode);
            itemWrapperNode.AppendChild(descriptionNode);
            itemWrapperNode.AppendChild(spriteNode);
            itemWrapperNode.AppendChild(qualityNode);
            itemWrapperNode.AppendChild(slotTypeNode);
            itemWrapperNode.AppendChild(sellPriceNode);
            itemWrapperNode.AppendChild(buyPriceNode);
            itemWrapperNode.AppendChild(sellableNode);
            itemWrapperNode.AppendChild(droppedFromEnemyNode);
            itemWrapperNode.AppendChild(itemEffectsListNode);

            databaseDocument.DocumentElement.InsertAfter(itemWrapperNode, 
            databaseDocument.DocumentElement.LastChild);


     databaseDocument.Save(AssetDatabase.GetAssetPath(_itemProgressDatabase));
}

我希望在运行时将玩家收集的物品保存到 xml 文件。

我终于找到了让它工作的方法。我只是像@derHugo 建议的那样使用了 XMLSerializer。 使用 XMLSerializer,我可以随时从“.xml”文件中保存和获取数据。

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

[DisallowMultipleComponent]
internal sealed class XMLManager : MonoBehaviour
{
    public ItemDatabase ItemDatabase = new ItemDatabase();

    public void SaveItem()
    {
        var xmlSerializer = new XmlSerializer(typeof(ItemDatabase));
        var fileStream = new FileStream(Application.dataPath + "/StreamingFiles/XML/Items.xml", FileMode.Create);

        xmlSerializer.Serialize(fileStream, ItemDatabase);

        fileStream.Close();
    }

    public void LoadItem()
    {
        var xmlSerializer = new XmlSerializer(typeof(ItemDatabase));
        var fileStream = new FileStream(Application.dataPath + "/StreamingFiles/XML/Items.xml", FileMode.Open);

        ItemDatabase = xmlSerializer.Deserialize(fileStream) as ItemDatabase;

        fileStream.Close();
    }
}

[System.Serializable]
public sealed class Item
{
    public string Name;
    public string Description;
    public int Damage;
    public Source Element;

    public enum Source { Fire, Water, Air };
}

[System.Serializable]
public sealed class ItemDatabase
{
    public List<Item> items = new List<Item>();
}

这是适合我的代码。

希望这对外面的人有所帮助。

谢谢。